Search Unity

Raycast Miss, How to run ComponentSystem after subscene is loaded?

Discussion in 'Physics for ECS' started by entropin_unity, Jan 11, 2020.

  1. entropin_unity

    entropin_unity

    Joined:
    Dec 31, 2019
    Posts:
    1
    Hi, I have a basic system that creates a grid of cubes, before every cube is instantiated, I would like to do a RayCast to determine the Y coordinate to place the box. But the raycast only returns a hit after a few seconds, the first time the system runs it can't find any colliders, so I'm guessing that the system is run before the subscene is created so i can't find the floor colliders.

    How can I fix this?

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.Physics;
    4. using Unity.Physics.Systems;
    5. using Unity.Transforms;
    6. using UnityEngine;
    7.  
    8. public struct RotateTractorInfo : IComponentData
    9. {
    10.     public float Speed;
    11.     public Vector3 lastKnownLocation;
    12.     public Vector3 teleportPoss;
    13. }
    14.  
    15. [UpdateAfter(typeof(RequestSceneLoaded))]
    16. public class RotateTractorSpawnerSystem : ComponentSystem
    17. {
    18.     // Start is called before the first frame update
    19.     void Start()
    20.     {
    21.  
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void Update()
    26.     {
    27.  
    28.     }
    29.  
    30.     protected override void OnUpdate()
    31.     {
    32.  
    33.         var collisionWorld = World.GetOrCreateSystem<BuildPhysicsWorld>().PhysicsWorld.CollisionWorld;
    34.  
    35.         float horizone = 2.0f;
    36.         float spacing  = 4.0f;
    37.         Entities.ForEach((Entity entity, ref RotateTractorInitData spawnerData) =>
    38.         {
    39.             float spaceStepsX = 0;
    40.             float spaceStepsZ = 0;
    41.             for (int x = 0; x < spawnerData.NumXCubes; ++x)
    42.             {
    43.                 float posX = spaceStepsX - (spawnerData.NumXCubes / 2);
    44.                 spaceStepsX += spacing;
    45.  
    46.                 spaceStepsZ = 0;
    47.                 for (int z = 0; z < spawnerData.NumZCubes; ++z)
    48.                 {
    49.                     float posZ = spaceStepsZ - (spawnerData.NumZCubes / 2);
    50.                     spaceStepsZ += spacing;
    51.                     // Actually create a rotating cube entity from the prefab.
    52.                     var rotatingCubeEntity = EntityManager.Instantiate(spawnerData.RotatingCubePrefabEntity);
    53.  
    54.                     var initPosition = new float3(posX, horizone, posZ);
    55.                     var adjustedPosition = adjustForGroundLevel(collisionWorld, initPosition);
    56.  
    57.                     // Set the position of the rotating cube.
    58.                     EntityManager.SetComponentData(rotatingCubeEntity, new Translation { Value = adjustedPosition });
    59.                     EntityManager.AddComponentData(rotatingCubeEntity, new RotateTractorInfo { Speed = spawnerData.RotationSpeed, lastKnownLocation = new float3(0f, 0f, 0f) });
    60.                     EntityManager.AddComponentData(rotatingCubeEntity, new Tractorbeam.Information { TractorLocation = new Vector3(posX, horizone, posZ) });
    61.                 }
    62.             }
    63.  
    64.             // We should destroy this spawner entity because if we don't, the spawner will run again on the next frame
    65.             // and spawn another NumCubes rotating cubes!
    66.             EntityManager.DestroyEntity(entity);
    67.         });
    68.     }
    69.  
    70.     float3 adjustForGroundLevel(CollisionWorld collisionWorld, float3 poss)
    71.     {
    72.         float3 aimDir = new float3(0f, -1f, 0f);
    73.         float beamDistance = 100f;
    74.  
    75.  
    76.         var staticGeomFilter = CollisionFilter.Default;
    77.         staticGeomFilter.CollidesWith = 1 << 0;
    78.  
    79.         var closestHit = new Unity.Physics.RaycastHit();
    80.         RaycastInput castInput = new RaycastInput
    81.         {
    82.             Start = poss,
    83.             End = poss + aimDir * beamDistance,
    84.             Filter = CollisionFilter.Default
    85.         };
    86.  
    87.  
    88.             if (collisionWorld.CastRay(castInput, out closestHit))
    89.             {
    90.             //Dose not hit here unit a few hundred loops
    91.             return closestHit.Position;
    92.         }
    93.  
    94.         return poss;
    95.     }
    96. }