RayCast Inside IJobEntity

I’m getting error when calling CastRay from within IJobEntity. What is the proper way to call it? When I CastRay from ISystem it works just fine.

Error

InvalidOperationException: The previously scheduled job ProjectileControlJob reads from the UNKNOWN_OBJECT_TYPE ProjectileControlJob.JobData.CollisionWorld.EntityBodyIndexMap. You must call JobHandle.Complete() on the job ProjectileControlJob, before you can write to the UNKNOWN_OBJECT_TYPE safely.

Job

[BurstCompile]
    public partial struct ProjectileControlJob : IJobEntity
    {
        public float DeltaTime;
        public EntityCommandBuffer.ParallelWriter ECB;
        [ReadOnly] public CollisionWorld CollisionWorld;

        [BurstCompile]
        private void Execute(
            [EntityIndexInQuery] int index,
            ProjectileAspect projectileData,
            RefRW<LocalTransform> localTransform,
            RefRO<CollisionFilterData> collisionFilterData,
            Entity projectileEntity)
        {
            /* Calculate position-related values */
            ProcessCollisions(position, nextPosition, collisionFilter);
            /* Move projectile if not collided */
        }

        [BurstCompile]
        private bool ProcessCollisions(float3 from, float3 to, CollisionFilter collisionFilter)
        {
            var input = new RaycastInput
            {
                Start = from,
                End = to,
                Filter = collistionFilter
            };
            if (!CollisionWorld.CastRay(input, out var hit)) return false;
            Debug.Log("Collided");
            return true;
        }
    }

System

[BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            var ecb = SystemAPI
                .GetSingleton<BeginInitializationEntityCommandBufferSystem.Singleton>()
                .CreateCommandBuffer(state.WorldUnmanaged)
                .AsParallelWriter();
            var dt = SystemAPI.Time.fixedDeltaTime;//DeltaTime;
            var builder = new EntityQueryBuilder(Allocator.Temp).WithAll<PhysicsWorldSingleton>();
            var singletonQuery = state.EntityManager.CreateEntityQuery(builder);
            var collisionWorld = singletonQuery.GetSingleton<PhysicsWorldSingleton>().CollisionWorld;
            state.Dependency = new ProjectileControlJob {DeltaTime = dt, ECB = ecb, CollisionWorld = collisionWorld}.ScheduleParallel(state.Dependency);
            singletonQuery.Dispose();

Make sure to include state.Dependency to the specified ECBSystem via AddJobHandleForProducer.
Also, disabling burst / job safetly should provide better error description.

You shouldn’t. Getting ECB Singleton already handle dependencies automatically. You only need AddJobHandleForProducer if you access non-singleton ECB system.

1 Like

You shouldn’t create query and all that burden in OnUpdate. You should just directly call:
SystemAPI.GetSingleton<PhysicsWorldSingleton>(), because you’re working in ISystem, code I see in OnUpdate for getting physics world seems copy-paste from doc samples, but it’s for calling it from MB land, and comments for that sample specify that in system you don’t need that.

2 Likes

That helped, thanks a lot!