Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Foulcloud · Aug 06, 2020 at 05:00 AM · general

How can I optimize this burst compiled job for better performance than regular method on main thread?

I have converted one of my AI functions to a burst compiled job. However, the performance is slightly worse than regular method running on main thread. I have 200 agents using this when testing, so not a lot but more than a few.

First, I have an interface that simulates an "EarlyFixedupdate". This is achieved using script execution order and a simple component that I can add to any GameObject.. I use this same method to provide an "EarlyOnAnimatorIKUpdate". I use this to batch a bunch of sphere casts I need in the animator to place feet and works great. Noticeable performance gains and simple to implement.

 public interface IEarlyFixedUpdate
 {
     void EarlyFixedUpdate();
 }
 
 public class EarlyFixedUpdateHandler : MonoBehaviour
 {
     IEarlyFixedUpdate earlyFixedUpdate;
     private void Awake()
     {
         earlyFixedUpdate = GetComponent<IEarlyFixedUpdate>();
     }
     public void FixedUpdate()
     {
         earlyFixedUpdate.EarlyFixedUpdate();
     }
 }

This is the job:

 [BurstCompile]
 public struct AIMoveJob : IJob
 {
     public float3 myPosition;
     public float fixedDeltaTime;
     public float3 transformForward;
     public float3 usingSlopeNormal;
     public bool walkBackwards;
     public float3 globalVelocity;
     public float acceleration;
     public bool leadTargetWhenClose;
     public bool validTarget;
     public bool targetIsClose;
     public bool targetPathClear;
     public bool moveAwayFromTarget;
     public float targetIsCloseDistance;
     public float targetDistance;
     public float rotateForce;
     public float torqueClamp;
     public float speedDampingLowerLimit;
     public float rotationDampingLowerLimit;
     public float rotationDampingFromSpeed;
     public float speedDampingFromRotation;
     public float originalMaxSpeed;
     public quaternion dotRot90;
     // Results
     public NativeArray<float3> resultSimulatedVelocity;
     public NativeArray<float3> resultNextPosition;
     public NativeArray<float> resultTorqueDelta;
     public NativeArray<float> resultMaxSpeed;
 
     public void Execute()
     {
         float moveSpeed;
         float3 moveVelocity;
         // Position
         moveSpeed = math.min(math.length(myPosition - resultNextPosition[0]) / fixedDeltaTime, 
         resultMaxSpeed[0]);
         moveVelocity = Util.ProjectOnPlane(transformForward * moveSpeed, usingSlopeNormal);
         if (walkBackwards) moveVelocity = -moveVelocity;
         resultSimulatedVelocity[0] = moveVelocity - globalVelocity;
         // Clamp the velocity
         if (math.length(resultSimulatedVelocity[0]) > acceleration * fixedDeltaTime) {
             resultSimulatedVelocity[0] = math.normalize(resultSimulatedVelocity[0]) * acceleration * fixedDeltaTime;
         }
         // Lead the target one frame
         if (leadTargetWhenClose && validTarget && targetIsClose && targetPathClear && !moveAwayFromTarget) {
             float leadStrength = math.sqrt((targetIsCloseDistance - targetDistance) / targetIsCloseDistance);
             resultNextPosition[0] += (globalVelocity * fixedDeltaTime * leadStrength);
         }
         // Rotation
 
             float dotProduct = math.dot(math.mul(dotRot90, math.normalize(resultNextPosition[0] - myPosition)), transformForward);
             if (walkBackwards) dotProduct = -dotProduct;
             resultTorqueDelta[0] = math.clamp(dotProduct * rotateForce * fixedDeltaTime, -torqueClamp, torqueClamp);
             float torqueModifier = math.max(moveSpeed * rotationDampingLowerLimit, moveSpeed / (1 + rotationDampingFromSpeed));
             resultTorqueDelta[0] *= torqueModifier;
             // Slow down if turning sharply
             resultMaxSpeed[0] = math.max(speedDampingLowerLimit * originalMaxSpeed, originalMaxSpeed - (math.abs(resultTorqueDelta[0] *     speedDampingFromRotation)));
         }
     }
 

This is the code used to prepare the job. This happens in the "EarlyFixedupdate".

 void PrepareAIMoveJob()
 {
     resultSimulatedVelocity = new NativeArray<float3>(1, Allocator.TempJob);
     resultNextPosition = new NativeArray<float3>(1, Allocator.TempJob);
     resultTorqueDelta = new NativeArray<float>(1, Allocator.TempJob);
     resultMaxSpeed = new NativeArray<float>(1, Allocator.TempJob);
     //// Results
     resultSimulatedVelocity[0] = groundManager.simulatedVelocity;
     resultNextPosition[0] = nextPosition;
     resultTorqueDelta[0] = groundManager.torqueDelta;
     resultMaxSpeed[0] = richAI.maxSpeed;
 
     AIMoveJob job = new AIMoveJob()
     {
         myPosition = root.myTransform.position,
         fixedDeltaTime = Time.fixedDeltaTime,
         transformForward = root.myTransform.forward,
         usingSlopeNormal = groundManager.usingSlopeNormal,
         walkBackwards = walkBackwards,
         globalVelocity = groundManager.GlobalVelocity,
         acceleration = richAI.acceleration,
         leadTargetWhenClose = agentData.leadTargetWhenClose,
         validTarget = ValidTarget,
         targetIsClose = targetHandler ? targetHandler.TargetIsClose : false,
         targetPathClear = targetPathClear,
         moveAwayFromTarget = moveAwayFromTarget,
         targetIsCloseDistance = agentData.targetIsCloseDistance,
         targetDistance = targetHandler ? targetHandler.targetDistance : 0,
         rotateForce = agentData.rotateForce,
         torqueClamp = agentData.torqueClamp,
         speedDampingLowerLimit = agentData.speedDampingLowerLimit,
         rotationDampingLowerLimit = agentData.rotationDampingLowerLimit,
         rotationDampingFromSpeed = agentData.rotationDampingFromSpeed,
         speedDampingFromRotation = agentData.speedDampingFromRotation,
         originalMaxSpeed = originalMaxSpeed,
         dotRot90 = Util.dotRot90,
         // Results
         resultSimulatedVelocity = resultSimulatedVelocity,
         resultNextPosition = resultNextPosition,
         resultTorqueDelta = resultTorqueDelta,
         resultMaxSpeed = resultMaxSpeed
     };
     aiMoveJobHandle = job.Schedule();
     aiMoveJobPrepared = true;
 }

So in "EarlyFixedUpodate" all the jobs are prepared and scheduled. Then in regular FixedUpdate I complete the jobs and process the results. I take care to dispose of the NativeArrays wherever needed.

The results in gameplay are the same as regular method but the performance is about 2 percent worse. I am only using the Mathematics library (including the ProjectOnPlane which is a static function that uses Unity mathematics). Any Vector3 are converted to float3.

Is there something I can do to actually increase the performance like batching or some scheduling option? It might just be that my required sample size is too small or the math is just too simple to achieve any benefits.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

131 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Getter and Setter in C# 2 Answers

How do you bring your ideas to real code? 1 Answer

Unity after fixing build with error kept getting error until I changed build name 0 Answers

Unity Ads Quesition 0 Answers

I already made a ar app which deploys flag, i want to upgrade it to make the flag stay there at the exact geo location 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges