How to smoothly move and rotate my object to a target?

The purpose of these four scripts is to:

  1. Populate a list of objects of interest in a room
  2. Pass a random one of those objects of interest to a character
  3. Move and rotate that character to the target object

The script is still unfinished, but the problem I’m running into is that the character is instantly appearing at the target object, instead of smoothly moving to it. The script was behaving correctly when the MoveTo() and RotateTo() functions were inside of Update(). But since moving them out, I’m not getting the smooth transition anymore.

Any advice about this problem or the scripts in general would be greatly appreciated. Thanks in advance for the help!

ObjectOfInterest.cs

using UnityEngine;
using System.Collections.Generic;

public class ObjectOfInterest : MonoBehaviour {
	
	public string objectName;
	private Room roomScript;
	private GameObject roomObject;
	
	// Use this for initialization
	void Start () {
	roomObject = transform.parent.gameObject;
	roomScript = roomObject.GetComponent<Room>();
	// Adds this object to the list of objects in the room
	roomScript.objectsInRoom.Add(gameObject);
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

Room.cs

using UnityEngine;
using System.Collections.Generic;

public class Room : MonoBehaviour {
	
	public List<GameObject> objectsInRoom;
	
	// This happens before Start() is called
	void Awake () {
	// This creates the list that will contain objects in the room
	objectsInRoom = new List<GameObject>();
	}
	
	// Use this for initialization
	void Start () {

	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

Director.cs

using UnityEngine;
using System.Collections;

public class Director : MonoBehaviour {
	
	private Vector3 targetLoc; // This is the position of the object of interest, here for the character to 'look at'
	private Vector3 target; // This is the position of the 'stand here' object in front of the object of interest
	private Controller controller;
	private GameObject roomObject;
	private Room roomScript;
	private int rnd;
	
	
	// Use this for initialization
	void Start () {
	controller = gameObject.GetComponent<Controller>();
	roomObject = GameObject.Find ("GroundRoom");
	roomScript = roomObject.GetComponent<Room>();
	}
	
	// Update is called once per frame
	void Update () {
		if (controller.CurrentState() == Controller.State.idle) {
			MoveToObject();
		}
	}
	
	public Vector3 Target () {
		return target;
	}
	
	public Vector3 TargetLoc () {
		return targetLoc;
	}
	
	void MoveToObject() {
		rnd = Random.Range (0, roomScript.objectsInRoom.Count);
		Debug.Log ("The number was " +rnd +" and the count is " +roomScript.objectsInRoom.Count);
		target = roomScript.objectsInRoom[rnd].transform.position;
		targetLoc = roomScript.objectsInRoom[rnd].transform.Find ("target").transform.position;
		controller.MoveToObject();
	}
}

Controller.cs

using UnityEngine;
using System.Collections;

public class Controller : MonoBehaviour {
	
	private Director director;
	public float speed;
	public float rotationSpeed;
	Vector3 direction = new Vector3();
	Quaternion looking = new Quaternion();
	private Vector3 target;
	private Vector3 targetLoc;
	public enum State {moving, idle};
	public static State myState;
		
	// Use this for initialization
	void Start () {
	director = gameObject.GetComponent<Director>();
	// Sets default speed and rotationSpeed if none are set;
	if (speed == 0) {
		speed = 100;
		}
	if (rotationSpeed == 0) {
		rotationSpeed = 100;
		}
	// Sets initial state to idle (this is required for Director to start doing stuff)
	myState = State.idle;
	}
	
	// Update is called once per frame
	void Update () {
		if (myState == State.moving) {
			Moving ();
		}
	}
	
	public void MoveToObject() {
		myState = State.moving;
		target = director.Target();
		targetLoc = director.TargetLoc();
	}
	
	void Moving() {
		while (transform.position != targetLoc) {
			MoveTo ();
			RotateTo ();
		}
		Debug.Log ("Done moving.");
	}
	
	void MoveTo () {
		targetLoc.y = transform.position.y;
		transform.position = Vector3.MoveTowards(transform.position, targetLoc, Time.deltaTime * speed);
	}
	
	void RotateTo () {
		direction = (target - transform.position).normalized;
		looking = Quaternion.LookRotation(direction);
		looking.x = 0;
		looking.z = 0;
		transform.rotation = Quaternion.Slerp(transform.rotation, looking, Time.deltaTime * rotationSpeed);
	}
	
	public State CurrentState() {
		return myState;
	}
}

Your problem is line 44:

while (transform.position != targetLoc) {

On a single frame, you are repeatedly calling MoveTo() and RotateTo() until they arrive at their destination. If you remove this while loop, then Moveto() should work. You’ll need to add logic so that myState get some value besides State.moving. Currently, once set, it is never reset.

Also lines 59 and 60 are problematic. You don’t want to be assigning individual components of a Quaternion unless you have a strong understanding of the math behind them. I believe you want this object to only rotate around the ‘Y’ axis. The typical way to make this happen is to bring the direction down so that it does not have a ‘Y’ component. So below line 58 you would add:

direction.y = 0;

Then you can remove the lines that directly assign components of the Quaternion.