Search Unity

Using WheelColliders on dynamic terrain or rigidbodies

Discussion in 'Physics' started by strich, Jan 26, 2017.

  1. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    374
    Scenario: A sim game with vehicles that will be interacting with terrains that will be dynamically modified at runtime as well as moving rigidbodies (logs, rocks, etc).

    Thus far I have been running tests with a player controlled 4W vehicle that modifies the terrain around and under the wheels. I started with barebones Unity components and have since moved to Edys Vehicle Physics. However I believe the underlying issue I'm having has a root cause closer to the actual PhysX implementation.

    I am finding I am having some annoying stability issues with dynamic terrain modifications under the wheelcolliders, even when the modified area of terrain is not near the wheels. IE the process of reprocessing the terrain heights is causing problems.

    Issue 1: Put a vehicle on a terrain, run the game, modify the terrain using the Unity terrain brushes (It doesn't have to actually adjust height at all, only cause a modification). What will happen is the WheelHit for the frame after will have a big hitForce on it. HitForce can be used for various calculations and can cause player input problems further upstream.

    Issue 2: When I do modify the terrain directly under a wheel I'd like to avoid with wheel losing ground contact - Loosing ground contact kills various calcs around friction, etc and causes player feedback issues. I have noticed that if I modify the terrain at runtime via the unity terrain brushes this mostly works - I can tweak the terrain height down and the wheelcollider won't loose ground contact, within reason. This is great. But with my own code tests I am finding it much less likely to stay grounded. I am wondering if I am not running the terrain changes at the right time in the frame.
    Should terrain height modifications be done in FixedUpdate? Will the terrain change occur prior to the wheelcollider resolving its string movement and running the ground check?

    I've been trying to read through the underlying PhysX documentation for heightfields in an attempt to identify any best practice nuggets with dynamic terrains with little luck. Is there maybe a better physics shape I should be using instead of the one used with the terrain system?
     
  2. CookieSalad

    CookieSalad

    Unity Technologies

    Joined:
    Dec 29, 2014
    Posts:
    24
    Hey!

    Thanks for the feedback!

    Could you please provide us with a repro project using the Bug Reporter that would allow us to reproduce the issues locally? The project doesn't need need to be complicated, in fact the simpler it is, the better. Then you can leave a reply with the bug report numbers.

    As for your questions, any changes that may influence how the Physics behaves should ideally be done in FixedUpdate. The terrain changes do occur before the wheel collider resolves its movement. Currently we only have the FixedUpdate message, which is always called right before the PhysX Simulation is done. There has been talk to introduce a LateFixedUpdate message, which would allow one to execute code immediately after the PhysX sim is done.
     
    strich likes this.
  3. strich

    strich

    Joined:
    Aug 14, 2012
    Posts:
    374
    Created a bug report with a small repro project for you (Case 874802).

    I also found an odd thing in the process of this:
    The order of events in the FixedUpdate loop appears to 'resolve' it. This however seems odd. I would like to know why this is, for my own purposes, and we might want to see about resolving why that is too.

    Code (CSharp):
    1. void FixedUpdate()
    2.     {
    3.         // Terrain modification first will cause the wheels to loose grounding:
    4.         if (EatSomeTerrain)
    5.         {
    6.             ModifyTerrainByCode();
    7.             EatSomeTerrain = false;
    8.         }
    9.  
    10.         DoWheelBump();
    11.         TestWheelGrounding();
    12.  
    13.         // Terrain modification last seems to resolve the issue:
    14.         //if (EatSomeTerrain)
    15.         //{
    16.         //    ModifyTerrainByCode();
    17.         //    EatSomeTerrain = false;
    18.         //}
    19.     }