- Home /
How can I slow down a camera rotation and then stop the camera rotation when the camera is facing group of objects ?
In this script I have 4 soldiers. They are all facing same direction and they are all moving walking same time and speed forward.
I have a camera that make RotateAround the whole soldiers. This part is working fine. The camera keep rotating around the soldiers while they are moving. Now I want to add that once the camera is facing the soldiers slow down and stop.
In fact I want that the camera will start a bit before facing the soldiers to slow down the rotating around and then stop rotating around when facing the soldiers.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class CameraMove : MonoBehaviour
{
[Header("Spin")]
public bool spin = false;
public Vector3 Direction;
[Range(0, 300)]
public float speed = 10f;
public bool randomSpeed = false;
public bool randomDirection = false;
[Range(0f, 100f)]
public float timeDirChange;
public Vector3 defaultDirection;
[Space(5)]
[Header("Move in circles")]
public bool moveInCircles = true;
public GameObject rotateAroundTarget;
public Vector3 axis;//by which axis it will rotate. x,y or z.
public float rotationSpeed; //or the speed of rotation.
public float upperLimit, lowerLimit, delay;// upperLimit & lowerLimit: heighest & lowest height;
public bool randomHeight = false;
public bool stopRotatingWhenFacing = false;
private float height, prevHeight, time;//height:height it is trying to reach(randomly generated); prevHeight:stores last value of height;delay in radomness;
[Space(5)]
[Header("Follow objects")]
public GameObject[] objectsToFollow;
public bool randomFollow;
private float nextRotationTime = 0f;
private int counter = 0;
private List<GameObject> Soldiers = new List<GameObject>();
// Use this for initialization
void Start()
{
Soldiers.AddRange(GameObject.FindGameObjectsWithTag("Soldier"));
}
private void Update()
{
if (randomSpeed)
{
speed = UnityEngine.Random.Range(0, 300);
}
if (spin)
{
if (randomDirection == false)
{
nextRotationTime = 0;
timeDirChange = 0;
Direction = defaultDirection;
}
else
{
if (Time.time > nextRotationTime)
{
nextRotationTime += timeDirChange;
RandomDirection();
}
}
transform.Rotate(Direction, speed * Time.deltaTime);
}
else
{
timeDirChange = 0;
randomDirection = false;
randomSpeed = false;
}
if (moveInCircles)
{
MoveInCircles();
}
}
private void RandomDirection()
{
Direction = new Vector3(UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1));
while (Direction == new Vector3(0, 0, 0))
{
counter++;
Direction = new Vector3(UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1), UnityEngine.Random.Range(-1, 1));
if (counter == 2)
{
Direction = new Vector3(1, 0, 0);
break;
}
}
counter = 0;
}
private void MoveInCircles()
{
var F = GetAverageDirectionsOfSoliders();
var D = transform.position - GetAverageLocationOfSoliders();
var angle = Vector3.Angle(D, F);
if (angle < 30f && rotationSpeed > 0.1f)
{
rotationSpeed -= 0.01f;
}
if (rotationSpeed > 0.1f && transform.forward != GetAverageLocationOfSoliders())
transform.RotateAround(GetAverageLocationOfSoliders(), axis, rotationSpeed);
//transform.RotateAround(rotateAroundTarget.transform.position, axis, rotationSpeed);
time += Time.deltaTime;
//Sets value of 'height' randomly within 'upperLimit' & 'lowerLimit' after delay
if (time > delay)
{
prevHeight = height;
if (randomHeight)
{
height = UnityEngine.Random.Range(lowerLimit, upperLimit);
}
time = 0;
}
if (randomHeight == false)
{
height = transform.position.y;
}
if (randomHeight)
{
//Mathf.Lerp changes height from 'prevHeight' to 'height' gradually (smooth transition)
transform.position = new Vector3(transform.position.x, Mathf.Lerp(prevHeight, height, time), transform.position.z);
}
else
{
transform.position = new Vector3(transform.position.x, height, transform.position.z);
}
}
private Vector3 GetAverageLocationOfSoliders()
{
var total = new Vector3();
foreach (var soldier in Soldiers)
{
total += soldier.transform.position;
}
return total / Soldiers.Count(); // Assuming Soldiers is List<Soldier>
}
private Vector3 GetAverageDirectionsOfSoliders()
{
var totalf = new Vector3();
foreach (var soldier in Soldiers)
{
totalf += soldier.transform.forward;
}
return totalf / Soldiers.Count();
}
}
In the bottom I have a method name GetAverageDirectionsOfSoliders and then inside MoveInCircles I'm doing this part:
var F = GetAverageDirectionsOfSoliders();
var D = transform.position - GetAverageLocationOfSoliders();
var angle = Vector3.Angle(D, F);
if (angle < 30f && rotationSpeed > 0.1f)
{
rotationSpeed -= 0.01f;
}
if (rotationSpeed > 0.1f && transform.forward != GetAverageLocationOfSoliders())
transform.RotateAround(GetAverageLocationOfSoliders(), axis, rotationSpeed);
The problems so far are that first I'm not sure that in the end when it top the rotatearound if the camera is really facing the soldiers or the solders center point. I'm using the method GetAverageLocationOfSoliders to find the cneter point of the soldiers.
Second problem is the angle. I used break point to find out that the minimum angle is something like 17.5656546 so the threshold I'm using now is 30 but it can be other numbers. Not sure how to find what is the range of angles for example from 17 to 300 or ...not sure. Second what value of the angle I should check against to so it will start slow down just a bit before facing the soldiers ?
Maybe there is some way to use the angle automatic instead setting a value like I did 30 in this example?
Screenshot of the editor:

And this is a screenshot of the soldiers once the camera suppose to be facing them and stopped rotating:

Your answer