#Rigidbody Dominance?

1 messages · Page 1 of 1 (latest)

placid swallow
#

Does the unity physics package support rigidbody dominance in any way? Where one rigidbody dynamic can affect another dynamic body but not vice-versa, for example a ship can affect and push the player around, but to the player the ship behaves as if its kinematic.

Alternatively are there any workaround to achieve something similar for a few specific entities.

pallid cedar
placid swallow
fossil cypress
#

You might be able to solve this with a job that modifies the rigidbody simulation right before it gets solved by the physics engine

Here's some example code in the ECS Physics samples project:
https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/PhysicsSamples/Assets/9. Modify/Contacts/ContactsSystem.cs

And here's a more general docs page on it:
https://docs.unity3d.com/Packages/com.unity.physics@1.0/manual/simulation-modification.html#modifying-simulation-results

Look for the place where we set the header.MassFactors in the sample code. This is where we customize the mass ratio between rigidbody A and rigidbody B in a collision. Here, if you detect that A is a ship and B is a player (either with component Lookup or with physics tags/categories), you can say that A has infinite mass compared to B

placid swallow
#

Funnily enough this is just what I did and got working (at least with my limited testing) about 5 minutes ago 😄

#

The code for anyone wondering, or wanting to roast/suggest improvements to the impl :)

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Physics;
using Unity.Physics.Systems;

public struct PhysicsDominance : IComponentData
{
    public byte Value;
}

[UpdateInGroup(typeof(PhysicsSimulationGroup))]
[UpdateAfter(typeof(PhysicsCreateContactsGroup))]
[UpdateBefore(typeof(PhysicsCreateJacobiansGroup))]
[BurstCompile]
public partial struct DominanceEnableMassFactorsSystem : ISystem
{
    [BurstCompile]
    private struct EnableMassFactorsJob : IContactsJob
    {
        public void Execute(ref ModifiableContactHeader manifold, ref ModifiableContactPoint contact)
        {
            manifold.JacobianFlags |= JacobianFlags.EnableMassFactors;
        }
    }

    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var simulationSingleton = SystemAPI.GetSingletonRW<SimulationSingleton>();
        var physicsWorldSingleton = SystemAPI.GetSingletonRW<PhysicsWorldSingleton>();

        state.Dependency = new EnableMassFactorsJob()
            .Schedule(simulationSingleton.ValueRW,
                ref physicsWorldSingleton.ValueRW.PhysicsWorld,
                state.Dependency);
    }
}

[UpdateInGroup(typeof(PhysicsSimulationGroup))]
[UpdateAfter(typeof(PhysicsCreateJacobiansGroup))]
[UpdateBefore(typeof(PhysicsSolveAndIntegrateGroup))]
[BurstCompile]
public partial struct DominanceMassFactorSystem : ISystem
{
    [BurstCompile]
    public void OnUpdate(ref SystemState state)
    {
        var dominanceLookup = state.GetComponentLookup<PhysicsDominance>();
        var simulationSingleton = SystemAPI.GetSingletonRW<SimulationSingleton>();
        var physicsWorldSingleton = SystemAPI.GetSingletonRW<PhysicsWorldSingleton>();

        state.Dependency = new DominanceJob
            {
                DominanceLookup = dominanceLookup
            }
            .Schedule(simulationSingleton.ValueRW,
                ref physicsWorldSingleton.ValueRW.PhysicsWorld,
                state.Dependency);
    }


    [BurstCompile]
    private struct DominanceJob : IJacobiansJob
    {
        [ReadOnly] public ComponentLookup<PhysicsDominance> DominanceLookup;

        // Don't do anything for triggers
        public void Execute(ref ModifiableJacobianHeader h, ref ModifiableTriggerJacobian j)
        {
        }

        [BurstCompile]
        public void Execute(ref ModifiableJacobianHeader jacHeader, ref ModifiableContactJacobian contactJacobian)
        {
            DominanceLookup.TryGetComponent(jacHeader.EntityA, out var dominanceA);
            DominanceLookup.TryGetComponent(jacHeader.EntityB, out var dominanceB);

            if (dominanceA.Value > dominanceB.Value)
            {
                var massFactors = new MassFactors
                {
                    InverseMassFactorA = 0,
                    InverseInertiaFactorA = 0,
                    InverseMassFactorB = jacHeader.MassFactors.InverseMassFactorB,
                    InverseInertiaFactorB = jacHeader.MassFactors.InverseInertiaFactorB
                };

                jacHeader.MassFactors = massFactors;
            }
            else if (dominanceB.Value > dominanceA.Value)
            {
                var massFactors = new MassFactors
                {
                    InverseMassFactorA = jacHeader.MassFactors.InverseMassFactorA,
                    InverseInertiaFactorA = jacHeader.MassFactors.InverseInertiaFactorA,
                    InverseMassFactorB = 0,
                    InverseInertiaFactorB = 0
                };

                jacHeader.MassFactors = massFactors;
            }
        }
    }
}