Hello!
I’m doing something relatively simple: rotating a battalion of soldiers towards a point at 90-degree intervals (so everything is perfectly aligned). Basically, the script determines if the point is to the left or right of the battalion of soldiers. Then, it looks what directions the soldiers are facing at the moment. Based on that, it decides how to rotate. However, the method I’m using seems very inefficient. Here’s the script I wrote:
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class BatalionController:MonoBehaviour {
private bool AllowMoveToPoint;
public GameObject Arrows;
public bool IsMovingToPoint;
public bool IsRotating;
public List<Vector3> WaypointList;
public List<GameObject> Soldiers;
[Header("Movement settings")]
public int RotationSpeed;
private bool TargetIsAbove;
private bool TargetIsBelow;
private bool TargetIsLeft;
private bool TargetIsRight;
//facing bools show what direction the soldiers are facing BEFORE starting to rotate
public bool FacingUp;
public bool FacingDown;
public bool FacingLeft;
public bool FacingRight;
public float DegreesTurned;
public float OrigYRotation;
public int TurnAmount;
// Use this for initialization
void Start ()
{
Soldiers = GetComponent<BatalionGenerator>().SpawnedObjects;
}
// Update is called once per frame
void FixedUpdate ()
{
if (IsMovingToPoint == true)
{
//now get direction of movement - up/down/left/right
if (IsRotating)
{
if (TargetIsRight)
{
RotateTargetIsRight();
}
if (TargetIsLeft)
{
RotateTargetIsLeft();
}
if (DegreesTurned >= TurnAmount)
IsRotating = false; Debug.Log("Finished rotating");
Debug.Log("Rotation Y: " + Soldiers.FirstOrDefault().transform.localEulerAngles.y);
}
}
}
void RotateTargetIsRight()
{
if (FacingUp)
{
TurnAmount = 90;
foreach (GameObject soldier in Soldiers)
{
//turn right
soldier.transform.Rotate(Vector3.up * RotationSpeed * Time.deltaTime);
DegreesTurned = soldier.transform.localEulerAngles.y;
}
}
if (FacingDown)
{
TurnAmount = 90;
foreach (GameObject soldier in Soldiers)
{
//turn right
soldier.transform.Rotate(Vector3.up * RotationSpeed * Time.deltaTime);
DegreesTurned = 180 - soldier.transform.localEulerAngles.y;
}
}
if (FacingRight)
{
foreach (GameObject soldier in Soldiers)
{
//already facing needed direction
IsRotating = false;
}
}
if (FacingLeft)
{
TurnAmount = 180;
foreach (GameObject soldier in Soldiers)
{
soldier.transform.Rotate(Vector3.up * -RotationSpeed * Time.deltaTime);
DegreesTurned = 270 - soldier.transform.localEulerAngles.y;
}
}
}
void RotateTargetIsLeft()
{
if (FacingUp)
{
TurnAmount = 90;
foreach (GameObject soldier in Soldiers)
{
//turn left
soldier.transform.Rotate(Vector3.up * -RotationSpeed * Time.deltaTime);
DegreesTurned = 360 - soldier.transform.localEulerAngles.y;
}
}
if (FacingDown)
{
TurnAmount = 90;
foreach (GameObject soldier in Soldiers)
{
//turn right
soldier.transform.Rotate(Vector3.up * RotationSpeed * Time.deltaTime);
DegreesTurned = soldier.transform.localEulerAngles.y - 180;
}
}
if (FacingRight)
{
TurnAmount = 180;
foreach (GameObject soldier in Soldiers)
{
soldier.transform.Rotate(Vector3.up * RotationSpeed * Time.deltaTime);
DegreesTurned = -(90 - soldier.transform.localEulerAngles.y);
}
}
if (FacingLeft)
{
foreach (GameObject soldier in Soldiers)
{
//already facing needed direction
IsRotating = false;
}
}
}
void GetDirection()
{
DegreesTurned = 0;
TargetIsAbove = false;
TargetIsBelow = false;
TargetIsLeft = false;
TargetIsRight = false;
FacingUp = false;
FacingDown = false;
FacingLeft = false;
FacingRight = false;
GameObject OneSoldier = Soldiers.FirstOrDefault();
OrigYRotation = OneSoldier.transform.localEulerAngles.y;
if (OrigYRotation < 1 && OrigYRotation > -1)
{
FacingUp = true;
}
if (OrigYRotation < 271 && OrigYRotation > 269)
{
FacingLeft = true;
}
if (OrigYRotation < 181 && OrigYRotation > 179)
{
FacingDown = true;
}
if (OrigYRotation < 91 && OrigYRotation > 90)
{
FacingRight = true;
}
//SpriteLine.transform.position = SpawnPositions[SpawnPositions.Count - 1];
float DiffX = WaypointList[WaypointList.Count - 1].x - transform.position.x;
//make sure it's positive
if (DiffX < 0)
{
DiffX *= -1;
TargetIsLeft = true;
}
else
{
TargetIsLeft = false;
TargetIsRight = true;
}
float DiffZ = transform.position.z - WaypointList[WaypointList.Count - 1].z;
//make sure it's positive
if (DiffZ < 0)
{
DiffZ *= -1;
TargetIsBelow = true;
}
else
{
TargetIsBelow = false;
TargetIsAbove = true;
}
IsRotating = true;
}
public void StartMoveAlongPoints()
{
Arrows.SetActive(false);
GetDirection();
IsMovingToPoint = true;
Debug.Log("Batalion movement started");
}
}
I have an obscene amount of if statements, and all they do is decide what direction to turn my battalion of soldiers. I’ve only done the script so the soldiers can point towards targets that are to the left or right only as I know I’m wasting my time doing this wrong. I just don’t think having 16 if statements is the proper way to do this (4 target locations (down, up, left, right) * 4 battalion start look rotation states (down, up, left right)). This will end up to about 200 lines of code of nothing but if statements.
The script works perfectly, but is there a way to shorten it? Note that I do NOT want to use Quaternion.Lerp as it has an acceleration/deceleration of rotation speed at the start and end of rotating. I need the soldiers to rotate at a fixed speed.
Thank you for any insight!