Click to Move spinning character bug

Hey people,

Hope someone out there can help me with a bug in Unity, I’m trying to develop a click to move character movement system.

For the most, it is working correctly. However I have encountered a bug where the player character will spin around the point it has been asked to move to. I believe this error is caused by elevation changes in the terrain height. I am currently using a RayCast to get the position and move the character. I am wondering if it is possible to have a ‘stop’ command when the player character reaches just before the “clicked” point on the terrain; thus hopefully fixing this spinning bug. I’ll post my script below. (note that it appears to work on level flat terrain)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ClickToMove : MonoBehaviour {
	public float speed;
	public CharacterController controller;
	private Vector3 position;

	// Use this for initialization
	void Start () {
		position = transform.position;
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetMouseButton(0)) {
			locatePosition ();
		}

		moveToPosition ();

	}

	void locatePosition() {
		RaycastHit hit;
		Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);

		if(Physics.Raycast(ray, out hit, 1000)) {
			position = new Vector3 (hit.point.x, hit.point.y, hit.point.z);
		}
	}

	void moveToPosition() {

		if (Vector3.Distance (transform.position, position) > 1) {
			Quaternion newRotation = Quaternion.LookRotation (position - transform.position);

			newRotation.x = 0f;
			newRotation.z = 0f;

			transform.rotation = Quaternion.Slerp (transform.rotation, newRotation, Time.deltaTime * 10);
			controller.SimpleMove (transform.forward * speed);
		}
	}
}

If you are certain the Y axis is the problem, you could create a new Vector3 which matches the transform.position.y of the character to that of the target position, then use that in the Vector3.Distance() check.

Example:

Vector3 vectorForComparison = new Vector3(position.x, transform.position.y, position.z);

         if (Vector3.Distance (transform.position, vectorForComparison ) > 1) {
             Quaternion newRotation = Quaternion.LookRotation (position - transform.position);
 
             newRotation.x = 0f;
             newRotation.z = 0f;
 
             transform.rotation = Quaternion.Slerp (transform.rotation, newRotation, Time.deltaTime * 10);
             controller.SimpleMove (transform.forward * speed);

This preserves the old Y axis value if you need it for some reason while bypassing the problem of the Y axis causing your character to “spin”.

Hope this helps.