I am trying to make limit my player’s jumping when he is not colliding with the floor
Here’s my system for doing this:
[UpdateBefore(typeof(PhysicsStep))]
public class TogglePLinearImpulseOnFloorCollisionSystem : JobComponentSystem
{
EntityQuery FloorGroup;
EntityQuery CharacterGroup;
BuildPhysicsWorld buildPhysicsWorld;
StepPhysicsWorld stepPhysicsWorld;
protected override void OnCreate()
{
FloorGroup = GetEntityQuery(typeof(FloorTag));
CharacterGroup = GetEntityQuery(typeof(ToggleInputLinearImpulseOnFloorCollisionTag));
base.OnCreate();
buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var jobHandle = new TogglePLinearImpulseOnFloorCollisionJob()
{
FloorGroup = GetComponentDataFromEntity<FloorTag>(true),
CharacterGroup = GetComponentDataFromEntity<ToggleInputLinearImpulseOnFloorCollisionTag>(true),
PLinearImpulseGroup = GetComponentDataFromEntity<PLinearImpulse>()
}.Schedule(stepPhysicsWorld.Simulation, ref buildPhysicsWorld.PhysicsWorld, inputDeps, stepPhysicsWorld.FinalSimulationJobHandle);
return jobHandle;
}
}
I get no result except for this error:
InvalidOperationException: The previously scheduled job HavokSimulation:SyncJob reads from the Unity.Collections.NativeArray`1[Unity.Physics.MotionVelocity] SyncJob.World.DynamicsWorld.m_MotionVelocities. You are trying to schedule a new job Solver:ParallelApplyGravityAndCopyInputVelocitiesJob, which writes to the same Unity.Collections.NativeArray`1[Unity.Physics.MotionVelocity] (via ParallelApplyGravityAndCopyInputVelocitiesJob.MotionVelocities). To guarantee safety, you must include HavokSimulation:SyncJob as a dependency of the
There is also a compiler error despite having the reference in the assembly definition:
stepPhysicsWorld.FinalSimulationJobHandle -> Unity.Physics.IBodyPairsJobExtensions.HAVOK_PHYSICS_MISSING_FROM_ASMDEF
Hey guys, I found the solution.
Mistake number 1: [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
should be used instead of [UpdateBefore(typeof(PhysicsStep))]
.
Mistake number 2: no need for FinalSimulationJobHandle
.
Mistake number 3: A JobHandle
should be completed before being returned, as it needs to finish before the next physics step. ( jobHandle.Complete()
)
I’m posting the full final code of the script, as I don’t want anyone else to frustrate over this:
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
public class TogglePLinearImpulseOnFloorCollisionSystem : JobComponentSystem
{
EntityQuery FloorGroup;
EntityQuery CharacterGroup;
BuildPhysicsWorld buildPhysicsWorld;
StepPhysicsWorld stepPhysicsWorld;
protected override void OnCreate()
{
base.OnCreate();
FloorGroup = GetEntityQuery(typeof(FloorTag));
CharacterGroup = GetEntityQuery(typeof(ToggleInputLinearImpulseOnFloorCollisionTag));
buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
var jobHandle = new TogglePLinearImpulseOnFloorCollisionJob()
{
FloorGroup = GetComponentDataFromEntity<FloorTag>(true),
CharacterGroup = GetComponentDataFromEntity<ToggleInputLinearImpulseOnFloorCollisionTag>(true),
PLinearImpulseGroup = GetComponentDataFromEntity<PLinearImpulse>()
}.Schedule(stepPhysicsWorld.Simulation, ref buildPhysicsWorld.PhysicsWorld, inputDeps);
jobHandle.Complete();
return jobHandle;
}
}
[BurstCompile]
struct TogglePLinearImpulseOnFloorCollisionJob : ICollisionEventsJobBase
{
[ReadOnly] public ComponentDataFromEntity<FloorTag> FloorGroup;
[ReadOnly] public ComponentDataFromEntity<ToggleInputLinearImpulseOnFloorCollisionTag> CharacterGroup;
public ComponentDataFromEntity<PLinearImpulse> PLinearImpulseGroup;
public void Execute(CollisionEvent collisionEvent)
{
var entityA = collisionEvent.EntityA;
var entityB = collisionEvent.EntityB;
var bodyAIsCharacter = CharacterGroup.HasComponent(entityA);
var bodyBIsCharacter = CharacterGroup.HasComponent(entityB);
var bodyAIsFloor = FloorGroup.HasComponent(entityA);
var bodyBIsFloor = FloorGroup.HasComponent(entityB);
var collisionCase =
(Convert.ToByte(bodyAIsFloor) << 0) +
(Convert.ToByte(bodyBIsFloor) << 1) +
(Convert.ToByte(bodyAIsCharacter) << 2) +
(Convert.ToByte(bodyBIsCharacter) << 3);
var pLinearImpulseComponent = new PLinearImpulse();
switch (collisionCase)
{
case (1 << 0) + (1 << 3):
pLinearImpulseComponent = PLinearImpulseGroup[entityB];
pLinearImpulseComponent.CanImpulse = true;
PLinearImpulseGroup[entityB] = pLinearImpulseComponent;
break;
case (1 << 1) + (1 << 2):
pLinearImpulseComponent = PLinearImpulseGroup[entityA];
pLinearImpulseComponent.CanImpulse = true;
PLinearImpulseGroup[entityA] = pLinearImpulseComponent;
break;
}
}
}