Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

What do I need to do to use raycasts in edit mode(not play mode)?

Discussion in 'Physics for ECS' started by RecursiveEclipse, Aug 30, 2020.

  1. RecursiveEclipse

    RecursiveEclipse

    Joined:
    Sep 6, 2018
    Posts:
    298
    I'm trying to raycast from a system with ExecuteAlways to run in the editor, but I don't get any hits when I run the system. But if I enter play mode and trigger it, I do. The entity I'm trying to hit is in a subscene, do I need to manually run BuildPhysicsWorld or complete a handle?
     
  2. RecursiveEclipse

    RecursiveEclipse

    Joined:
    Sep 6, 2018
    Posts:
    298
    This is what I have now, if it matters, bit messy, just trying to get things to work. The mesh is set to collide with everything, and belongs to everything.

    Code (CSharp):
    1. [ExecuteAlways]
    2. [UpdateInGroup(typeof(EcoCellSystemGroup))]
    3. [UpdateAfter(typeof(WorldBoundsSystem)), UpdateAfter(typeof(BuildPhysicsWorld))]
    4. public unsafe class BuildEcoCellSystem : SystemBase {
    5.     BuildPhysicsWorld buildPhysicsWorld;
    6.     NativeHashMap<int2, Entity> ecoCells;
    7.     EntityArchetype ecoCellArchetype;
    8.     float cellSize;
    9.  
    10.     protected override void OnCreate() {
    11.         buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    12.         ecoCells = new NativeHashMap<int2, Entity>(1024, Allocator.Persistent);
    13.         ecoCellArchetype = EntityManager.CreateArchetype(typeof(IsEcoCell), typeof(WorldRenderBounds));
    14.     }
    15.  
    16.     protected override void OnDestroy() {
    17.         base.OnDestroy();
    18.         ecoCells.Dispose();
    19.     }
    20.  
    21.     public Entity GetEcoCellFromPosition(float3 position) {
    22.         int2 hash = GetHashFromPosition(position);
    23.         return ecoCells[hash];
    24.     }
    25.  
    26.     int2 GetHashFromPosition(float3 position) {
    27.         int x = (int)math.floor(position.x / cellSize);
    28.         int y = (int)math.floor(position.z / cellSize);
    29.         return new int2(x, y);
    30.     }
    31.  
    32.     protected override void OnUpdate() {
    33.         cellSize = GetSingleton<EcoCellSize>().Value;
    34.         var collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
    35.  
    36.         Entities
    37.         .WithStructuralChanges()
    38.         .WithoutBurst()
    39.         .ForEach((in WorldRenderBounds renderBounds, in LocalToWorld localToWorld, in PhysicsCollider collider) => {
    40.             AABB bounds = renderBounds.Value;
    41.          
    42.             float3 voxelsPerAxis = (bounds.Max - bounds.Min) / cellSize;
    43.             float3 aabbSize = cellSize * math.ceil(voxelsPerAxis + 2);
    44.             float3 aabbCenter = (bounds.Max + bounds.Min) / 2;
    45.             var aabbGrid = new AABBGrid(center:aabbCenter, extents:aabbSize / 2, cellSize:cellSize);
    46.             int3 cellsPerAxis = aabbGrid.CellsPerAxis;
    47.  
    48.             var terrainFilter = new CollisionFilter {
    49.                 BelongsTo = ~0u,
    50.                 CollidesWith = ~0u,
    51.                 GroupIndex = 0
    52.             };
    53.  
    54.             for(int x = 0; x < cellsPerAxis.x; x++) {
    55.                 for(int z = 0; z < cellsPerAxis.z; z++) {
    56.                     AABB cellAABB = aabbGrid.AABBAt(x, 0, z);
    57.                     cellAABB.Center.y -= .1f;
    58.                     var upInput = new RaycastInput {
    59.                         Start = cellAABB.Center,
    60.                         End = cellAABB.Center + (math.up() * 100f),
    61.                         Filter = terrainFilter
    62.                     };
    63.                     Debug.Log("1");
    64.                     if(collisionWorld.CastRay(upInput, out RaycastHit hit)) {
    65.                         cellAABB.Center = hit.Position;
    66.                         Debug.Log("1 Hit");
    67.                     }
    68.                     else {
    69.                         var downInput = new RaycastInput {
    70.                             Start = cellAABB.Center,
    71.                             End = (math.down() * 100f),
    72.                             Filter = terrainFilter
    73.                         };
    74.                         Debug.Log("2");
    75.                         if(collisionWorld.CastRay(downInput, out hit)) {
    76.                             cellAABB.Center = hit.Position;
    77.                             Debug.Log("2 Hit");
    78.                         }
    79.                         else {
    80.                             var distanceInput = new ColliderDistanceInput {
    81.                                 Collider = collider.ColliderPtr,
    82.                                 Transform = new RigidTransform(quaternion.identity, cellAABB.Center),
    83.                                 MaxDistance = cellSize
    84.                             };
    85.                             Debug.Log("3");
    86.                             if(collisionWorld.CalculateDistance(distanceInput, out DistanceHit distanceHit)) {
    87.                                 cellAABB.Center.y = distanceHit.Position.y;
    88.                                 Debug.Log("3 Hit");
    89.                             }
    90.                         }
    91.                     }
    92.  
    93.                     int2 cellHash = GetHashFromPosition(cellAABB.Center);
    94.                     if(!ecoCells.ContainsKey(cellHash)) {
    95.                         Entity ecoCell = EntityManager.CreateEntity(ecoCellArchetype);
    96.                         EntityManager.SetComponentData(ecoCell, new WorldRenderBounds {Value = cellAABB});
    97.                         ecoCells.TryAdd(cellHash, ecoCell);
    98.                     }
    99.                 }
    100.             }
    101.         }).Run();
    102.     }
    103. }
     
    cultureulterior likes this.
  3. RecursiveEclipse

    RecursiveEclipse

    Joined:
    Sep 6, 2018
    Posts:
    298
    I needed to add:

    Code (CSharp):
    1. buildPhysicsWorld.Update();
    2. buildPhysicsWorld.GetOutputDependency().Complete();
    to my OnUpdate(). Is there a better way? I might be able to move it to OnCreate()
     
    cultureulterior likes this.
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    If you want to abstract it out a bit there is UnityEditor.EditorApplication.update delegate.

    So a general tool would startup ECS by calling DefaultWorldInitialization.DefaultLazyEditModeInitialize() and then assigning delegates to the systems you want.

    Shutdown would unassign the delegates call World.DefaultGameObjectInjectionWorld.DestroySystem on each system. Then get all entities in world and destroy them.


    Create a MB or SO that has a list of system types and an editor script with start/stop buttons.
     
    RecursiveEclipse likes this.