- Home /
CustomCameraController: Rotating my camera breaks my out of bounds code
Hey there guys, I've run into an issue that I can't seem to solve. I have a custom camera controller for an RTS like game I'm working on, and recently I tried to add boundaries, so that the camera can't go off the map.
The issue is, that when I move the camera to the edge it works just fine, but as soon as I add a small rotation to it, it breaks my logic. I know why this is happening, but I don't know how to fix it.
Basically, what is happening, is that I am moving the camera relative to the rotation and I am applying the Vector3.forward/Vector3.right for when I translate the camera regardless. Its worked fine until now.
The issue lies with these two:
TranslateCamera(Vector3.forward, Input.GetAxisRaw("Vertical"), movementSpeed);
TranslateCamera(Vector3.right, Input.GetAxisRaw("Horizontal"), movementSpeed);
and this method:
private void TranslateCamera(Vector3 direction, float force, float additionalSpeed)
{
Vector3 translation = direction * force * additionalSpeed * amplify * Time.deltaTime;
if (boundingBoxIsPresent)
{
Vector2 position = new Vector2(rotationPoint.transform.position.x + translation.x, rotationPoint.transform.position.z + translation.y);
if (position.x > maxBounds.x || position.x < minBounds.x || position.y > maxBounds.y || position.y < minBounds.y)
translation = Vector3.zero;
}
rotationPoint.transform.Translate(translation, movementPoint.transform);
}
How would I pass in the direction to make it work? or do you recommend a better way to handle the out of bounds, with out it bouncing back and forth when hits the wall (because as of now, it just hits the boundary and then stops perfectly)
If you feel like you are missing any context, then Here is my CameraController:
/*
* Camera Controller
* -----------------
* #Script uses controls provided by the InputManager
* This scripts adds controls to the camera. These controls include:
* - camera movement using the "Horizontal" and "Vertical" movements as well as "Mouse X" and "Mouse Y" controls.
* - camera rotation around a point*1 using the combination of "Fire3" and "Mouse X" (Required to hold down "Fire3" before using "Mouse X"
* - camera zoom using the "Mouse ScrollWheel"
* - speed up : using a custom Input called "Speed up" on the PC that is Shift and on the controller "ADD CONTROLLER HERE"
*
* *1: This point is to be added as a parent of the camera (the object holding this script)
*
*
*/
using UnityEngine;
public class CameraController : MonoBehaviour {
// Speed properties
public int movementSpeed = 10;
public float speedIncrease = 2;
public int mousePanMovementSpeed = 2;
public int rotationSpeed = 20;
public int scrollSpeed = 10;
public float mousePanSensitivity = 1f;
public GameObject BoundingBox;
private Vector2 minBounds;
private Vector2 maxBounds;
private bool boundingBoxIsPresent = true;
// World point properties
/* This handles the constant movement, since when you rotate the camera the movement stays the same
* (that implies that moving forward makes it look like you're going, for example left).
* This object alters it to always stay constant. */
private GameObject movementPoint;
private Transform rotationPoint;
private float amplify;
void Start()
{
rotationPoint = this.transform.parent;
amplify = 1;
movementPoint = new GameObject("inst_camera_movement");
movementPoint.transform.position = this.transform.position;
if(rotationPoint == null)
Debug.LogError("!No parent was found on the Camera Object (with the CameraController component)! Camera needs a parent to operate! This parent is what controls the rotation (The camera rotates around this object");
if(BoundingBox == null)
{
Debug.LogWarning("!Warning! No bounding box was found; the bounding box allows you to limit the camera movement to a specific distance (so not to go completely out of bound");
boundingBoxIsPresent = false;
}
else
{
Renderer mapBounds = BoundingBox.GetComponent<Renderer>();
if (mapBounds == null)
Debug.LogError("ERROR: " + BoundingBox.name + " does not have a renderer!");
minBounds = new Vector2(BoundingBox.transform.position.x - mapBounds.bounds.size.x / 2, BoundingBox.transform.position.z - mapBounds.bounds.size.z / 2);
maxBounds = new Vector2(BoundingBox.transform.position.x + mapBounds.bounds.size.x / 2, BoundingBox.transform.position.z + mapBounds.bounds.size.z / 2);
Debug.Log("Camera Bounds created!");
}
this.transform.LookAt(rotationPoint.transform); // Makes sure that the camera looks at the point at all time (for rotation purposes)
}
void Update ()
{
movementPoint.transform.position = this.transform.position;
amplify = (Input.GetAxisRaw("Jump") == 1.0f) ? speedIncrease : 1;
// ------- Controls the player movement
TranslateCamera(Vector3.forward, Input.GetAxisRaw("Vertical"), movementSpeed);
TranslateCamera(Vector3.right, Input.GetAxisRaw("Horizontal"), movementSpeed);
// -------- Controls the scrolling mechanic
this.transform.Translate(Vector3.forward * Input.GetAxisRaw("Mouse ScrollWheel") * scrollSpeed * amplify * Time.deltaTime, Space.Self);
// --------- Controls the rotation mechanic
if (Input.GetAxisRaw("Fire3") == 1.0f)
{
this.transform.RotateAround(rotationPoint.transform.position, Vector3.up, Input.GetAxis("Mouse X") * rotationSpeed * amplify * Time.deltaTime); // rotates around the y axis
movementPoint.transform.RotateAround(rotationPoint.transform.position, Vector3.up, Input.GetAxis("Mouse X") * rotationSpeed * amplify * Time.deltaTime);
this.transform.LookAt(rotationPoint.transform); // Makes sure that the camera looks at the point at all time (for rotation purposes)
}
else
{
// --------- Camera movement based on mouse touching the edge
// This is written in this "slavery" fashion because this seems to make it run most smoothly
if(Input.GetAxisRaw("Fire1") != 1f) // So that you can use the drag functionality in the MouseController without moving the camera meanwhile
{
if (Input.mousePosition.x < mousePanSensitivity)
TranslateCamera(Vector3.left, mousePanMovementSpeed, 1);
else if (Input.mousePosition.x >= Screen.width - mousePanSensitivity)
TranslateCamera(Vector3.right, mousePanMovementSpeed, 1);
if (Input.mousePosition.y < mousePanSensitivity)
TranslateCamera(Vector3.back, mousePanMovementSpeed, 1);
else if (Input.mousePosition.y >= Screen.height - mousePanSensitivity)
TranslateCamera(Vector3.forward, mousePanMovementSpeed, 1);
}
}
}
private void TranslateCamera(Vector3 direction, float force, float additionalSpeed)
{
Vector3 translation = direction * force * additionalSpeed * amplify * Time.deltaTime;
if (boundingBoxIsPresent)
{
Vector2 position = new Vector2(rotationPoint.transform.position.x + translation.x, rotationPoint.transform.position.z + translation.y);
if (position.x > maxBounds.x || position.x < minBounds.x || position.y > maxBounds.y || position.y < minBounds.y)
translation = Vector3.zero;
}
rotationPoint.transform.Translate(translation, movementPoint.transform);
}
}
Thank you very much for going through this lengthy post c: May the Unity gods watch over you :p