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

Resolved Testing Systems Performing RayCasts?

Discussion in 'Physics for ECS' started by florianhanke, Jan 1, 2021.

  1. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    Hi all,

    I'd be grateful for some feedback on how to set up tests when they perform ray casts using Unity Physics. Sadly no tests I can copy since the Physics tests I've seen are unit tests. I've read the Physics source, but am still unsure why in the tests, the colliders are not hit by raycasts.

    In this specific case, I am trying to find the closest enemy that is hit by a raycast (selecting an enemy to aim at).
    The test:
    Code (CSharp):
    1. [TestFixture]
    2. public class SelectAimSystemTest : BaseTest<SelectAimSystem>
    3. {
    4.     [Test]
    5.     public void selectsClosestTargetTest()
    6.     {
    7.         var aimingEntity = em.CreateEntity(
    8.                                            typeof(Translation),
    9.                                            typeof(Rotation),
    10.                                            typeof(LocalToWorld),
    11.                                            typeof(FactionComponent),
    12.                                            typeof(Aiming),
    13.                                            typeof(PhysicsVelocity),
    14.                                            typeof(PhysicsCollider)
    15.                                           );
    16.  
    17.         var aimingTranslation = em.
    18.                                 GetComponentData<Translation>(
    19.                                                               aimingEntity
    20.                                                              ).
    21.                                 Value;
    22.         em.SetComponentData(
    23.                             aimingEntity,
    24.                             new FactionComponent
    25.                             {
    26.                                 Value = (byte) Factions.Id.Allies
    27.                             }
    28.                            );
    29.         em.SetComponentData(
    30.                             aimingEntity,
    31.                             new LocalToWorld
    32.                             {
    33.                                 Value = new float4x4(
    34.                                                      quaternion.identity,
    35.                                                      aimingTranslation
    36.                                                     )
    37.                             }
    38.                            );
    39.         em.SetComponentData(
    40.                             aimingEntity,
    41.                             new PhysicsCollider
    42.                             {
    43.                                 Value = SphereCollider.Create(
    44.                                                               new SphereGeometry
    45.                                                               {
    46.                                                                   Center = aimingTranslation,
    47.                                                                   Radius = 0.5f
    48.                                                               }
    49.                                                              )
    50.                             }
    51.                            );
    52.  
    53.         var targetEntity1 = em.CreateEntity(
    54.                                             typeof(Translation),
    55.                                             typeof(Rotation),
    56.                                             typeof(LocalToWorld),
    57.                                             typeof(FactionComponent),
    58.                                             typeof(PhysicsVelocity),
    59.                                             typeof(PhysicsCollider)
    60.                                            );
    61.         var targetTranslation1 = new float3(10, 0, 10);
    62.         em.SetComponentData(
    63.                             targetEntity1,
    64.                             new Translation
    65.                             {
    66.                                 Value = targetTranslation1
    67.                             }
    68.                            );
    69.         em.SetComponentData(
    70.                             targetEntity1,
    71.                             new FactionComponent
    72.                             {
    73.                                 Value = (byte) Factions.Id.Axis
    74.                             }
    75.                            );
    76.         em.SetComponentData(
    77.                             targetEntity1,
    78.                             new LocalToWorld
    79.                             {
    80.                                 Value = new float4x4(
    81.                                                      quaternion.identity,
    82.                                                      targetTranslation1
    83.                                                     )
    84.                             }
    85.                            );
    86.         em.SetComponentData(
    87.                             targetEntity1,
    88.                             new PhysicsCollider
    89.                             {
    90.                                 Value = SphereCollider.Create(
    91.                                                               new SphereGeometry
    92.                                                               {
    93.                                                                   Center = em.
    94.                                                                            GetComponentData<Translation>(
    95.                                                                                 targetEntity1
    96.                                                                                ).
    97.                                                                            Value,
    98.                                                                   Radius = 0.5f
    99.                                                               }
    100.                                                              )
    101.                             }
    102.                            );
    103.  
    104.         var aiming = em.GetComponentData<Aiming>(aimingEntity);
    105.         Assert.AreEqual(new float3(0, 0, 0), aiming.globalDirection);
    106.  
    107.         World.Update();
    108.  
    109.         aiming = em.GetComponentData<Aiming>(aimingEntity);
    110.         Assert.AreEqual(new float3(10, 0, 10), aiming.globalDirection);
    111.     }
    112. }
    Aiming is the component which should contain the result direction where the enemy is. Faction determines who is a valid target. Adding a PhysicsCollider for the raycast.
    The test base class sets up the basic systems:
    Code (CSharp):
    1. public class BaseTest<T> : ECSTestsFixture where T : ComponentSystemBase
    2. {
    3.     protected EntityManager em;
    4.  
    5.     [SetUp]
    6.     public override void Setup()
    7.     {
    8.         base.Setup();
    9.  
    10.         em = m_Manager;
    11.  
    12.         var systems = new List<Type>
    13.         {
    14.             // Defaults are added in DefaultWorldInitialization.
    15.             // var initializationSystemGroup = world.GetOrCreateSystem<InitializationSystemGroup>();
    16.             // var simulationSystemGroup = world.GetOrCreateSystem<SimulationSystemGroup>();
    17.             // var presentationSystemGroup = world.GetOrCreateSystem<PresentationSystemGroup>();
    18.          
    19.             typeof(BeginInitializationEntityCommandBufferSystem),
    20.             typeof(EndInitializationEntityCommandBufferSystem),
    21.          
    22.             typeof(BeginFixedStepSimulationEntityCommandBufferSystem),
    23.             typeof(FixedStepSimulationSystemGroup),
    24.             typeof(EndFixedStepSimulationEntityCommandBufferSystem),
    25.          
    26.             typeof(BeginSimulationEntityCommandBufferSystem),
    27.             typeof(EndSimulationEntityCommandBufferSystem),
    28.          
    29.             typeof(LateSimulationSystemGroup),
    30.          
    31.             typeof(BeginPresentationEntityCommandBufferSystem),
    32.          
    33.             typeof(BuildPhysicsWorld),
    34.             typeof(StepPhysicsWorld),
    35.             typeof(ExportPhysicsWorld),
    36.             typeof(EndFramePhysicsSystem),
    37.          
    38.             typeof(ServerPerformPhysicsGroup),
    39.          
    40.             typeof(T),
    41.         };
    42.         DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups(World, systems);
    43.  
    44.         World.SetTime(new TimeData(1.234, 0.016f));
    45.     }
    46. }
    Has anyone set up tests to test raycasts in their systems and can give me some pointers by any chance?

    P.S: The SelectAimSystem runs after the BuildPhysicsWorld system and before the StepPhysicsWorld system.
     
  2. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    426
    Figured it out! I was mistakenly assuming the collider requires world coordinates, but the collider center should use local coordinates (in my test case (0, 0, 0)). I'm quite happy about the relatively minimal setup for testing systems using raycasts.

    Also, there is a test that tests raycasts in a functional manner. It's
    WorldQueryTest
    in file
    QueryTests.cs
    .
     
    petarmHavok likes this.