Problem with raycasting InvalidOperationException

Hello

I get several errors when i try to do a raycast from my systembase script, but if i do a isolated test with a simple box and a plane it will work.
Trying to create a controller with raycast but i am not able to make it work on my controller script.
The error say that i should call JobHandle.Complete() on the script but not sure. Other systembase scripts that i have made didn’t require to call JobHandle.Complete(). And my test systembase script works so i am kind of lost.
Anyone that can point me in the right direction?

Error:

InvalidOperationException: The previously scheduled job CharacterControllerSystem:OnUpdate_LambdaJob0 writes to the Unity.Collections.NativeHashMap2[Unity.Entities.Entity,System.Int32] OnUpdate_LambdaJob0.JobData.rayCaster.physicsWorld.CollisionWorld.EntityBodyIndexMap. You must call JobHandle.Complete() on the job CharacterControllerSystem:OnUpdate_LambdaJob0, before you can write to the Unity.Collections.NativeHashMap2[Unity.Entities.Entity,System.Int32] safely.
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at :0)
Unity.Collections.NativeHashMap2[TKey,TValue].CheckWrite () (at Library/PackageCache/com.unity.collections@0.15.0-preview.21/Unity.Collections/NativeHashMap.cs:554) Unity.Collections.NativeHashMap2[TKey,TValue].Clear () (at Library/PackageCache/com.unity.collections@0.15.0-preview.21/Unity.Collections/NativeHashMap.cs:194)
Unity.Physics.CollisionWorld.Reset (System.Int32 numStaticBodies, System.Int32 numDynamicBodies) (at Library/PackageCache/com.unity.physics@0.6.0-preview.3/Unity.Physics/Collision/World/CollisionWorld.cs:53)
Unity.Physics.PhysicsWorld.Reset (System.Int32 numStaticBodies, System.Int32 numDynamicBodies, System.Int32 numJoints) (at Library/PackageCache/com.unity.physics@0.6.0-preview.3/Unity.Physics/Dynamics/World/PhysicsWorld.cs:41)
Unity.Physics.Systems.BuildPhysicsWorld.OnUpdate () (at Library/PackageCache/com.unity.physics@0.6.0-preview.3/Unity.Physics/ECS/Base/Systems/BuildPhysicsWorld.cs:122)

Script:

namespace CharacterControllerNamespace
{
    //[UpdateAfter(typeof(EndFramePhysicsSystem))]
    public class CharacterControllerSystem : SystemBase
    {

        protected override void OnUpdate()
        {
            var rayCaster = new MovementRayCast() { physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>().PhysicsWorld };
            float deltaTime = Time.DeltaTime;


            Entities.ForEach((ref CharacterDataComponent characterDataComponent, ref Translation translation, ref Rotation rotation, in PlayerControllerComponent playerControllerComponent) =>
            {

                float3 vectorRight = math.mul(rotation.Value, math.right());
                vectorRight.y = 0;
                vectorRight = math.normalizesafe(vectorRight);

                translation.Value = translation.Value + (playerControllerComponent.inputVertical * math.forward(rotation.Value)) * 5f * deltaTime;
                translation.Value = translation.Value + (playerControllerComponent.inputHorizontal * vectorRight) * 5f * deltaTime;


                if (playerControllerComponent.leftAlt)
                {

                }
                else
                {
                    rotation.Value = quaternion.RotateY(playerControllerComponent.cameraHorizontal);
                }

                //check for ground
                if (rayCaster.CheckRay(translation.Value, characterDataComponent.Gravity, 4f))
                {

                }
                else
                {
                    translation.Value = translation.Value + characterDataComponent.Gravity * deltaTime;
                }

                if (playerControllerComponent.jump)
                {
                    translation.Value = translation.Value + (-characterDataComponent.Gravity) * 100f * deltaTime;
                }


            }).Schedule();
        }


        private struct MovementRayCast
        {
            public PhysicsWorld physicsWorld;

            public bool CheckRay(float3 position, float3 direction, float rayLength)
            {
                var ray = new RaycastInput()
                {
                    Start = position,
                    End = position + (direction * rayLength),
                    Filter = new CollisionFilter()
                    {
                        GroupIndex = 0,
                        BelongsTo = 1u << 2, 
                        CollidesWith = 1u << 1
                    }
                };

                return physicsWorld.CastRay(ray);
            }


        }
    }


}

Working test

public class ECSTest : SystemBase
{
    protected override void OnUpdate()
    {
        var rayCastTest = new TestRayCast() { physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>().PhysicsWorld };
        float deltaTime = Time.DeltaTime;

        Entities.ForEach((ref Translation translation, ref Rotation rotation, ref ECSTestData ECSTestData) =>
        {



            if (rayCastTest.CheckRay(translation.Value, new float3(0, -1f, 0), 1f))
            {
                translation.Value = translation.Value + (new float3(0, 5f, 0));
            }
            else
            {
                translation.Value = translation.Value + (new float3(0, -1f, 0) * deltaTime);
            }


        }).Schedule();
    }


    private struct TestRayCast
    {
        [ReadOnly] public PhysicsWorld physicsWorld;

        public bool CheckRay(float3 position, float3 direction, float rayLength)
        {
            var ray = new RaycastInput()
            {
                Start = position,
                End = position + (direction * rayLength),
                Filter = new CollisionFilter()
                {
                    GroupIndex = 0,
                    BelongsTo = ~0u,
                    CollidesWith = 1u << 2
                }
            };

            return physicsWorld.CastRay(ray);
        }


    }
}

I solved it by getting a reference to the BuildPhysicsWorld system in OnCreate:

buildPhysicsWorldSystem = World.GetExistingSystem<BuildPhysicsWorld>();

And then after your job, you add its dependency to the BuildPhysicsWorld system:

buildPhysicsWorldSystem.AddInputDependencyToComplete(Dependency);
1 Like

Thanks that solved it.