How do I make my isometic-view camera follow my player (without being its child)?

I’m making a game where the player can travel along the x/z plane only. I have a camera above the player that looks down at the player at a 45-degree angle. The camera needs to follow the player and always point at the player, and it can rotate around the player and zoom in and out. When I began the project, I had the player parenting the camera, but now I want their rotations to be independent. The question is how do I make the camera follow the player without making the player the parent of the camera, while maintaining my tricky rotation code? (Or how can I keep the parent-child relationship and keep independent rotation?) Everything I’ve found online points to just setting the camera position equal to the player position, minus a z value. I’m not sure how that would work with my isometric view, and letting the camera rotate and zoom.

Here is my current code for the camera. When the player is the parent, the camera rotates whenever the player does. The the player is NOT the parent, it does not follow the player.

using UnityEngine;
using System.Collections;

public class CameraScript : MonoBehaviour
{
	public const int MIN_ZOOM_DISTANCE = 80;
	public const int MAX_ZOOM_DISTANCE = 200;

	Transform target;

	void Start()
	{
		target = GameObject.FindGameObjectWithTag("Player").transform;
	}

	void Update()
	{
		transform.LookAt(target);

		if(Input.GetKey(KeyCode.Q) || Input.GetAxis("RightStick Horizontal") > 0)
		{
			transform.RotateAround(target.position, Vector3.up, 40 * Time.deltaTime);
		}
		else if(Input.GetKey(KeyCode.E) || Input.GetAxis("RightStick Horizontal") < 0)
		{
			transform.RotateAround(target.position, -Vector3.up, 40 * Time.deltaTime);
		}

		if(Input.GetKey(KeyCode.Alpha9) || Input.GetAxis("RightStick Vertical") > 0)
		{
			if(Vector3.Distance(transform.position, target.position) <= MAX_ZOOM_DISTANCE)
			{
				transform.position += transform.forward * -1;
			}
		}
		else if(Input.GetKey(KeyCode.Alpha0) || Input.GetAxis("RightStick Vertical") < 0)
		{
			if(Vector3.Distance(transform.position, target.position) >= MIN_ZOOM_DISTANCE)
			{
				transform.position += transform.forward;
			}
		}
	}
}

You could try using vector math/trig to force the camera’s position to be on a ring above the player. In your script set the camera’s y coordinate to some offset above the player, then for its x/z, use some trig to place it on the ring. Just a thought. It’s hard to give more exact suggestions without seeing your game.

Hi there

Without knowing the exact effect desired I couldn’t write you code, but I think you’re on the right lines. As I understand it:

  • you have a camera that can rotate in all kinds of fun ways
  • you want it to always look at the player
  • you want it to stay a fixed distance from the player (your ‘zoom’ value)

So basically, the key is that zoom (or better named ‘required_distance_from_player’). All you need to do is each frame, once the camera has done all its rotatey stuff say:

transform.position = target.position - transform.forwards * required_distance_from_player;

Or in english “put my camera exactly at the player, then move it backwards by my zoom value”

I think perhaps the issue in your script is that you aren’t actually storing a desired distance from player anywhere. Try just storing that as a member variable in your script and tweak it due to player input. Then each frame do as I said above and job done!

side note: The reason you’ve heard a lot about moving by z, is that the calculation above is moving backwards by the camera’s LOCAL z axis, otherwise known as ‘forwards’.