- Home /
Rotate gameobject accroding to ground slope ?!
i have a horse animal that is controllable. i want to set animal rotation with ground slope. i've use some codes but doesn't work. so please help me to fix this.
i've used this code :
RaycastHit hit;
if (Physics.SphereCast(transform.position,0.5f, -(transform.up), out hit, 1))
{
transform.rotation = Quaternion.LookRotation(Vector3.Cross(transform.right, hit.normal));
}
Answer by Pangamini · Oct 25, 2021 at 07:26 PM
Try
transform.rotation = Quaternion.LookRotation(transform.right, hit.normal);
Good general direction, but that transform.right
turns a humble horse into an Apache attack helicopter :D
I got that from your code. It would make more sense to me to use transform.forward, or better, some stable solution that doesn't use transform to change itself
Answer by andrew-lukasik · Oct 25, 2021 at 11:08 PM
RotateGameObjectAccordingToGroundSlope.cs
using UnityEngine;
public class RotateGameObjectAccordingToGroundSlope : MonoBehaviour
{
Vector3 _dir = Vector3.forward;
Camera _camera = null;
void Start ()
{
_dir = transform.forward;
_camera = Camera.main;
}
void Update ()
{
Vector3 inputXZ = _camera.transform.right*Input.GetAxis("Horizontal") + _camera.transform.forward*Input.GetAxis("Vertical");
inputXZ.y = 0;
if( inputXZ.sqrMagnitude>0 ) _dir = inputXZ.normalized;
var ray = _camera.ScreenPointToRay( Input.mousePosition );
if( Physics.Raycast( ray , out var hit ) )
{
Vector3 tangent = Vector3.ProjectOnPlane( _dir , hit.normal );
transform.rotation = Quaternion.LookRotation( tangent , hit.normal );
transform.position = hit.point;
Debug.DrawRay( hit.point , hit.normal , Color.yellow );
Debug.DrawRay( hit.point , tangent , Color.cyan );
Debug.DrawRay( hit.point , inputXZ , Color.magenta );
}
// var ray = new Ray( transform.position , Vector3.down );
// if( Physics.Raycast( ray , out var hit , 1 ) )
// {
// Vector3 tangent = Vector3.ProjectOnPlane( _dir , hit.normal );
// transform.rotation = Quaternion.LookRotation( tangent , hit.normal );
// }
}
}
Here is a script that allows you to control this "horse" with a keyboard input. It requires NavMeshAgent
component and a valid nav mesh.
tip: lower the Angular Speed
on that NavMeshAgent
component to something around 3.0
. Default 120
is too much here.
> NavMeshAgentHorseController.cs
using UnityEngine;
using UnityEngine.AI;
public class NavMeshAgentHorseController : MonoBehaviour
{
[SerializeField] NavMeshAgent _navComponent = null;
Vector3 _moveDirXZ, _moveNormal, _moveTangent;
void Start ()
{
_moveDirXZ = transform.forward;
_moveNormal = Vector3.up;
}
void Update ()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
_moveDirXZ = Quaternion.Euler( 0 , h * _navComponent.angularSpeed , 0 ) * _moveDirXZ;
_navComponent.velocity = Vector3.MoveTowards(
_navComponent.velocity ,
_moveDirXZ * v * _navComponent.speed ,
_navComponent.acceleration * Time.deltaTime
);
}
void LateUpdate ()
{
if( Physics.Raycast( transform.position , Vector3.down , out var hit , 1f , _navComponent.areaMask ) )
{
Vector3 tangent = Vector3.ProjectOnPlane( _moveDirXZ , hit.normal ).normalized;
_moveTangent = Vector3.Lerp( _moveTangent , tangent , Time.deltaTime*5f );
_moveNormal = Vector3.Lerp( _moveNormal , hit.normal , Time.deltaTime*5f );
transform.rotation = Quaternion.LookRotation( _moveTangent , _moveNormal );
Debug.DrawRay( hit.point , hit.normal , Color.yellow );
Debug.DrawRay( hit.point , _moveDirXZ , Color.red );
}
}
}
Thanks for your code. I think that it's a proper code but I have separated MainCamera and the Horse is controlled by the keyboard. so mouse inputs and camera transform and input.getAxis is caused that it doesn't work properly. could you please write a code that is suitable for my game ?
I added additional script in my answer, NavMeshAgentHorseController.cs
.