Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Physics gone wild

Discussion in 'Physics for ECS' started by snacktime, Jul 24, 2020.

  1. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I'm finding it very easy to trigger some sort of cascading reaction with dynamic bodies where it looks like the resolver just goes wild and then Unity goes into a death spiral. Quickly chewing up more and more memory and the editor is too busy to get out of play mode, just have to hard kill Unity.

    This only happens when bodies are colliding, and all my tests have been dynamic colliding with kinematic or static.

    Joints seem to be a common thread but can't say for sure. I would think the memory usage would be a clue.

    Going to create a build see how it acts there, but any ideas on where to look?
     
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Are these joints really complex or simple ones? Also, do they have collisions enabled?

    Also take a look at safety checks, some of them tend to get slower or consume more memory over time, so make sure they are disabled when looking at performance in the editor.
     
  3. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Check with the JobsDebugger off as well. The other thing to check is to make sure that there isn't accidentally a PhysicsShape that is a dynamic mesh. If dynamic meshes start overlapping you will get a ridiculous spike in contacts.
     
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Simple single fixed joint no collision. Disabling safety/leak detection/jobs debugger didn't make a significant difference.

    I didn't get around to testing it in a build, partly because I remembered the testing tools to setup the scenario were editor only and before I fixed that I changed direction in design.

    Colliders involved were convex hulls and our kinematic character controller that uses SimplexSolver.

    What it looked like visually is the bodies connected via joints oscillated quickly for the first second or so then it all slows to a crawl as framerate plunges. The character controller got pushed away fairly quickly so was no longer involved in whatever reaction was going on. Could very well be something editor specific that is slow enough to push it all over the edge.
     
  5. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Any chance of getting a repro scene?
    If the Joints are leading to divergent oscillations then the bodies will likely have massive velocities, leading to massive AABBs and so overlapping/colliding with everything else! Debug draw could help with Unity Physics, or the VDB would help visualize the problem with Havok Physics.
     
  6. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,227
    I want to say that ever since the last update, my collisions have been causing brutal spikes as seen in the images below.

    It typically ends up happening when one vehicle runs into another, the vehicles always end up overlapping/intersecting and it goes nuts. I don't believe I have changed much, if anything related to that recently, but I have yet to figure out what to do about it exactly. I certainly don't want the vehicles to intersect, and most definitely don't want the spikes like this, but I don't really have anything custom going on. I am simply moving them through a list of waypoints using a pretty basic job.

    Did something change anytime recently that might cause the settings I am using (seen under Additional Images) for my vehicle physics body and shape to become no longer ideal?

    Code (CSharp):
    1. [BurstCompile(FloatMode = FloatMode.Fast)]
    2.         private struct VehicleMoveJob : IJobChunk
    3.         {
    4.             [ReadOnly] public float dT;
    5.             public Unity.Entities.ComponentTypeHandle<Rotation> rotationType;
    6.             public Unity.Entities.ComponentTypeHandle<Translation> translationType;
    7.             [ReadOnly] public Unity.Entities.ComponentTypeHandle<VehicleTag> vehicleTagType;
    8.             [ReadOnly] public Unity.Entities.ComponentTypeHandle<MoveSpeed> vehicleSpeedType;
    9.             [ReadOnly] public Unity.Entities.ComponentTypeHandle<WaypointData> vehicleDataType;
    10.             [ReadOnly] public Unity.Entities.ComponentTypeHandle<SettingData> vehicleSettingsType;
    11.             [ReadOnly] public Unity.Entities.ComponentTypeHandle<WPMoveStatus> vehicleMoveStatusType;
    12.  
    13.             public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
    14.             {
    15.                 var chunkRotation = chunk.GetNativeArray(rotationType);
    16.                 var chunkPosition = chunk.GetNativeArray(translationType);
    17.                 var chunkSetting = chunk.GetNativeArray(vehicleSettingsType);
    18.                 var chunkVehicleData = chunk.GetNativeArray(vehicleDataType);
    19.                 var chunkVehicleSpeed = chunk.GetNativeArray(vehicleSpeedType);
    20.                 var chunkMoveStatus = chunk.GetNativeArray(vehicleMoveStatusType);
    21.  
    22.                 for (var i = 0; i < chunk.Count; i++)
    23.                 {
    24.                     var rotation = chunkRotation[i];
    25.                     var position = chunkPosition[i];
    26.                     var vehicleSetting = chunkSetting[i];
    27.                     var vehicleData = chunkVehicleData[i];
    28.                     var vehicleStatus = chunkMoveStatus[i];
    29.                     var vehicleSpeed = chunkVehicleSpeed[i];
    30.  
    31.                     if (vehicleStatus.movementStatus == MovementStatus.Moving)
    32.                     {
    33.                         float3 movement = position.Value;
    34.                         var direction = vehicleData.currentWaypoint.Position - movement;
    35.                         var lookRotation = quaternion.LookRotation(direction, new float3(0, 1, 0));
    36.                         rotation.Value = math.slerp(rotation.Value, lookRotation, vehicleSetting.CurrentTurnSpeed);
    37.                         position.Value += dT * vehicleSpeed.speed * math.forward(lookRotation);
    38.                         chunkRotation[i] = rotation;
    39.                         chunkPosition[i] = position;
    40.                     }
    41.                 }
    42.             }
    43.         }






    (Sorry for the overlap in the physics body GUI, still not quite sure why it ends up doing that)
     
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Watch out for Nan's. So far I've tracked all our cases of physics exploding back to that.
     
  8. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Also noticed that you move your vehicles by setting their position. That is risky as it can result in penetrations and possibly spikes that you are seeing, before physics expects to move bodies by a provided velocity, not set it's transform to a totally arbitrary position. How about instead you just set the velocity and let physics move them in a safe way? You can check https://github.com/Unity-Technologi...ts/Demos/5. Modify/5e. Kinematic Motion.unity to see the effect on each of the approaches. Note that all these apply to dynamic bodies as well as kinematic ones.
     
    MostHated likes this.
  9. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,227
    I will definitely give that a try, thanks!
     
    petarmHavok likes this.
  10. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,227
    ------ Edit--- At least I am headed in the right direction. Found a few mistakes in my original reply. Getting pretty close, but not quite there yet.

    Code (CSharp):
    1. float3 translation = position.Value;
    2. var direction = vehicleData.currentWaypoint.Position - translation;
    3. var lookRotation = quaternion.LookRotation(direction, new float3(0, 1, 0));
    4. rotation.Value = math.slerp(rotation.Value, lookRotation, vehicleSetting.CurrentTurnSpeed);
    5.                
    6. pvd.ApplyLinearImpulse(pmd, math.mul(rotation.Value, new float3(0, 0, (vehicleSpeed.speed * speedMultiplier)*dT)));
    7. chunkPVD[i] = pvd;
    8. chunkRotation[i] = rotation;
    I am going to have to try and find some more examples that are a bit more in line with the type of movement I am trying to achieve, or at least tweak things a lot because there ends up being a lot of missing/overshooting the waypoints and doing circles to try and get to it properly.



    -------------------- Original reply
    This didn't quite turn out how I expected, lol. I am not sure if I am doing this properly. It's strange, the vehicle would sit there, then I move the mouse a bit and it would move about 1cm, and then as seen below it tends to go forward a bit then stops.

    I am guessing I am doing something incorrectly in this? It is being done in an IJobChunk currently, am I supposed to be writing back the position? I tried just having the ApplyImpulse without writing back rotation, which then had no rotation, so it seems like I still need to write that back, but the velocity is applied without writing it back, just... not consistently, it seems.

    I saw some examples using UpdateAfter BuildPhysicsWorld, but I tried that and then nothing seemed to be applied.

    https://gist.github.com/instance-id/a2fac0c9f004ef426ec8401b47ff6277

     
    Last edited: Aug 19, 2020
  11. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
  12. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,227
    I had made an edit to my post yesterday, I had got the stuff from the video all worked out luckily.

    I was just testing out things to see how they worked, such as PhysicsVelocity.CalculateVelocityToTarget(), which was fairly accurate but with inconsistent movement and ended up looking like each vehicle was being shot from one waypoint to another:



    and the current that I was testing, which is more like an underground drift competition in downtown Japan.:

    Code (CSharp):
    1. float3 translation = position.Value;
    2. var direction = vehicleData.currentWaypoint.Position - translation;
    3. var lookRotation = quaternion.LookRotation(direction, new float3(0, 1, 0));
    4. rotation.Value = math.slerp(rotation.Value, lookRotation, vehicleSetting.CurrentTurnSpeed);
    5.  
    6.  
    7. var impulse = math.mul(rotation.Value, new float3(0, 0, (vehicleSpeed.speed * speedMultiplier)*dT));
    8. ComponentExtensions.ApplyImpulse(ref pvd, pmd, position, rotation, impulse, translation);
    9. chunkPVD[i] = pvd;
    10. chunkRotation[i] = rotation;
    11.  



    I am mostly now just trying to find a good middle ground. I much prefer the consistent movement that I had initially when manually setting the position each frame, but with the collision results from applying velocity to the entity. I am going to be looking around for some more examples in random repos that I come across to see if I can find anything that might help out and get a bit closer to the results I am after.
     
    petarmHavok likes this.