HI all,
I’m relatively new to Unity (started in August). I have followed many tutorials and wanted to try something myself. I am trying to do a click to move character in a game.
I created a basic scene with obstacles in Unity and downloaded the SuperCyan Character pack free from the unity store to test my scripting before going heavy on the art. I had some errors and issues but I managed to resolve them, thanks to searching the forums and the manual. The problem I have now that I cant find a solution to is to do with the root motion i believe.
At start my character is in idle, when I click on the NavMesh the character rotates to face the direction but does not move towards it but instead it moves in the z+ direction while walking. It stops at the edge of the NavMesh and will walk on the spot.
No matter where I click the character will rotate but won’t move towards the click on ground. Before adding the root motion script my character would just walk on the spot and rotate to face the direction i clicked.
Root motion script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(Animator))]
public class RootMotion : MonoBehaviour {
private void OnAnimatorMove()
{
Animator animator = GetComponent<Animator>();
if (animator)
{
Vector3 newPosition = transform.position;
newPosition.z += animator.GetFloat("Speed") * Time.deltaTime;
transform.position = newPosition;
}
}
}
Player motion script (Based on the Adventure game tutorial script)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI; //Needs to be added to be used with the events system
using UnityEngine.EventSystems; //Needs to be added when an event system ia required
public class PlayerMovement : MonoBehaviour
{
public Animator animator;
public NavMeshAgent agent;
public float inputHoldDelay = 0.5f;
public float turnSpeedThreashold = 0.5f;
public float speedDampTime = 0.1f;
public float slowingSpeed = 0.175f;
public float turnSmoothing = 15f;
public bool isStopped;
private WaitForSeconds inputHoldWait;
private Vector3 destinationPosition;
//private bool handleInput = true;
private const float stopDistanceProportion = 0.1f;
private const float navMeshSampleDistance = 4f;
private readonly int hashSpeedPara = Animator.StringToHash("Speed");
private readonly int hashLocomotionTag = Animator.StringToHash("Locomotion");
private void Start()
{
agent.updateRotation = false; //Don't update mesh rtoation
inputHoldWait = new WaitForSeconds(inputHoldDelay);
destinationPosition = transform.position;
}
private void OnAnimatorMove()
{
agent.velocity = animator.deltaPosition / Time.deltaTime;
//Vector3 newPosition = transform.position;
//transform.position = newPosition;
}
private void Update()
{
if (agent.pathPending)
{
return;
}
float speed = agent.desiredVelocity.magnitude;
if (agent.remainingDistance <= agent.stoppingDistance * stopDistanceProportion)
{
Stopping(out speed);
}
else if (agent.remainingDistance <= agent.stoppingDistance)
{
Slowing(out speed, agent.remainingDistance);
}
else if (speed > turnSpeedThreashold)
{
Moving();
}
animator.SetFloat(hashSpeedPara, speed, speedDampTime, Time.deltaTime);
}
private void Stopping(out float speed)
{
agent.isStopped = true; // replaces agent.Stop();
transform.position = destinationPosition;
speed = 0f;
}
private void Slowing(out float speed, float distanceToDestination)
{
agent.isStopped = true;
transform.position = Vector3.MoveTowards(transform.position, destinationPosition, slowingSpeed * Time.deltaTime);
float proportionalDistance = 1f - distanceToDestination / agent.stoppingDistance;
speed = Mathf.Lerp(slowingSpeed, 0f, proportionalDistance);
}
private void Moving()
{
Quaternion targetRotation = Quaternion.LookRotation(agent.desiredVelocity);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, turnSmoothing * Time.deltaTime);
}
public void OnGroundClick(BaseEventData data)
{
PointerEventData pData = (PointerEventData) data;
NavMeshHit hit;
if (NavMesh.SamplePosition(pData.pointerCurrentRaycast.worldPosition, out hit, navMeshSampleDistance, NavMesh.AllAreas))
{
destinationPosition = hit.position;
}
else
{
destinationPosition = pData.pointerCurrentRaycast.worldPosition;
}
agent.SetDestination (destinationPosition);
agent.isStopped = false; // replaces agent.Resume();
}
/*private IEnumerator WaitForInteraction ()
{
handleInput = false;
yield return inputHoldWait;
while(animator.GetCurrentAnimatorStateInfo(0).tagHash != hashLocomotionTag)
{
yield return null;
}
handleInput = true;
}*/
}
I read somewhere that the rigidbody could conflict with the root motion script but I don’t have a rigidbody on the character. I also followed the instructions for root motion in the unity manual. I think it is something to do with newPosition.z but I am not sure what to write in the script to fix it.
Any advice would be great. Thanks in advance ![]()