Search Unity

  1. Want to see 2020.1b in action? Sign up for our Beta 2020.1 Overview Webinar on April 20th for a live presentation from our evangelists and a Q&A session with guests from R&D.
    Dismiss Notice
  2. Interested in giving us feedback? Join our online research interviews on a broad range of topics and share your insights with us.
    Dismiss Notice
  3. We're hosting a webinar for the new Input System where you'll be able to get in touch with the devs. Sign up now and share your questions with us in preparation for the session on April 15.
    Dismiss Notice
  4. Dismiss Notice

[Unity.Physics]PhysicsVelocity does not reflect the current velocity of the Physics Body

Discussion in 'Data Oriented Technology Stack' started by migueln6, Jan 21, 2020.

  1. migueln6

    migueln6

    Joined:
    Jun 4, 2017
    Posts:
    2
    Hello.

    I have been playing with ECS and now I'm transfering that to Unity.Physics. I tried to ask this in the discord server but didn't got much help there, lets continue with the issue.

    Actually I'm spawning an Entity from a prefab, no issue here; It has a PhysicsBody and PhysicsShape, I do set the initial velocity with PhysicsVelocity heres the code related to this:
    Code (CSharp):
    1. Using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Entities;
    5. using Unity.Transforms;
    6. using Unity.Physics;
    7. using Unity.Mathematics;
    8.  
    9. namespace Systems
    10. {
    11.     [UpdateAfter(typeof(Input))]
    12.     public class InputMainAttackProcess : ComponentSystem
    13.     {
    14.         protected override void OnUpdate()
    15.         {
    16.             var input = this.GetSingleton<Components.InputSingleton>();
    17.  
    18.             if (input.fire1)
    19.             {
    20.                 Entities.ForEach((ref Components.Prefabs.BulletAuthoring bulletAuthoring, ref LocalToWorld location, ref Components.VectorToMouse vectorToMouse) =>
    21.                 {
    22.                     var instance = EntityManager.Instantiate(bulletAuthoring.prefabEntity);
    23.                     float3 vel = math.normalize(vectorToMouse.Value) * bulletAuthoring.speed;
    24.                     Debug.Log(string.Format("vel: {0}", vel));
    25.                     float time = bulletAuthoring.attackRange / bulletAuthoring.speed;
    26.                    
    27.  
    28.                     EntityManager.SetComponentData(instance, new Translation { Value = location.Position });
    29.                     EntityManager.SetComponentData(instance, new PhysicsVelocity { Linear = vel });
    30.                     EntityManager.SetComponentData(instance, new Components.LifeTime { Value = time, Counting = true });
    31.                 });
    32.             }
    33.         }
    34.     }
    35. }
    So far this works, the issue arises when the Entity is created and moved by BuildPyshicsWorldSystem, as you can se from the instantiation code the Entity is asignated a life time so it travels at max attackRange with certain velocity, but for some reason it does past that expected point.

    I have seen that sometimes the entity is destroyed a bit earlier or a bit later (but never before the expected destroy distance). Here is in fact the code in charge of that(if you look at the github ignore the other methods they are a residue of when i tried to do the destroy in a Job, way easier to handle in concurrent SystemComponent):
    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Physics;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Components;
    6. using Unity.Collections;
    7. using Unity.Physics.Systems;
    8. using Unity.Burst;
    9.  
    10. namespace Systems
    11. {
    12.     [UpdateAfter(typeof(EndFramePhysicsSystem))]
    13.     public class DestroyOnTimer : ComponentSystem
    14.     {
    15.      
    16.         [BurstCompile]
    17.         protected override void OnUpdate()
    18.         {
    19.             float deltaTime = Time.DeltaTime;
    20.             Entities.ForEach((Entity ent, ref LifeTime time) =>
    21.             {
    22.                 if (time.Counting)
    23.                 {
    24.                     if (time.Value <= 0)
    25.  
    26.                         EntityManager.DestroyEntity(ent);
    27.                     else
    28.                     {
    29.                         //Debug.Log("Current: " + time.Value + " delta:" + deltaTime);
    30.                         time.Value -= deltaTime;
    31.                     }
    32.                 }
    33.             });
    34.         }
    35.     }
    36.  
    37. }
    Here I provide a working project with the issue https://github.com/EngHell/Unity-ECS-TEST

    Steps to Reproduce:
    1. Hit Play
    2. Click above the cube to the right (it's set at exactly 10 units from the spawn position)
    3. You should see how the spawned entity goes far beyond the 10 units(if you check the code, the entity is asigned a life time of 2 seconds a velocity with magnitude of 5 units)
    Im pretty sure this should be a mistake on my side by how i did setup things, but I can't get to find the error, any help would be valuable.


    Thanks.
     
  2. migueln6

    migueln6

    Joined:
    Jun 4, 2017
    Posts:
    2
    Quoting drUiD from the discord server:
    Code (CSharp):
    1. ///#if !UNITY_DOTSPLAYER
    2. ///           float timeStep = UnityEngine.Time.fixedDeltaTime;
    3. ///#else
    4.             float timeStep = Time.DeltaTime;
    5. ///#endif
    This fixed the issue, in case anyone happens to need an answer in the future, but this change will be reverted each time you open the project, so you must make the package local by copying it from Lybrary/PackageCache to Packages
     
  3. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    117
    You can also force the Step Physics World system into updating with fixed update:

    Code (CSharp):
    1.     public class PhysicsUpdateController : MonoBehaviour
    2.     {
    3.         public bool autoUpdateStepPhysicsWorld = false;
    4.  
    5.         public bool fixedUpdateStepPhysicsWorld = true;
    6.  
    7.         int framesUntilTicks = 0;
    8.  
    9.         private void Update()
    10.         {
    11.             if (!fixedUpdateStepPhysicsWorld || autoUpdateStepPhysicsWorld)
    12.             {
    13.                 EnableStepPhysicsWorld(autoUpdateStepPhysicsWorld);
    14.             }
    15.  
    16.             if (fixedUpdateStepPhysicsWorld && !autoUpdateStepPhysicsWorld && framesUntilTicks == 0)
    17.             {
    18.                 EnableStepPhysicsWorld(false);
    19.             }
    20.  
    21.             framesUntilTicks--;
    22.         }
    23.  
    24.         private void FixedUpdate()
    25.         {
    26.             if (fixedUpdateStepPhysicsWorld && !autoUpdateStepPhysicsWorld)
    27.             {
    28.                 EnableStepPhysicsWorld(true);
    29.  
    30.                 framesUntilTicks = 1;
    31.             }
    32.         }
    33.  
    34.         internal void EnableStepPhysicsWorld(bool active)
    35.         {
    36.             var worlds = World.AllWorlds;
    37.  
    38.             if (worlds == null)
    39.             {
    40.                 return;
    41.             }
    42.  
    43.             int index;
    44.  
    45.             for (index = 0; index < worlds.Count; index++)
    46.             {
    47.                 var stepPhysicsWorld = worlds[index].GetExistingSystem<StepPhysicsWorld>();
    48.  
    49.                 if (stepPhysicsWorld == null)
    50.                 {
    51.                     continue;
    52.                 }
    53.  
    54.                 stepPhysicsWorld.Enabled = active;
    55.             }
    56.         }
    57.     }
     
unityunity