Skip to content

Instantly share code, notes, and snippets.

@nickedname
Last active July 13, 2022 04:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickedname/4c9997bc9ddb44686fe38ba5199802a1 to your computer and use it in GitHub Desktop.
Save nickedname/4c9997bc9ddb44686fe38ba5199802a1 to your computer and use it in GitHub Desktop.
Dependency Error
The system Unity.Physics.Systems.StepPhysicsWorld reads Player via PlatformSystem:SetContactFlagsJob but that type was not assigned to the Dependency property. To ensure correct behavior of other systems, the job or a dependency must be assigned to the Dependency property before returning from the OnUpdate method.
UnityEngine.Debug:LogError (object)
Unity.Debug:LogError (object) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/Stubs/Unity/Debug.cs:13)
Unity.Entities.SystemState:LogSafetyDetails (Unity.Entities.SystemDependencySafetyUtility/SafetyErrorDetails&,bool&) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/SystemState.cs:523)
Unity.Entities.SystemState:LogSafetyErrors () (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/SystemState.cs:509)
Unity.Entities.EntityManager/<>c:<Initialize>b__49_0 () (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/EntityManager.cs:233)
Unity.Jobs.LowLevel.Unsafe.JobsUtility:InvokePanicFunction ()
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle:CheckWriteAndThrowNoEarlyOut (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle)
Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle:CheckWriteAndThrow (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle)
Unity.Entities.ArchetypeChunk:GetComponentDataPtrRW<Unity.Transforms.LocalToWorld> (Unity.Entities.ComponentTypeHandle`1<Unity.Transforms.LocalToWorld>&) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/Iterators/ArchetypeChunkArray.cs:924)
Unity.Entities.InternalCompilerInterface:UnsafeGetChunkNativeArrayIntPtr<Unity.Transforms.LocalToWorld> (Unity.Entities.ArchetypeChunk,Unity.Entities.ComponentTypeHandle`1<Unity.Transforms.LocalToWorld>) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/CodeGeneratedJobForEach/InternalCompilerInterface.cs:65)
Game_System/Game_System_LambdaJob_1_Job:Execute (Unity.Entities.ArchetypeChunk,int) (at Temp/GeneratedCode/Assembly-CSharp/Game_System__System_388146053.g.cs:167)
Unity.Entities.JobEntityBatchExtensions:RunWithoutJobsInternal<Game_System/Game_System_LambdaJob_1_Job> (Game_System/Game_System_LambdaJob_1_Job&,Unity.Entities.Chunk**,int,Unity.Entities.EntityComponentStore*) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/IJobEntityBatch.cs:504)
Unity.Entities.JobEntityBatchExtensions:RunWithoutJobs<Game_System/Game_System_LambdaJob_1_Job> (Game_System/Game_System_LambdaJob_1_Job&,Unity.Entities.EntityQuery) (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/IJobEntityBatch.cs:546)
Game_System:Game_System_LambdaJob_1_Execute () (at Temp/GeneratedCode/Assembly-CSharp/Game_System__System_388146053.g.cs:190)
Game_System:OnUpdate () (at Assets/Scripts/Systems/Game_System.cs:75)
Unity.Entities.SystemBase:Update () (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/SystemBase.cs:400)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystemGroup.cs:583)
Unity.Entities.ComponentSystemGroup:OnUpdate () (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystemGroup.cs:523)
Unity.Entities.ComponentSystem:Update () (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ComponentSystem.cs:114)
Unity.Entities.ScriptBehaviourUpdateOrder/DummyDelegateWrapper:TriggerUpdate () (at Library/PackageCache/com.unity.entities@0.51.0-preview.32/Unity.Entities/ScriptBehaviourUpdateOrder.cs:426)
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Systems;
using UnityEngine;
public struct ModifyContactJacobians : IComponentData
{
public enum ModificationType
{
None,
SoftContact,
SurfaceVelocity,
InfiniteInertia,
BiggerInertia,
NoAngularEffects,
DisabledContact,
DisabledAngularFriction,
}
public ModificationType type;
}
[Serializable]
public class ModifyContactJacobiansBehaviour : MonoBehaviour, IConvertGameObjectToEntity
{
void IConvertGameObjectToEntity.Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
dstManager.AddComponentData(entity, new ModifyContactJacobians { type = ModificationType });
}
public ModifyContactJacobians.ModificationType ModificationType;
}
// A system which configures the simulation step to modify contact jacobains in various ways
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateBefore(typeof(StepPhysicsWorld))]
public partial class ModifyContactJacobiansSystem : SystemBase
{
StepPhysicsWorld m_StepPhysicsWorld;
SimulationCallbacks.Callback m_PreparationCallback;
SimulationCallbacks.Callback m_JacobianModificationCallback;
private static bool IsModificationType(ModifyContactJacobians.ModificationType typeToCheck,
ModifyContactJacobians.ModificationType typeOfA, ModifyContactJacobians.ModificationType typeOfB) => typeOfA == typeToCheck || typeOfB == typeToCheck;
protected override void OnCreate()
{
m_StepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
m_PreparationCallback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) =>
{
return new SetContactFlagsJob
{
modificationData = GetComponentDataFromEntity<ModifyContactJacobians>(true)
}.Schedule(simulation, ref world, inDeps);
};
m_JacobianModificationCallback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) =>
{
return new ModifyJacobiansJob
{
modificationData = GetComponentDataFromEntity<ModifyContactJacobians>(true)
}.Schedule(simulation, ref world, inDeps);
};
RequireForUpdate(GetEntityQuery(new EntityQueryDesc
{
All = new ComponentType[] { typeof(ModifyContactJacobians) }
}));
}
// This job reads the modify component and sets some data on the contact, to get propagated to the jacobian
// for processing in our jacobian modifier job. This is necessary because some flags require extra data to
// be allocated along with the jacobian (e.g., SurfaceVelocity data typically does not exist). We also set
// user data bits in the jacobianFlags to save us from looking up the ComponentDataFromEntity later.
[BurstCompile]
struct SetContactFlagsJob : IContactsJob
{
[ReadOnly]
public ComponentDataFromEntity<ModifyContactJacobians> modificationData;
public void Execute(ref ModifiableContactHeader manifold, ref ModifiableContactPoint contact)
{
Entity entityA = manifold.EntityA;
Entity entityB = manifold.EntityB;
ModifyContactJacobians.ModificationType typeA = ModifyContactJacobians.ModificationType.None;
if (modificationData.HasComponent(entityA))
{
typeA = modificationData[entityA].type;
}
ModifyContactJacobians.ModificationType typeB = ModifyContactJacobians.ModificationType.None;
if (modificationData.HasComponent(entityB))
{
typeB = modificationData[entityB].type;
}
if (IsModificationType(ModifyContactJacobians.ModificationType.SurfaceVelocity, typeA, typeB))
{
manifold.JacobianFlags |= JacobianFlags.EnableSurfaceVelocity;
}
if (IsModificationType(ModifyContactJacobians.ModificationType.InfiniteInertia, typeA, typeB) ||
IsModificationType(ModifyContactJacobians.ModificationType.BiggerInertia, typeA, typeB))
{
manifold.JacobianFlags |= JacobianFlags.EnableMassFactors;
}
}
}
[BurstCompile]
struct ModifyJacobiansJob : IJacobiansJob
{
[ReadOnly]
public ComponentDataFromEntity<ModifyContactJacobians> modificationData;
// Don't do anything for triggers
public void Execute(ref ModifiableJacobianHeader h, ref ModifiableTriggerJacobian j) { }
public void Execute(ref ModifiableJacobianHeader jacHeader, ref ModifiableContactJacobian contactJacobian)
{
Entity entityA = jacHeader.EntityA;
Entity entityB = jacHeader.EntityB;
ModifyContactJacobians.ModificationType typeA = ModifyContactJacobians.ModificationType.None;
if (modificationData.HasComponent(entityA))
{
typeA = modificationData[entityA].type;
}
ModifyContactJacobians.ModificationType typeB = ModifyContactJacobians.ModificationType.None;
if (modificationData.HasComponent(entityB))
{
typeB = modificationData[entityB].type;
}
{
// Check for jacobians we want to ignore:
if (IsModificationType(ModifyContactJacobians.ModificationType.DisabledContact, typeA, typeB))
{
jacHeader.Flags = jacHeader.Flags | JacobianFlags.Disabled;
}
// Check if NoTorque modifier, or friction should be disabled through jacobian
if (IsModificationType(ModifyContactJacobians.ModificationType.NoAngularEffects, typeA, typeB) ||
IsModificationType(ModifyContactJacobians.ModificationType.DisabledAngularFriction, typeA, typeB))
{
// Disable all friction angular effects
var friction0 = contactJacobian.Friction0;
friction0.AngularA = 0.0f;
friction0.AngularB = 0.0f;
contactJacobian.Friction0 = friction0;
var friction1 = contactJacobian.Friction1;
friction1.AngularA = 0.0f;
friction1.AngularB = 0.0f;
contactJacobian.Friction1 = friction1;
var angularFriction = contactJacobian.AngularFriction;
angularFriction.AngularA = 0.0f;
angularFriction.AngularB = 0.0f;
contactJacobian.AngularFriction = angularFriction;
}
// Check if SurfaceVelocity present
if (jacHeader.HasSurfaceVelocity && IsModificationType(ModifyContactJacobians.ModificationType.SurfaceVelocity, typeA, typeB))
{
// Since surface normal can change, make sure angular velocity is always relative to it, not independent
jacHeader.SurfaceVelocity = new SurfaceVelocity
{
LinearVelocity = float3.zero,
AngularVelocity = contactJacobian.Normal * (new float3(0.0f, 1.0f, 0.0f))
};
}
// Check if MassFactors present and we should make inertia infinite
if (jacHeader.HasMassFactors && IsModificationType(ModifyContactJacobians.ModificationType.InfiniteInertia, typeA, typeB))
{
// Give both bodies infinite inertia
jacHeader.MassFactors = new MassFactors
{
InverseInertiaFactorA = float3.zero,
InverseMassFactorA = 1.0f,
InverseInertiaFactorB = float3.zero,
InverseMassFactorB = 1.0f
};
}
// Check if MassFactors present and we should make inertia 10x bigger
if (jacHeader.HasMassFactors && IsModificationType(ModifyContactJacobians.ModificationType.BiggerInertia, typeA, typeB))
{
// Give both bodies 10x bigger inertia
jacHeader.MassFactors = new MassFactors
{
InverseInertiaFactorA = new float3(0.1f),
InverseMassFactorA = 1.0f,
InverseInertiaFactorB = new float3(0.1f),
InverseMassFactorB = 1.0f
};
}
}
// Angular jacobian modifications
for (int i = 0; i < contactJacobian.NumContacts; i++)
{
ContactJacAngAndVelToReachCp jacobianAngular = jacHeader.GetAngularJacobian(i);
// Check if NoTorque modifier
if (IsModificationType(ModifyContactJacobians.ModificationType.NoAngularEffects, typeA, typeB))
{
// Disable all angular effects
jacobianAngular.Jac.AngularA = 0.0f;
jacobianAngular.Jac.AngularB = 0.0f;
}
// Check if SoftContact modifier
if (IsModificationType(ModifyContactJacobians.ModificationType.SoftContact, typeA, typeB))
{
jacobianAngular.Jac.EffectiveMass *= 0.1f;
if (jacobianAngular.VelToReachCp > 0.0f)
{
jacobianAngular.VelToReachCp *= 0.5f;
}
}
jacHeader.SetAngularJacobian(i, jacobianAngular);
}
}
}
protected override void OnUpdate()
{
if (m_StepPhysicsWorld.Simulation.Type == SimulationType.NoPhysics) return;
m_StepPhysicsWorld.EnqueueCallback(SimulationCallbacks.Phase.PostCreateContacts, m_PreparationCallback, Dependency);
m_StepPhysicsWorld.EnqueueCallback(SimulationCallbacks.Phase.PostCreateContactJacobians, m_JacobianModificationCallback, Dependency);
Dependency = Entities.ForEach(( ref ModifyContactJacobians contactJacobians) =>
{
//just for testing
}).Schedule(Dependency);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Physics;
using Unity.Collections;
using Unity.Mathematics;
using System;
using Unity.Transforms;
using Unity.Physics.Systems;
using Unity.Jobs;
using MeshCollider = Unity.Physics.MeshCollider;
using Unity.Burst;
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateBefore(typeof(StepPhysicsWorld))]
public partial class PlatformSystem : SystemBase
{
BuildPhysicsWorld buildPhysicsWorld;
StepPhysicsWorld stepPhysicsWorld;
SimulationCallbacks.Callback beforePhysicsCallback;
protected override void OnCreate()
{
buildPhysicsWorld = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
stepPhysicsWorld = World.DefaultGameObjectInjectionWorld.GetExistingSystem<StepPhysicsWorld>();
beforePhysicsCallback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) =>
{
SetContactFlagsJob contactFlagsJob = new SetContactFlagsJob
{
worldTransformComponents = GetComponentDataFromEntity<LocalToWorld>(true),
physicsVelocityComponent = GetComponentDataFromEntity<PhysicsVelocity>(true),
playerComponents = GetComponentDataFromEntity<Player>(true),
platformComponents = GetComponentDataFromEntity<Platform>(true),
};
return contactFlagsJob.Schedule(simulation, ref world, inDeps);
};
}
//requires modifying IContactsJob and IJacobiansJob
//Set flag for when collision is in the direction of the given normal
//[BurstCompile(Debug = true)]
[BurstCompile]
struct SetContactFlagsJob : IContactsJob
{
//public PhysicsWorld physicsWorld;
//public SimulationStepInput input;
[ReadOnly]
public ComponentDataFromEntity<Player> playerComponents;
[ReadOnly]
public ComponentDataFromEntity<Platform> platformComponents;
[ReadOnly]
public ComponentDataFromEntity<LocalToWorld> worldTransformComponents;
[ReadOnly]
public ComponentDataFromEntity<PhysicsVelocity> physicsVelocityComponent;
public void Execute(ref ModifiableContactHeader header, ref ModifiableContactPoint contact)
{
bool isPlatformA = platformComponents.HasComponent(header.EntityA);
bool isPlatformB = platformComponents.HasComponent(header.EntityB);
Entity platformEntity = isPlatformA ? header.EntityA : (isPlatformB ? header.EntityB : Entity.Null);
if (platformEntity == Entity.Null)
return;
bool isPlayerA = playerComponents.HasComponent(header.EntityA);
bool isPlayerB = playerComponents.HasComponent(header.EntityB);
Entity playerEntity = isPlayerA ? header.EntityA : (isPlayerB ? header.EntityB : Entity.Null);
if (playerEntity == Entity.Null)
return;
bool validPosition = false;
{
LocalToWorld platformPosition = worldTransformComponents[platformEntity];
float3 up = platformPosition.Up;
//this collision is ABOVE the platform
if (math.dot(header.Normal, up) > 0)
{
validPosition = true;
}
}
bool entering = false;
{
PhysicsVelocity playerVelocity = physicsVelocityComponent[playerEntity];
//check if vectors are in opposing direction
if (math.dot(header.Normal, playerVelocity.Linear) < 0)
{
entering = true;
}
}
bool overlap = false;
{
//penetration depth is smaller than 0.1 (also why is contact.distance negative?)
if (contact.Distance < -0.1)
{
overlap = true;
}
}
if (!entering || !validPosition || overlap)
{
header.JacobianFlags = JacobianFlags.Disabled;
}
}
}
protected override void OnUpdate()
{
if (stepPhysicsWorld.Simulation.Type == SimulationType.NoPhysics) return;
stepPhysicsWorld.EnqueueCallback(SimulationCallbacks.Phase.PostCreateContacts, beforePhysicsCallback, Dependency);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment