Hey guys, I’m coding a small space themed RTS-type project (which got really complicated, really quickly) and in my Unit script, in the portion of the code that has rotate to face a waypoint when the player selects a waypoint on the grid (always on the XZ plane, y always = 0), and Quaternion.Slerp seems to always face the same direction–or rather, it turns part of the way before coming to a stop and never fully completing the rotation.
Line 107 is where the Slerp is performed. I’m not entirely sure what I’m doing wrong here, and I apologize for the messiness.
using UnityEngine;
using System.Collections;
public enum IFFAlignment {
friendly,
hostile,
pirate
};
public enum Order {
blank, waypoint, attack, defend, fortify, follow, construct
};
public class Unit : MonoBehaviour {
public IFFAlignment alignment = IFFAlignment.friendly;
[HideInInspector]
public bool selected = false;
public AudioClip mouseoverSound;
public AudioClip selectSound;
public AudioClip deselectSound;
public AudioClip giveOrderSound;
public bool useFuel = false;
public int fuelUsage = 2;
public bool isCapitalShip = false;
public bool canConstruct = false;
public bool isImmobile = false;
public int maxMovementDistance = 50;
public float maxVelocity = 5.0f;
private float maxTurnVelocity = 0.5f;
public float accelerationRate = 1.0f;
public string type = "";
public int health = 100;
public int strength = 1;
private Color initialColor;
private Color friendlyColor = Color.green;
private Color unfriendlyColor = Color.red;
private Shader initialShader;
private bool overrideReset = false;
private GameObject CameraController;
private bool doInterpCheck = true;
private HUD hud;
[HideInInspector]
public int fuel = 0;
[HideInInspector]
public Order[] queue = new Order[6];
[HideInInspector]
public int numOrders = 0;
[HideInInspector]
public Transform[] transformQueue;
public GameObject[] gameobjectQueue;
private UnitSelectionMode mode;
private bool allowMovement = true;
private bool successfullyRotated = false;
[HideInInspector]
public float currentVelocity = 0.0f;
// Use this for initialization
void Start () {
initialColor = renderer.material.color;
initialShader = renderer.material.shader;
CameraController = GameObject.Find ("Camera Controller");
hud = Camera.main.GetComponent<HUD>();
for (int i = 0; i < queue.Length; i++) {
queue[i] = Order.blank;
}
transformQueue = new Transform[queue.Length];
gameobjectQueue = new GameObject[queue.Length];
}
// Update is called once per frame
void Update () {
CameraController.GetComponent<CameraMovement>().mode = mode;
string toprint = "";
for (int i = 0; i < transformQueue.Length; i++) {
if (transformQueue[i] != null) {
toprint += transformQueue[i].position.ToString();
toprint += ";";
toprint += transformQueue[i].rotation.ToString();
toprint += "$";
}
}
//print (toprint);
if (queue[0] == Order.waypoint) {
if (successfullyRotated) {
currentVelocity = Mathf.Lerp(currentVelocity, maxVelocity, Time.deltaTime*accelerationRate);
transform.Translate(Vector3.right*Time.deltaTime*currentVelocity);
if (IsApproximately(transform.position.x, transformQueue[0].position.x, 5.0f) IsApproximately(transform.position.z, transformQueue[0].position.z, 5.0f)) {
currentVelocity = 0;
successfullyRotated = false;
transformQueue[0] = null;
deleteFromQueue(0);
}
} else {
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(transformQueue[0].position, Vector3.up), Time.deltaTime*maxTurnVelocity);
print (Quaternion.LookRotation(transformQueue[0].position, Vector3.up));
if (Quaternion.Angle(transform.rotation, Quaternion.LookRotation(transformQueue[0].position)) < 1.0f) {
successfullyRotated = true;
}
}
}
if (mode == UnitSelectionMode.selectGrid selected) {
if (Input.GetKey("space")) {
mode = UnitSelectionMode.normal;
Camera.main.audio.PlayOneShot (deselectSound);
setHUDToDescription();
}
if (Input.GetMouseButton(0) allowMovement) {
Camera.main.audio.PlayOneShot (giveOrderSound);
giveOrder (Order.waypoint, gameObject, CameraController.GetComponent<CameraMovement>().gotoSelector.transform);
mode = UnitSelectionMode.normal;
}
if (Input.GetMouseButtonDown(0) !allowMovement) {
Camera.main.audio.PlayOneShot (deselectSound);
}
if (Vector3.Distance (transform.position, CameraController.GetComponent<CameraMovement>().gotoSelector.transform.position) > maxMovementDistance) {
CameraController.GetComponent<CameraMovement>().gotoSelector.renderer.material.color = Color.red;
allowMovement = false;
hud.SmallText = "Cannot move unit this far";
} else {
CameraController.GetComponent<CameraMovement>().gotoSelector.renderer.material.color = Color.green;
allowMovement = true;
hud.SmallText = "Select where you want to send this ship.\n(Press Spacebar to cancel)";
}
}
// These blocks highlight the ship when it's selected depending on its alignment
if (selected) {
if (mode == UnitSelectionMode.normal) {
setHUDToDescription();
}
if (alignment == IFFAlignment.friendly) {
renderer.material.color = friendlyColor;
} else {
renderer.material.color = unfriendlyColor;
}
renderer.material.shader = Shader.Find ("Self-Illumin/Bumped Specular");
if ((CameraController.transform.position.x >= (transform.position.x-0.2f)) (CameraController.transform.position.x <= (transform.position.x+0.2f))
(CameraController.transform.position.z >= (transform.position.z-0.2f)) (CameraController.transform.position.z <= (transform.position.z+0.2f))
doInterpCheck) {
CameraController.GetComponent<CameraMovement>().currentSelection = null;
doInterpCheck = false;
}
} else {
if (overrideReset) {
renderer.material.color = initialColor;
renderer.material.shader = initialShader;
}
}
}
void OnGUI () {
GUI.depth = 10;
// Show the list of possible orders
GUI.skin.font = Camera.main.GetComponent<HUD>().HUDSmallFont;
if (selected) {
// Show the order list
GUI.Box (new Rect (10,Screen.height-260,100,250), "Order Unit");
if (!isImmobile) {
if (GUI.Button (new Rect (20,Screen.height-220,80,20), "Go To")) {
if (mode != UnitSelectionMode.selectGrid) {
mode = UnitSelectionMode.selectGrid;
Camera.main.audio.PlayOneShot(mouseoverSound);
CameraController.GetComponent<CameraMovement>().currentZoom = CameraController.GetComponent<CameraMovement>().zoomLevels.Length-1;
hud.BigText = "Select Waypoint";
} else {
mode = UnitSelectionMode.normal;
Camera.main.audio.PlayOneShot(deselectSound);
setHUDToDescription();
}
}
} else if (isImmobile canConstruct) {
if (GUI.Button (new Rect (20,Screen.height-220,80,20), "Construct")) {
giveOrder (Order.waypoint, gameObject, transform);
}
}
if (GUI.Button (new Rect (20,Screen.height-190,80,20), "Attack")) {
// do nothing
}
if (!isImmobile !canConstruct) {
if (GUI.Button (new Rect (20,Screen.height-160,80,20), "Defend")) {
// do nothing
}
} else {
if (GUI.Button (new Rect (20,Screen.height-160,80,20), "Construct")) {
// do nothing
}
}
if (GUI.Button (new Rect (20,Screen.height-130,80,20), "Fortify")) {
// do nothing
}
if (GUI.Button (new Rect (20,Screen.height-100,80,20), "Follow")) {
// do nothing
}
if (GUI.Button (new Rect (20,Screen.height-40,80,20), "Cancel All")) {
// do nothing
}
// Show the order queue
GUI.Box (new Rect (120,Screen.height-260,100,250), "Queue");
if (queue[0] != Order.blank) {
if (GUI.Button (new Rect (130,Screen.height-220,80,20), getOrderName(0))) {
currentVelocity = 0;
successfullyRotated = false;
deleteFromQueue(0);
mode = UnitSelectionMode.normal;
}
}
if (queue[1] != Order.blank) {
if (GUI.Button (new Rect (130,Screen.height-190,80,20), getOrderName(1))) {
deleteFromQueue(1);
}
}
if (queue[2] != Order.blank) {
if (GUI.Button (new Rect (130,Screen.height-160,80,20), getOrderName(2))) {
deleteFromQueue(2);
}
}
if (queue[3] != Order.blank) {
if (GUI.Button (new Rect (130,Screen.height-130,80,20), getOrderName(3))) {
deleteFromQueue(3);
}
}
if (queue[4] != Order.blank) {
if (GUI.Button (new Rect (130,Screen.height-100,80,20), getOrderName(4))) {
deleteFromQueue(4);
}
}
if (queue[5] != Order.blank) {
if (GUI.Button (new Rect (130,Screen.height-70,80,20), getOrderName(5))) {
deleteFromQueue(5);
}
}
}
}
void OnMouseDown() {
if (mode == UnitSelectionMode.normal) toggleSelection();
}
void OnMouseEnter() {
overrideReset = false;
renderer.material.shader = Shader.Find ("Self-Illumin/Bumped Specular");
Camera.main.audio.PlayOneShot(mouseoverSound);
if (!selected || mode == UnitSelectionMode.selectUnit) hud.SmallText = "Unit Type: " + type;
}
void OnMouseExit() {
overrideReset = true;
if (!selected) hud.SmallText = "No unit currently selected.";
}
void toggleSelection() {
if (selected) {
selected = false;
CameraController.GetComponent<CameraMovement>().currentSelection = null;
renderer.material.color = initialColor;
doInterpCheck = true;
Camera.main.audio.PlayOneShot(deselectSound);
hud.BigText = "Select a Unit";
hud.SmallText = "No unit currently selected";
} else {
CameraController.GetComponent<CameraMovement>().currentSelection = transform;
selected = true;
Camera.main.audio.PlayOneShot(selectSound);
setHUDToDescription();
}
}
public void deselect() {
selected = false;
CameraController.GetComponent<CameraMovement>().currentSelection = null;
renderer.material.color = initialColor;
doInterpCheck = true;
Camera.main.audio.PlayOneShot(deselectSound);
hud.BigText = "Select a Unit";
hud.SmallText = "No unit currently selected.";
}
private bool deleteFromQueue(int index) {
if (index < 0 || index > queue.Length) {
print ("UNSUCCESSFUL");
return false;
}
if (alignment == IFFAlignment.friendly) Camera.main.audio.PlayOneShot(deselectSound);
print ("deleting:" + index);
queue[index] = Order.blank;
gameobjectQueue[index] = null;
transformQueue[index] = null;
int currentPos = index;
while (currentPos + 1 < queue.Length) {
queue[currentPos] = queue[currentPos+1];
gameobjectQueue[currentPos] = gameobjectQueue[currentPos+1];
transformQueue[currentPos] = transformQueue[currentPos+1];
currentPos++;
}
currentPos = 0;
numOrders--;
print ("SUCCESSFUL");
return true;
}
public bool giveOrder(Order order, GameObject obj, Transform trans) {
if (numOrders+2 > queue.Length) {
print ("not giving order");
return false;
}
if (alignment == IFFAlignment.friendly) Camera.main.audio.PlayOneShot(giveOrderSound);
print ("giving order");
queue[numOrders] = order;
gameobjectQueue[numOrders] = obj;
transformQueue[numOrders] = trans;
numOrders++;
return true;
}
private string getOrderName(int index) {
return queue[index].ToString();
}
private void setHUDToDescription() {
hud.BigText = type;
if (useFuel) {
hud.SmallText = "Hull: " + health + "% - Fuel: " + fuel + "%";
} else {
hud.SmallText = "Hull: " + health + "%";
}
}
private bool IsApproximately(float a, float b, float tolerance) {
return Mathf.Abs(a - b) < tolerance;
}
}
Any help?