Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

Question Synchronizing entity rotation with terrain's rotation under it

Discussion in 'Physics for ECS' started by Palom-Porom, Aug 23, 2023.

  1. Palom-Porom

    Palom-Porom

    Joined:
    Sep 21, 2022
    Posts:
    51
    Hello everyone
    I am trying to make my entity (cylinder) to rotate depending on the terrain under it. So that cylinder is always standing perpendicular to the terrain. I tried to do this by using PointDistance collision query but as you can see on the video it doesn`t work as well as I want:

    For me my code seems to be logical and right (but of course it is not true if I have such issues with it):
    Code (CSharp):
    1. [UpdateBefore(typeof(MovementSystem))]
    2. public partial struct MouseTargetingUnits : ISystem
    3. {
    4.     public void OnCreate (ref SystemState state)
    5.     {
    6.         state.RequireForUpdate<MovementComponent>();
    7.     }
    8.  
    9.     public void OnUpdate(ref SystemState state)
    10.     {
    11.         if (Mouse.current.rightButton.wasPressedThisFrame && CheckCursorOnTerrain(out Unity.Physics.RaycastHit newTarget))
    12.         {
    13.             foreach (var movement in SystemAPI.Query<RefRW<MovementComponent>>())
    14.             {
    15.                 movement.ValueRW.target = newTarget.Position;
    16.             }
    17.         }
    18.     }
    19.  
    20.     private bool CheckCursorOnTerrain(out Unity.Physics.RaycastHit newTarget)
    21.     {
    22.         var collisionWorld = SystemAPI.GetSingleton<PhysicsWorldSingleton>().CollisionWorld;
    23.         UnityEngine.Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.value);
    24.         RaycastInput raycastInput = new RaycastInput
    25.         {
    26.             Start = ray.origin,
    27.             End = ray.GetPoint(1000f),
    28.             Filter = new CollisionFilter
    29.             {
    30.                 BelongsTo = ~0u,
    31.                 CollidesWith = 1u << 7,
    32.                 GroupIndex = 0
    33.             }
    34.         };
    35.         newTarget = new Unity.Physics.RaycastHit();
    36.         return collisionWorld.CastRay(raycastInput, out newTarget);
    37.     }
    38. }
    Code (CSharp):
    1. [BurstCompile]
    2. public partial struct MovementSystem : ISystem
    3. {
    4.     [BurstCompile]
    5.     public void OnCreate(ref SystemState state)
    6.     {
    7.         state.RequireForUpdate<MovementComponent>();
    8.      
    9.     }
    10.  
    11.     [BurstCompile]
    12.     public void OnUpdate(ref SystemState state)
    13.     {
    14.         var moveJob = new MovementJob { time = SystemAPI.Time.DeltaTime, collisionWorld = SystemAPI.GetSingleton<PhysicsWorldSingleton>().CollisionWorld };
    15.         JobHandle a = moveJob.Schedule(state.Dependency);
    16.         a.Complete();
    17.     }
    18.  
    19.     [BurstCompile]
    20.     public void OnDestroy(ref SystemState state)
    21.     {
    22.      
    23.     }
    24. }
    25.  
    26. [BurstCompile]
    27. public partial struct MovementJob : IJobEntity
    28. {
    29.     public float time;
    30.     public CollisionWorld collisionWorld;
    31.     public void Execute(ref LocalTransform transform, in MovementComponent movementComponent)
    32.     {
    33.         float3 tempDir = movementComponent.target - transform.Position;
    34.         tempDir.y = 0;
    35.         float3 dir = math.normalize(tempDir);
    36.  
    37.         if (math.distancesq(movementComponent.target, transform.Position) < 1f)
    38.             return;
    39.  
    40.         CollisionFilter filter = new CollisionFilter
    41.         {
    42.             BelongsTo = ~0u,
    43.             CollidesWith = 1u << 7,
    44.             GroupIndex = 0
    45.         };
    46.         float3 originPointDistance = transform.Position;
    47.         originPointDistance.y -= 1f;
    48.         var pointDistanceInput = new PointDistanceInput { Filter = filter, Position = originPointDistance, MaxDistance = 1.5f };
    49.         if (collisionWorld.CalculateDistance(pointDistanceInput, out DistanceHit closestHit))
    50.         {
    51.             transform.Position.y = closestHit.Position.y + 1;
    52.             transform.Rotation = quaternion.LookRotation(transform.Forward(), closestHit.SurfaceNormal);
    53.          
    54.         }
    55.         else
    56.         {
    57.             Debug.Log("ERROR: Terrain under unit is not found");
    58.         }
    59.      
    60.         transform.Position += dir * time * movementComponent.speed;
    61.     }
    62. }
    So what is the problem here? Also if anyone knows a better solution for that problem, I will appreciate it as well. But in any case I am interested in understanding the roots of my problem
     
    Last edited: Aug 25, 2023
  2. Palom-Porom

    Palom-Porom

    Joined:
    Sep 21, 2022
    Posts:
    51
    Here is a .unitypackage with the scene, I am talking about. Maybe this way it will be easier to understand my problem.
    If you import it, just remember to import via PackageManager as well: Entities, Entities Graphics, Input System, Terrain Tools, Unity Physics with a Custom Physics Authoring in the 'Samples'
     

    Attached Files: