- Home /
Orient a vehicle to the ground and in the direction of its travel.
I have some code that's working well for steering my vehicle towards a waypoint. It orients the vehicle in the direction of its travel and all is good except for one problem: Hills.
I need my vehicle to orient itself in the direction of its travel, but also rotated so its down is aligned with the ground.
Here's my code. I'm not at all sure what to put in the raycast to orient myself to the normal without breaking the rotation that points in the direction I'm going:
Vector3 targetVector = predictivePoint - transform.position; targetVector.Normalize(); steerVector = Vector3.Slerp(steerVector, targetVector, turnSpeed);
transform.LookAt(transform.position + steerVector);
transform.Translate(steerVector * speed, Space.World);
if (transform.position.y != ground) {
RaycastHit hit;
Vector3 origin = transform.position;
origin.y += 1;
if (Physics.Raycast(origin, -transform.up, out hit, 5f, groundLayer)) {
origin.y = hit.point.y;
transform.position = origin;
}
}
World of Warcraft uses the "orient to normal" trick for non-bipeds, which gives them that excessively jerky tilt (pets near a wall flip on their sides.) Ins$$anonymous$$d, maybe check the ground near front and back and orient to that slope.
That requires two raycasts firing really often though. Aren't raycasts expensive? As long as I smooth the orientation it shouldn't be jerky.
Raycasts are not that expensive. You can even limit them to be cast only against certain objects or layers to further optimize them.
Answer by StephanK · Apr 02, 2011 at 08:29 AM
Look at the Quaternion.LookRotation method. You can create a rotation that looks along a specific axis (steerVector) and has a specific up-direction (the ground normal).
The ground normal is: TerrainData td = Terrain.activeTerrain.terrainData; Vector3 grndNorm = td.GetInterpolatedNormal(pos.x/td.size.x, pos.z/td.size.z); Can use that as 2nd input to Lookat (will give a small sideways tilt, but not extra pitch.)
$$anonymous$$y terrain is actually just a mesh not a unity Terrain.
Answer by Owen-Reynolds · Apr 03, 2011 at 10:26 PM
This worked to angle something exactly with the ground. Disclaimers: I'm assuming you have some Y-rotation 0-360 variable (called mine facing.) It looks OK if the ground mesh is big compared to the thing being moved -- otherwise it will jerk around on the bumps. It's tested, but may have been copied incorrectly, and I have not tested the hit.normal part. It is in C#:
// after raycast, or however you get normal:
// Compute angle to tilt with ground:
Quaternion grndTilt = Quaternion.FromToRotation(Vector3.up, hit.normal);
// Base angle is straight up, spun only on y:
// "facing" is the script variable used for turning:
transform.rotation = Quaternion.Euler(0,facing,0);
// tilt to align with ground:
transform.rotation = grndTilt*transform.rotation;
If makes kind of a cool snap when you land after a small jump. If you want smooth, replace transform.rotation with Quaternion wantRotation; (and blend with trans.rot however.)
Your answer