Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Unit testing an ITriggerEventsJob

Discussion in 'Physics for ECS' started by martinjonsson01, Dec 27, 2020.

  1. martinjonsson01

    martinjonsson01

    Joined:
    Jan 2, 2016
    Posts:
    7
    I've been trying to write a unit test for my ITriggerEventsJob but the two methods I have tried so far have failed.

    The first method I tried was by creating the Unity Physics-systems in my test world and trying to get them to recognize an actual collision between two entities with Collision-components. I failed to get this working, seemingly because there are a lot of physics-systems and I'm not sure I created them all correctly.

    I did also try not manually creating systems at all, but instead used the
    DefaultWorldInitialization.Initialize-method to create the world with all systems, but this did not result in any registered triggers either. I'm thinking this might be because of incorrectly applied components to my test entities, as when I try the collision in the actual editor (using game object to entity conversion) the trigger collision is handled in my job.

    The second method I tried was by manually calling the Execute-method of my ITriggerEventsJob, but since it requires a TriggerEvent-parameter I had to create one and pass one in. The problem here is that while I can create a TriggerEvent-instance, I can not set any of its values since they are all based on an internal field of type TriggerEventData. Good thing is that TriggerEventData contains a method for creating a TriggerEvent from it. Bad thing is that the TriggerEventData-struct is private and the CreateTriggerEvent-method is internal. (Mocking the TriggerEvent using NSubstitute is not an option either since it can't mock structs. If anyone knows about a mocking-library that allows this then that would help!)

    My last-ditch efforts in trying to manually call the Execute-method lead me down the route of trying to use reflection to modify the internal fields of TriggerEvent to allow me to set the EntityPair to my two test-entities that I want to trigger the job. This also failed, most probably because I have zero experience using reflection and so I had trouble actually setting the values of the internal fields as they are structs and can not be modified since they are value-types (I believe).


    In summary, what I need is some way of artificially creating a TriggerEvent for my two entities that I want to collide so that my ITriggerEventsJob runs. Anyone got any ideas?
     
  2. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    Hi @martinjonsson01 , you could maybe create your own struct (MyTriggerEventData) that has the same fields and layout like TriggerEventData, to enable you to set the values you need. Then I see 2 options:
    1. Create MyTriggerEventData local var and use unsafe code to cast it to TriggerEvent, passing it to the method you want to test (your job's Execute):
    Code (CSharp):
    1.     MyTriggerEventData data = new MyTriggerEventData
    2.     {
    3.         <init fields to desired values>
    4.     };
    5.  
    6.     unsafe
    7.     {
    8.         TriggerEvent* triggerEvent = (TriggerEvent*)UnsafeUtility.AddressOf<MyTriggerEventData>(ref data);
    9.         myTriggerJob.Execute(*triggerEvent);
    10.     }
    11.  
    2. Slightly refactor your ITriggerEventsJob to do the core processing on MyTriggerEventData:
    Code (CSharp):
    1. struct MyTriggerJob : ITriggerEventsJob
    2. {
    3.         public void Execute(TriggerEvent triggerEvent)
    4.         {
    5.             MyTriggerEventData data = new MyTriggerEventData
    6.             {
    7.                 <init struct fields from triggerEvent>
    8.             };
    9.             ExecuteImpl(data);
    10.         }
    11.  
    12.         public void ExecuteImpl(MyTriggerEventData data)
    13.         {
    14.         <your processing>
    15.         }
    16. }
    Please let me know if this helps.
     
    martinjonsson01 and petarmHavok like this.
  3. martinjonsson01

    martinjonsson01

    Joined:
    Jan 2, 2016
    Posts:
    7
    Those sound like great solutions, I'll try them out!

    Thank you!
     
    milos85miki likes this.