[SOLVED]Sample scene 2b1 not working

Hello,

I played with physics this weekend with no success.
So I try sample scene 2b1 which is close to what I want earlier but this sample is broken.
Is it known ? Do I have to report a bug ?

Hi! Can you be more specific about what is broken in the sample? In this particular case, the simulation will not stabilize, so it is expected that things do not stay in balance, and instead will ultimately fall.

Hi :slight_smile:

I misunderstood the purpose of this sample then, I assumed simulation will stabilized. ok Thanks

I tried this scene because during my tests something goes wrong, I tried to stack cubes and they always slide away whatever settings I tweak .
With Physix engine, in GO world, stack blocks works directly :frowning:

Unity Physics, being stateless does not cache friction impulses from frame to frame. This leads to an accumulation of errors and the unstable stacking drift you are seeing. You can 2 options.

  • Download the Havok Physics for Unity package from Package Manager and switch the “Simulation Type” of the “Physics Step” component on the “Physics Scene Basic Elements > Physics Settings” node. 5837125--619330--upload_2020-5-12_13-52-9.png
    Havok Physics, replaces the simulation backed to a cached version where stacking of the boxes will work as in the GO world. However, the multi-sphere balance is inherently unstable without a high Damping/Drag factor.
  • If sticking with Unity Physics you can clip out small velocities using the following system. I recommend adding the ClipMotionAuthoring component to the same “Physics Settings” node. This approach does have issues. The thresholds are independent of mass so if set for light bodies then stacked heavy bodies will still drift. If set for heavier bodies, lighter bodies will clip to unrealistic orientations. We are working on a better version of this system that work within the simulation, but this might get you want you need now.
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 class ClipMotionAuthoring : MonoBehaviour
{
    //public bool EnableSystem = false;
    public float LinearThreshold = 1E-4f;
    public float AngularThreshold = 1E-6f;

    ClipMotionAuthoring() { }

    private void OnEnable() { OnValidate(); }

    void OnValidate()
    {
        var world = BasePhysicsDemo.DefaultWorld;
        if (world != null)
        {
            var system = BasePhysicsDemo.DefaultWorld.GetOrCreateSystem<ClipMotionSystem>();
            if (system != null)
            {
                system.Enabled = this.enabled;
                system.LinearThreshold = LinearThreshold;
                system.AngularThreshold = AngularThreshold;
            }
        }
    }
}


[AlwaysUpdateSystem]
[UpdateBefore(typeof(StepPhysicsWorld))]
public class ClipMotionSystem : JobComponentSystem
{
    public float LinearThreshold = 1E-4f;
    public float AngularThreshold = 1E-6f;

    StepPhysicsWorld m_stepPhysicsWorld;

    protected override void OnCreate()
    {
        Enabled = false;
        m_stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
    }

    [BurstCompile]
    struct ClipMotionDataJob : IJobParallelFor
    {
        public float linearThreshold;
        public float angularThreshold;
        public float3 gravityDir;

        public NativeSlice<MotionVelocity> MotionVelocities;

        public void Execute(int index)
        {
            var pm = MotionVelocities[index];

            float3 linearEnergy = 0.5f * math.rcp(pm.InverseMass) * (pm.LinearVelocity * pm.LinearVelocity);
            float3 angularEnergy = 0.5f * math.rcp(pm.InverseInertia) * (pm.AngularVelocity* pm.AngularVelocity);

            if (math.lengthsq(linearEnergy) < linearThreshold)
            {
                var gravityComponent = math.dot(pm.LinearVelocity, gravityDir) * gravityDir;
                pm.LinearVelocity = gravityComponent;
                if (math.lengthsq(angularEnergy) < angularThreshold)
                {
                    pm.AngularVelocity = float3.zero;
                }
            }

            MotionVelocities[index] = pm;
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        if (Enabled)
        {
            SimulationCallbacks.Callback clipMotionsCallback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) =>
            {
                return new ClipMotionDataJob
                {
                    gravityDir = math.normalizesafe(GetSingleton<PhysicsStep>().Gravity),
                    linearThreshold = LinearThreshold,
                    angularThreshold = AngularThreshold,
                    MotionVelocities = world.MotionVelocities,
                }.Schedule(world.NumDynamicBodies, 64, inDeps);
            };
            m_stepPhysicsWorld.EnqueueCallback(SimulationCallbacks.Phase.PostSolveJacobians, clipMotionsCallback, inputDeps);
        }

        return inputDeps;
    }
}
2 Likes

Oh I will try that, thanks for hints !