Search Unity

Question Multiple systems dependent on physics

Discussion in 'Physics for ECS' started by manpower13, Feb 26, 2021.

  1. manpower13

    manpower13

    Joined:
    Dec 22, 2013
    Posts:
    140
    Hi all!

    Sorry if this has been asked before, I couldn't find a post about it.

    I have multiple systems, all doing raycasts.
    • CheckGroundSystem
      Checks whether entities that need updating are touching the ground at the moment using a raycast.
    • VisionSystem
      Calculates whether an AI is able to see something.
    • MouseOverSystem
      Will add appropriate components when an entity is a target for mouse over changes.
    They all start with
    Code (CSharp):
    1. Dependency = JobHandle.CombineDependencies(Dependency, _buildPhysicsWorld.GetOutputDependency());
    in
    OnUpdate()
    to make sure the physics world is done building.
    Afterwards, it will schedule its raycast jobs and perform other computations.

    Even though it went well for a long time, suddenly (when working on different systems and adding more), I get the following error:
    Code (CSharp):
    1. InvalidOperationException: The previously scheduled job VisionJob reads from the Unity.Collections.NativeArray`1[Unity.Physics.RigidBody] VisionJob.world.m_Bodies. You are trying to schedule a new job CheckGroundSystem:OnUpdate_LambdaJob0, which writes to the same Unity.Collections.NativeArray`1[Unity.Physics.RigidBody] (via OnUpdate_LambdaJob0.JobData.collisionWorld.m_Bodies). To guarantee safety, you must include VisionJob as a dependency of the newly scheduled job.
    The error sounds clear, apparently they are not allowed to read and write in parallel (makes sense). I'm not sure where I'm writing to the rigidbodies in this case though (code that is called from inside an Entities.Foreach in
    CheckGroundSystem
    :
    Code (CSharp):
    1. private static unsafe bool IsGrounded(in PhysicsCollider physicsCollider, in float3 position, ref CollisionWorld collisionWorld, in uint collidesWith)
    2.         {
    3.             var filter = new CollisionFilter
    4.             {
    5.                 BelongsTo = ~collidesWith,
    6.                 CollidesWith = collidesWith,
    7.                 GroupIndex = 0
    8.             };
    9.             var oldFilter = physicsCollider.Value.Value.Filter;
    10.             physicsCollider.Value.Value.Filter = filter;
    11.             var colliderCastInput = new ColliderCastInput
    12.             {
    13.                 Collider = physicsCollider.ColliderPtr,
    14.                 Orientation = quaternion.identity,
    15.                 Start = position,
    16.                 End = new float3(position.x, position.y - 0.05f, position.z)
    17.             };
    18.             bool hit = collisionWorld.CastCollider(colliderCastInput, out var colliderCastHit);
    19.             physicsCollider.Value.Value.Filter = oldFilter;
    20.            
    21.             return hit;
    22.         }

    Two questions:
    1. Do I need to add more code to make sure dependencies are correctly handled in relation to the physics systems? Some posts mention
      _stepPhysicsWorld.AddInputDependency(Dependency);
      , but I do not think that is required? Same goes for

      [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
      [UpdateAfter(typeof(BuildPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
      .
    2. How can I make sure I'm not writing to the rigidbodies such that multiple systems can safely work together on physics (and thus do raycasts)? Or should I add dependencies on the specific jobs (thus, like the error is saying, I must include 'VisionJob' as a dependency to 'CheckGroundSystem'? How would that work with more systems? Why are only these two systems colliding with each other and are the other system-combinations no problem?
    Thanks a lot in advance :)

    Unity ECS, Burst and physics are amazing, but I still find them a bit confusing sometimes! Hope an answer clears stuff up!

    Sincerely,
    Floris Weers
     
    Mikael-H likes this.
  2. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220
    You need 3 things mainly
    The dependency system works best when you use jobs from what i found

    1) schedule your work, after export and before end frame physics
    Code (CSharp):
    1. [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    2. [UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore((typeof(EndFramePhysicsSystem)))]
    2) Job dependency for the NEXT SYSTEM
    endFramePhysicsSystem.AddInputDependency(Dependency);

    3) Job dependency for the PREVIOUS systems
    all your jobs must wait for this to finish _buildPhysicsWorld.GetOutputDependency()


    if your systems run outside the fixed step simulation then you need to wait for physics jobs(not systems) and also tell the next frame physics to wait for you
    _buildPhysicsWorld.GetOutputDependency()
    endFramePhysicsSystem.GetOutputDependency()

    next frame physics wait
    _buildPhysicsWorld.AddInputDependency(Dependency);


    If you don't use jobs or Entities.ForEach then i am not sure how to handle these dependency problems, perhaps someone can shed some light here?

    If my system runs and does some old school code (no entities for each or job scheduling), what do we do? are we forced to use Entities.ForEach or Jobs to handle dependencies properly?
     
    Mikael-H and manpower13 like this.
  3. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    Hi @manpower13 , seems like you're changing collider's filter and that's also a write operation to the collider (and thus a RigidBody that's referencing the collider). Please test it without changing the filter to make sure that was the cause.

    @argibaltzi , if you're wondering about reading/writing data in system.OnUpdate(), you can still do it, but should know how it works:
    - OnUpdate calls are ordered via UpdateAfter and UpdateBefore and they run on the main thread
    - Jobs scheduled in previous systems could be running in parallel with current system's OnUpdate, so you might need to complete some of them if they can affect your OnUpdate (for example, call Dependency.Complete() )

    I hope all of this will be much easier to implement and clearly documented very soon, in the upcoming release of UnityPhysics. Stay tuned, we'll put a sticky post when it's out.
     
    Mikael-H and argibaltzi like this.
  4. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    309
    Yes, documentation of how to properly handle dependencies when using Unity.Physics is sorely needed. I haven't found any doc specifically for dependencies, does any exist?
     
  5. milos85miki

    milos85miki

    Joined:
    Nov 29, 2019
    Posts:
    197
    We've done a lot to simplify physics systems scheduling and have written some nice documentation, but unfortunately I don't know when it'll be publicly available. Please stay tuned for UnityPhysics versions >= 0.7.0 .