Hello, I am trying to make a character controller in pure ECS and I am having a lot of trouble getting a capsule cast to work, I have tried every example I can and I just can't get any combination to work.
Here is my code so you can see what I am trying:
using Unity.Entities; using Unity.Jobs; using Unity.Transforms; using Unity.Mathematics; using Unity.Physics; public class CharacterControllerSystem : JobComponentSystem { protected unsafe override JobHandle OnUpdate(JobHandle inputDeps) { JobHandle job = Entities.ForEach((ref CharacterControllerData characterController, ref Translation translation, in PhysicsCollider collider) => { var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem();
var collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld;
var filter = new CollisionFilter()
{
BelongsTo = ~0u,
CollidesWith = ~0u,
GroupIndex = 0
};
CapsuleGeometry capsuleGeometry = new CapsuleGeometry() { Vertex0 =translation.Value, Vertex1 = translation.Value + new float3(0,1,0), Radius = .2f};
BlobAssetReference capsuleCollider = CapsuleCollider.Create(capsuleGeometry, filter);
var input = new ColliderCastInput()
{
Collider = (Collider*)capsuleCollider.GetUnsafePtr(),
Orientation = quaternion.identity,
Start = translation.Value,
End = translation.Value + new float3(0, -100, 0),
};
ColliderCastHit hit = new ColliderCastHit();
if (collisionWorld.CastCollider(input, out hit))
translation.Value = hit.Position;
characterController.moveDelta = float3.zero;
}).Schedule(inputDeps);
job.Complete();
return inputDeps;
}
}
I realize that I could probably get it to work on the main thread but I want it to be as performant as possible, thus running it in a job. I know that the code can run in a job because I have seen examples but I don't know why it's not working here. The current error I am getting is:
InvalidOperationException: The native container has been declared as [WriteOnly] in the job, but you are reading from it.
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <23a7799da2e941b88c6db790c607d655>:0)
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckReadAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <23a7799da2e941b88c6db790c607d655>:0)
Unity.Collections.LowLevel.Unsafe.NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr[T] (Unity.Collections.NativeArray`1[T] nativeArray) (at <23a7799da2e941b88c6db790c607d655>:0)
Unity.Physics.BoundingVolumeHierarchy..ctor (Unity.Collections.NativeArray`1[T] nodes, Unity.Collections.NativeArray`1[T] nodeFilters) (at Library/PackageCache/com.unity.physics@0.3.2-preview/Unity.Physics/Collision/Geometry/BoundingVolumeHierarchy.cs:26)
Unity.Physics.Broadphase+Tree.get_BoundingVolumeHierarchy () (at Library/PackageCache/com.unity.physics@0.3.2-preview/Unity.Physics/Collision/World/Broadphase.cs:359)
Unity.Physics.Broadphase.CastCollider[T] (Unity.Physics.ColliderCastInput input, Unity.Collections.NativeSlice`1[T] rigidBodies, T& collector) (at Library/PackageCache/com.unity.physics@0.3.2-preview/Unity.Physics/Collision/World/Broadphase.cs:524)
Unity.Physics.CollisionWorld.CastCollider[T] (Unity.Physics.ColliderCastInput input, T& collector) (at Library/PackageCache/com.unity.physics@0.3.2-preview/Unity.Physics/Collision/World/CollisionWorld.cs:209)
Unity.Physics.QueryWrappers.ColliderCast[T] (T& target, Unity.Physics.ColliderCastInput input, Unity.Physics.ColliderCastHit& result) (at Library/PackageCache/com.unity.physics@0.3.2-preview/Unity.Physics/Collision/Queries/Collidable.cs:134)
Unity.Physics.CollisionWorld.CastCollider (Unity.Physics.ColliderCastInput input, Unity.Physics.ColliderCastHit& closestHit) (at Library/PackageCache/com.unity.physics@0.3.2-preview/Unity.Physics/Collision/World/CollisionWorld.cs:205)
CharacterControllerSystem+<>c__DisplayClass_OnUpdate_LambdaJob0.OriginalLambdaBody (CharacterControllerData& characterController, Unity.Transforms.Translation& translation, Unity.Physics.PhysicsCollider& collider) (at Assets/Scripts/Systems/CharacterControllerSystem.cs:38)
CharacterControllerSystem+<>c__DisplayClass_OnUpdate_LambdaJob0.IterateEntities (Unity.Entities.ArchetypeChunk& chunk, CharacterControllerSystem+<>c__DisplayClass_OnUpdate_LambdaJob0+LambdaParameterValueProviders+Runtimes& runtimes) (at <77b6acafb1f146aca4bbf50c83211b59>:0)
CharacterControllerSystem+<>c__DisplayClass_OnUpdate_LambdaJob0.Execute (Unity.Entities.ArchetypeChunk chunk, System.Int32 chunkIndex, System.Int32 firstEntityIndex) (at <77b6acafb1f146aca4bbf50c83211b59>:0)
Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].ExecuteInternal (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.11.0-preview.7/Unity.Entities/IJobChunk.cs:275)
Unity.Entities.JobChunkExtensions+JobChunkProducer`1[T].Execute (Unity.Entities.JobChunkExtensions+JobChunkWrapper`1[T]& jobWrapper, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at Library/PackageCache/com.unity.entities@0.11.0-preview.7/Unity.Entities/IJobChunk.cs:249)
Is there a better way to do it that is still performant and could work in a component?
Here is my code so you can see what I am trying:
using Unity.Entities; using Unity.Jobs; using Unity.Transforms; using Unity.Mathematics; using Unity.Physics; public class CharacterControllerSystem : JobComponentSystem { protected unsafe override JobHandle OnUpdate(JobHandle inputDeps) { JobHandle job = Entities.ForEach((ref CharacterControllerData characterController, ref Translation translation, in PhysicsCollider collider) => { var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem