Calculating the resting position of a rigidbody.
What is the easiest way to calculate the resting transformation of an object with a rigidbody attached to it?
Currently, I have to position the object just over the terrain, then when the scene starts, you see it drop into place.
I'd like to not see it drop when the scene is initialized.
My current idea is to wait for all objects to drop before showing the scene, but I'd prefer something less hacky.
Answer by kidmosey · Dec 07, 2015 at 10:05 AM
Okay, I've found a solution to this from http://answers.unity3d.com/questions/168097/orient-vehicle-to-ground-normal.html
It isn't the most straightforward solution, but I can use it for more than just initialization. Currently, I am using it in my character controller.
I don't actually need the rigidbody with this solution, so I've disabled it for now. Also, this could probably use a few optimizations, but it works for now.
Vector3 GetUpVector()
{
// quad is an invisible rectangle denoting the four corners of the base
MeshCollider collider = quad.GetComponent<MeshCollider>();
// ensure we are above the terrain so the hit tests work
transform.position += Vector3.up * 5;
Vector3 backLeft = quad.transform.TransformPoint(collider.sharedMesh.vertices[3]);
Vector3 backRight = quad.transform.TransformPoint(collider.sharedMesh.vertices[0]);
Vector3 frontLeft = quad.transform.TransformPoint(collider.sharedMesh.vertices[1]);
Vector3 frontRight = quad.transform.TransformPoint(collider.sharedMesh.vertices[2]);
RaycastHit lr, rr, lf, rf;
Vector3 upDir = Vector3.up;
int layerMask = LayerMask.GetMask(new[] { "Terrain" });
bool overTerrain = Physics.Raycast(backLeft + Vector3.up,
Vector3.down, out lr, layerMask)
&& Physics.Raycast(backRight + Vector3.up, Vector3.down, out rr, layerMask)
&& Physics.Raycast(frontLeft + Vector3.up, Vector3.down, out lf, layerMask)
&& Physics.Raycast(frontRight + Vector3.up, Vector3.down, out rf, layerMask);
if (overTerrain)
{
upDir = (Vector3.Cross(rr.point - Vector3.up, lr.point - Vector3.up) +
Vector3.Cross(lr.point - Vector3.up, lf.point - Vector3.up) +
Vector3.Cross(lf.point - Vector3.up, rf.point - Vector3.up) +
Vector3.Cross(rf.point - Vector3.up, rr.point - Vector3.up)
).normalized;
}
// Move back to the starting position
transform.position += Vector3.down * 5;
return upDir;
}
Quaternion GetPredictedForwardQuaternion()
{
// temporarily orient the object and calculate the up vector
Quaternion origRot = transform.rotation;
transform.rotation = Quaternion.LookRotation(camera.forward, Vector3.up);
Vector3 up = GetUpVector();
transform.rotation = origRot;
// get the forward vector and create a new quaternion
Vector3 forward = Vector3.ProjectOnPlane(camera.forward, up).normalized;
return Quaternion.LookRotation(forward, up);
}
void DropToTerrain()
{
MeshCollider collider = quad.GetComponent<MeshCollider>();
// Ensure we are above the terrain.
transform.position += Vector3.up * 5;
Vector3 backLeft = quad.transform.TransformPoint(collider.sharedMesh.vertices[3]);
Vector3 backRight = quad.transform.TransformPoint(collider.sharedMesh.vertices[0]);
int layerMask = LayerMask.GetMask(new[] { "Terrain" });
RaycastHit lr, rr;
// One of these corners will be one of the 3 that are touching the ground
if (Physics.Raycast(backLeft, Vector3.down, out lr, layerMask)
&& Physics.Raycast(backRight, Vector3.down, out rr, layerMask))
{
transform.position += Vector3.down * Mathf.Min(lr.distance, rr.distance);
}
}
Your answer
![](https://koobas.hobune.stream/wayback/20220612051443im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Car made from Different GameObjects and Empty GameObjects breaks on Collision with Terrain. 0 Answers
Rotating around a point using Rigidbody? 0 Answers
Sphere bouncing back on edges of aligned objects 0 Answers
Proper way to set a RigidBody's maximum velocity 1 Answer
AI detect incoming rigid body position placement to catch it 1 Answer