Search code examples
c#unity-game-engineunity3d-terrain

How can I calculate an average terrain slope based on four points?


I'm programming a simple physics system for vehicles in Unity and I'm trying to figure out how to calculate the average slope based on four points in order to apply the gravitational acceleration. I can get the terrain height at the vehicle wheels positions like this:

Terrain.activeTerrain.SampleHeight(wheel.position);

How can I calculate the average terrain slope based on those four points? I thought about calculating direction vectors between different points, but I'm not sure how to combine them into a single slope vector.


Solution

  • (Assuming that all 4 wheels are always coplanar) I think you could take any 3 wheels, take the height sample

    var wheels = new Vector3[3]{ wheel1.transform.position, wheel2.transform.position, wheel3.transform.position };
    for(var i = 0; i < wheels.Length; i++)
    {
        var w = wheels[i];
        w.y = Terrain.activeTerrain.SampleHeight(w)
        wheels[i]= w;
    }
    

    and from that resulting 3 points generate a plane

    var plane = new Plane(wheels[0], wheels[1], wheels[2]);
    

    Now you can take any of these points and take a vector in straight up direction.

    var upPoint = wheels[0] + Vector3.up;
    

    Then you can map that vector onto the plane using closest point on plane.

    var planePoint = plane.ClosestPointOnPlane(upPoint);
    

    As a last step normalize the vector between that mapped point and your start wheel point and you should have the direction of the slope + the Y component tells you how steep it is

    var planeVector = wheels[0] - planePoint;
    var direction = planeVector.normalized;
    
    Debug.Log($"Slope direction is {direction} with a steepness factor of {direction.y} or also {-planeVector.magnitude}");
    

    where both planeVector.magnitude and direction.y should be moving between 0 (completely horizontal surface) and -1 (completely vertical surface)

    Something like that I guess ^^