Convert JobComponentSystem to SystemBase

Hi,i am still a beginner in Dots and am trying to learn about controlling dependency, please can someone help me to make raycast code work in SystemBase
the code works as JobSystem :

[UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
public class raycastJob  : JobComponentSystem
{
    public struct CollisionWorldRo
    {
        [ReadOnly] public CollisionWorld collisionWorld;

    }
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        float DeltaTime = Time.DeltaTime;
        var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
        var collisionWorldRo = new CollisionWorldRo { collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld };
        JobHandle jobhandle = Entities.ForEach((ref Translation translation, ref Rotation rotation, in LocalToWorld localtoworld) =>
        {
            float3 RayFrom = localtoworld.Value.c3.xyz;
            float3 RayTo = RayFrom - (5 * localtoworld.Value.c1.xyz);
            RaycastInput input = new RaycastInput()
            {
                Start = RayFrom,
                End = RayTo,
                Filter = new CollisionFilter
                {
                    BelongsTo = 1u << 2,  
                    CollidesWith = 1u << 9 | 1u << 10,
                    GroupIndex = 0
                }
            };

            Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit();
            bool haveHit = collisionWorldRo.collisionWorld.CastRay(input, out hit);

            if (haveHit)
            {

            }
        }).Schedule(JobHandle.CombineDependencies(inputDeps, physicsWorldSystem.FinalJobHandle));
        return jobhandle;
    }
}

I tried converting it in this way but I got an error about dependency:

[UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
public class raycastSystemBase : SystemBase
{
    public struct CollisionWorldRo
    {
        [ReadOnly] public CollisionWorld collisionWorld;

    }
    protected override void OnUpdate( )
    {
        float DeltaTime = Time.DeltaTime;
        var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
        var collisionWorldRo = new CollisionWorldRo { collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld };
       Entities.ForEach((ref Translation translation, ref Rotation rotation, in LocalToWorld localtoworld) =>
        {
            float3 RayFrom = localtoworld.Value.c3.xyz;
            float3 RayTo = RayFrom - (5 * localtoworld.Value.c1.xyz);
            RaycastInput input = new RaycastInput()
            {
                Start = RayFrom,
                End = RayTo,
                Filter = new CollisionFilter
                {
                    BelongsTo = 1u << 2,
                    CollidesWith = 1u << 9 | 1u << 10,
                    GroupIndex = 0
                }
            };

            Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit();
            bool haveHit = collisionWorldRo.collisionWorld.CastRay(input, out hit);

            if (haveHit)
            {

            }
        }).Schedule(physicsWorldSystem.FinalJobHandle);
       
    }
}

error:
InvalidOperationException: The previously scheduled job ExportPhysicsWorld:ExportDynamicBodiesJob writes to the NativeArray ExportDynamicBodiesJob.Data.PositionType. You are trying to schedule a new job raycastSystemBase:<>c__DisplayClass_OnUpdate_LambdaJob0, which writes to the same NativeArray (via <>c__DisplayClass_OnUpdate_LambdaJob0.Data._lambdaParameterValueProviders.forParameter_translation._type). To guarantee safety, you must include ExportPhysicsWorld:ExportDynamicBodiesJob as a dependency of the newly scheduled job.

Instead of inputDeps use Dependency. And instead of returning a JobHandle write back to Dependency.

1 Like

You still need to manually add a dependency to the physics world to ensure it’s completed before you use it.

    [UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
    public class raycastSystemBase : SystemBase
    {
        public struct CollisionWorldRo
        {
            [ReadOnly] public CollisionWorld collisionWorld;
    
        }
        protected override void OnUpdate( )
        {
            float DeltaTime = Time.DeltaTime;
            var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
           Dependency = JobHandle.CombineDependencies(physicsWorldSystem.FinalJobHandle, Dependency); // add this line
            var collisionWorldRo = new CollisionWorldRo { collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld };
           Entities.ForEach((ref Translation translation, ref Rotation rotation, in LocalToWorld localtoworld) =>
            {
                float3 RayFrom = localtoworld.Value.c3.xyz;
                float3 RayTo = RayFrom - (5 * localtoworld.Value.c1.xyz);
                RaycastInput input = new RaycastInput()
                {
                    Start = RayFrom,
                    End = RayTo,
                    Filter = new CollisionFilter
                    {
                        BelongsTo = 1u << 2,
                        CollidesWith = 1u << 9 | 1u << 10,
                        GroupIndex = 0
                    }
                };
    
                Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit();
                bool haveHit = collisionWorldRo.collisionWorld.CastRay(input, out hit);
    
                if (haveHit)
                {
    
                }
            }).ScheduleParallel(); // In system base schedule is single thread
          
        }
    }

Also note that Schedule() is single threaded in SystemBase. You need to use ScheduleParallel if you want parallel operations.

1 Like

aw that’s awesome thank you very much !!

I do this to convert my JobComponentSystem to SystemBase:

protected override void OnUpdate() {
    this.Dependency = OnUpdate(this.Dependency);
}

private JobHandle OnUpdate(JobHandle inputDeps) {
    // Place old code here
}
1 Like