Search Unity

Trigger Events Raised On Dev Machine But Not Other Computers

Discussion in 'Physics for ECS' started by EternalAmbiguity, Mar 9, 2021.

  1. EternalAmbiguity

    EternalAmbiguity

    Joined:
    Dec 27, 2014
    Posts:
    3,144
    Been working on a game that I've had in the last few Feedback Fridays over in Game Design. On my dev PC the game works perfectly fine, as seen in the GIF in this post. However on other machines it's jerky and more importantly the bullet system, that uses trigger events, straight up isn't working, as seen in this post. The bullets do move, which is done in OnUpdate, but the check for collisions doesn't seem to be happening. The bullets should disappear when they hit enemies and walls.

    The system is below.
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using Unity.Jobs;
    6. using UnityEngine.Jobs;
    7. using Unity.Entities;
    8. using Unity.Transforms;
    9. using System.Linq;
    10. using Unity.Mathematics;
    11. using Unity.Physics;
    12. using Unity.Physics.Systems;
    13.  
    14. using Unity.Collections;
    15. using Unity.Rendering;
    16. using System.Threading.Tasks;
    17. using Unity.Burst;
    18. public class WeaponSystem:SystemBase
    19. {
    20.     EntityCommandBufferSystem m_Barrier;
    21.     BuildPhysicsWorld physicsWorldSystem;
    22.     StepPhysicsWorld m_StepPhysicsWorldSystem;
    23.     EndFramePhysicsSystem EndFramePhysicsSystem;
    24.  
    25.     protected override void OnCreate()
    26.     {
    27.         m_Barrier = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    28.         physicsWorldSystem = Unity.Entities.World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<BuildPhysicsWorld>();
    29.         m_StepPhysicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<StepPhysicsWorld>();
    30.         EndFramePhysicsSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<EndFramePhysicsSystem>();
    31.     }
    32.  
    33.     struct TriggerEventJob : ITriggerEventsJob
    34.     {
    35.         public EntityCommandBuffer.ParallelWriter cBuffer;
    36.         [NativeDisableParallelForRestriction] public ComponentDataFromEntity<WeaponEntity> weaponEntityInfo;
    37.         [NativeDisableParallelForRestriction] public ComponentDataFromEntity<PlayerEntity> playerEntityInfo;
    38.         [NativeDisableParallelForRestriction] public ComponentDataFromEntity<EnemyEntity> enemyEntityInfo;
    39.         [NativeDisableParallelForRestriction] public ComponentDataFromEntity<EnemyCageEntity> enemyStructureEntityInfo;
    40.  
    41.         public void Execute(TriggerEvent collisionEvent)
    42.         {
    43.             CheckWeapon(collisionEvent.EntityA);
    44.             CheckWeapon(collisionEvent.EntityB);
    45.             CheckCollided(collisionEvent.EntityA, collisionEvent.EntityB);
    46.             CheckCollided(collisionEvent.EntityB, collisionEvent.EntityA);
    47.         }
    48.  
    49.         void CheckWeapon(Entity entity)
    50.         {
    51.             if (weaponEntityInfo.HasComponent(entity))
    52.             {
    53.                 var cur = weaponEntityInfo[entity];
    54.                 if(cur.type != WeaponType.TrapBio && cur.type != WeaponType.TrapEn)
    55.                 {
    56.                     StaticClass.Damage(entity);
    57.                 }
    58.                 else
    59.                 {
    60.                     cur.stop = true;
    61.                     cBuffer.SetComponent(entity.Index, entity, cur);
    62.                     // still stop it, stick where it's at
    63.                 }
    64.             }
    65.         }
    66.  
    67.         void CheckCollided(Entity a, Entity b)
    68.         {
    69.             if(enemyStructureEntityInfo.HasComponent(a) && weaponEntityInfo.HasComponent(b))
    70.             {
    71.                 var cur = weaponEntityInfo[b];
    72.                 StaticClass.damageEnemyStructure?.Invoke(a, cur.type);
    73.             }
    74.         }
    75.     }
    76.  
    77.     protected override void OnUpdate()
    78.     {
    79.         var commandBuffer = m_Barrier.CreateCommandBuffer().AsParallelWriter();
    80.         var weaponEntityInfo = GetComponentDataFromEntity<WeaponEntity>();
    81.         var playerEntityInfo = GetComponentDataFromEntity<PlayerEntity>();
    82.         var enemyEntityInfo = GetComponentDataFromEntity<EnemyEntity>();
    83.         var enemyStructureEntityInfo = GetComponentDataFromEntity<EnemyCageEntity>();
    84.         var deltaTime = Time.DeltaTime;
    85.         var physicsWorld = physicsWorldSystem.PhysicsWorld;
    86.         var collisionWorld = physicsWorld.CollisionWorld;
    87.         var grid = StaticClass.GetFlatWalkableGrid();
    88.         var gridHeight = StaticClass.interactiveGrids[StaticClass.currentLevel].GetLength(1);
    89.         var gridLength = grid.Length;
    90.         var cellWalkable0 = new NativeArray<CellWalkableState>(grid, Allocator.TempJob);
    91.         var cellWalkable = cellWalkable0.AsReadOnly();
    92.         var mapCorner = StaticClass.mapCorners[0];
    93.         var exploder = new NativeQueue<Entity>(Allocator.TempJob);
    94.         var exploderParallel = exploder.AsParallelWriter();
    95.         Entities
    96.             .WithName("WeaponSystem")
    97.             .WithBurst(Unity.Burst.FloatMode.Default, Unity.Burst.FloatPrecision.Standard, true)
    98.             .ForEach((Entity entity, int nativeThreadIndex, /*in Translation translation,*/ ref WeaponEntity weaponEntity, ref PhysicsVelocity velocity, ref Translation translation/*, in LocalToWorld localToWorld, in WorldRenderBounds bounds, in PhysicsCollider collider*/) =>
    99.             {
    100.                 bool destroy = false;
    101.                 if(weaponEntity.type == WeaponType.TrapBio || weaponEntity.type == WeaponType.TrapEn)
    102.                 {
    103.                     weaponEntity.countdown += deltaTime;
    104.                     if(weaponEntity.stop)
    105.                     {
    106.                         velocity.Linear = new float3();
    107.                     }
    108.                     else
    109.                     {
    110.                         if (velocity.Linear.x > 0 || velocity.Linear.z > 0)
    111.                         {
    112.                             velocity.Linear.y = math.pow(weaponEntity.countdown + 0.5f, 4) * -10;
    113.                         }
    114.                         if (translation.Value.y <= 0)
    115.                         {
    116.                             velocity.Linear = new float3(0, 0, 0);
    117.                             translation.Value.y = 0;
    118.                         }
    119.                     }
    120.                 }
    121.                 if(weaponEntity.countdown > 1)
    122.                 {
    123.                     exploderParallel.Enqueue(entity);
    124.                 }
    125.                 if (destroy)
    126.                 {
    127.                     commandBuffer.DestroyEntity(nativeThreadIndex, entity);
    128.                 }
    129.             })
    130.             .ScheduleParallel();
    131.         Dependency = new TriggerEventJob {
    132.             cBuffer = commandBuffer,
    133.             weaponEntityInfo = weaponEntityInfo,
    134.             playerEntityInfo = playerEntityInfo,
    135.             enemyEntityInfo = enemyEntityInfo,
    136.             enemyStructureEntityInfo = enemyStructureEntityInfo,
    137.         }
    138.         .Schedule(m_StepPhysicsWorldSystem.Simulation, ref physicsWorldSystem.PhysicsWorld, Dependency);
    139.         m_Barrier.AddJobHandleForProducer(Dependency);
    140.         Dependency.Complete();
    141.         for (int i = 0; i < exploder.Count; i++)
    142.         {
    143.             StaticClass.Damage(exploder.Dequeue());
    144.         }
    145.         cellWalkable0.Dispose();
    146.         exploder.Dispose();
    147.     }
    148. }
    149.  
    Can anyone point out what might be causing this to work on my dev machine but literally no others?
     
  2. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    Your system is missing the attributes:
    [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    [UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
     
  3. EternalAmbiguity

    EternalAmbiguity

    Joined:
    Dec 27, 2014
    Posts:
    3,144
    I actually had something like that before, but the log file indicated it was being ignored for some reason so I removed it.

    Added it back in just above the class declaration, so
    Code (csharp):
    1.  
    2. [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    3. [UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
    4. public class WeaponSystem:SystemBase
    5.  
    , but it still doesn't seem to be working. The latest version is up on my itch.io page - https://eternalambiguity.itch.io/ca-shooter
     
  4. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    Hi @EternalAmbiguity , which UnityPhysics version are you using, is it very old maybe?
    The only explanation I have for the ignore message is that you're on a version where physics systems were not in FixedStepSimulationSystemGroup. Could you please look inside the physics package and check in which groups are ExportPhysicsWorld and EndFramePhysicsSystem (they're both in ECS\Base\Systems\ folder)?
     
  5. EternalAmbiguity

    EternalAmbiguity

    Joined:
    Dec 27, 2014
    Posts:
    3,144
    It's not giving the ignore message anymore. That was with old code, that didn't have exactly what you suggested, though I don't remember specifically what it was. I think it was missing the first line about the FixedStepSimulationSystemGroup, and so the warning was that it was ignoring the UpdateAfter/Before because of that.

    I just added a debug.log to the beginning of the trigger event, so line 43...and it fires from other PCs. So the trigger is firing apparently, but something else is going on in one of those subsequent methods that prevents it from destroying the entity. Sorry, I guess I should have done that before making this thread, but it didn't occur to me until now.

    Edit: I got it working. Seems like a weird issue with threading, with me using things like Task.Run and Task.Start(main thread) all over the place and some of those apparently not working on other machines for some reason.
     
    Last edited: Mar 11, 2021
  6. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    Glad you worked it out!
    It worked on my machine as well, but obviously not everywhere. If you don't have to deal with threads directly, it's probably better to let the job scheduling do it for you.
     
  7. EternalAmbiguity

    EternalAmbiguity

    Joined:
    Dec 27, 2014
    Posts:
    3,144
    I'm still using them in other places (for the backend simulation for my game), but this makes me wonder if I should be shifting to jobs completely. I need a number of things that I've heard aren't valid for burst, like classes (not structs), and specific non per-frame update rate and interaction with the rest of my code. I can do these things on backgrounds threads and just jump onto the main one when necessary for entities and such, but this problem has me worried.

    The specific situation here was that the trigger called a method in a static class, which called an action in that same class, which called an Action defined in a Monobehavior script, and the Action used a Task.Run which was working on my machine and apparently yours, but not on others. I removed it and it works now, but I'm not sure if it was a Burst thread ->Task.Run thing, or a Task.Run thing on its own. As mentioned I'm still using Task.Run in other places and it's working, so I dunno.
     
  8. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    I guess the other places are fine, while spawning a ThreadPool task from Burst-ed job doesn't sound like a reliable thing. Unfortunately, the only thing I can definitely recommend is to test everything on all supported platforms and high/low end configs.

    You could open a thread on DOTS subforum, maybe Burst folks will be able to give more precise guidelines.
     
    EternalAmbiguity likes this.