- Home /
Make GameObject always vertical to Terrain
So I am working on my Animal AI and its working everything fine exept the fact that if the ground is not flat it breakes itself so is there a way to make the gameobject(animal) always vertical to the ground?
here my drawing
I am thinking about a solution for so long but i cant figure out how i should do this! thanks!
Answer by Mikyjax · Jan 05, 2015 at 10:15 AM
Hi, did you try try to send a ray and align the rotation of your object to the "normal" of your terrain under you raycast? Try to put your animal inside an empty game object and apply the rotation on your empty game object.
Hope this help! Mike
The Problem is the Rotation dont got an Rotation if i am right cause its one gameobject
'It's not working' is far to generic to give you help the steps required should be very straight forward, at the point you are instantiating or placing your animal, do a raycast straight down that should get the hit information from the ray cast and then, then assign the rotation of the raycasthit normal to the gameobject
Answer by Rainbirth · Jan 06, 2015 at 03:41 AM
as said by mikyjax, you need to raycast the terrain and get the normal. Then using your object rotate to that normal.
you have sample code in this forum post. http://forum.unity3d.com/threads/aligning-object-to-surface-normal-with-quaternion-lookrotation.63619/
Hope it helps!
Answer by Weblyan · Jan 08, 2017 at 09:33 AM
You don't need to raycast the terrain. You can get the normal from the terrain data.
public static void AlignTransform(Transform transform)
{
Vector3 sample = SampleNormal(transform.position);
Vector3 proj = transform.forward - (Vector3.Dot(transform.forward, sample)) * sample;
transform.rotation = Quaternion.LookRotation(proj, sample);
}
public static Vector3 SampleNormal(Vector3 position)
{
Terrain terrain = Terrain.activeTerrain;
var terrainLocalPos = position - terrain.transform.position;
var normalizedPos = new Vector2(
Mathf.InverseLerp(0f, terrain.terrainData.size.x, terrainLocalPos.x),
Mathf.InverseLerp(0f, terrain.terrainData.size.z, terrainLocalPos.z)
);
var terrainNormal = terrain.terrainData.GetInterpolatedNormal(normalizedPos.x, normalizedPos.y);
return terrainNormal;
}
Answer by aakwewaanaqa · Jan 24, 2017 at 07:51 AM
private GameObject root;
void Start ()
{
root = transform.root.gameObject;
}
private void OnTriggerStay(Collider other)
{
if (other.tag == "Planet")
{
RaycastHit hit;
if (Physics.Raycast(transform.position, -transform.up, out hit))
{
}
//Makes the character to stand vertically to the ground
float angle = Vector3.Angle(root.GetComponent<Transform>().up, hit.normal);
Vector3 look = Vector3.Cross(root.GetComponent<Transform>().up, hit.normal);
if (angle < 3 && angle > -3) { angle = 0; }
root.GetComponent<Transform>().RotateAround(root.GetComponent<Transform>().position, look, angle * Time.deltaTime);
Debug.Log(angle);
}
}
I discovered using the Object.GetComponent().RotateAround still can solve this problem. Just only have to find out the rotate axis and the angle. By using Vector3.Angle() and Vector3.Cross(), easily find out where to rotate. Also the cross production determines it is angle or -angle automatically.
Your answer
Follow this Question
Related Questions
How to get a object to stick another object? 1 Answer
Ground continuing down when ball collide with ground. Help? 1 Answer
Gameobject placing halfway through ground? 1 Answer
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers
How attach one sphere to another sphere on draging of sphere 1 Answer