- Home /
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;
}
}
}
}
So when the player rotates, should the camera rotate as well, or remain where it was?
Answer by YourGamesBeOver · Mar 05, 2014 at 10:45 PM
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.
Answer by wibble82 · Mar 05, 2014 at 10:06 PM
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'.
$$anonymous$$eeping the "required_distance_from_player" as a variable and using it in the code like you wrote does make the camera follow the player, but it introduces a new problem: The camera no longer keeps its 45-degree angle. When the player moves forward, the camera stays required_distance_from_player units away, but it lowers toward y = 0. I'm playing around with it now, seeing if I can fix it.
That makes sense. The player moves, so their angle to the camera is changing. If you want to fix that, the simplest (albeit slightly ugly) approach would be to put my position correction code both before AND after your calculations.
There's lots of different ways of doing it depending on your scenario - if it were me I'd be storing my desired position relative to the player as 2 angles and a distance, then recalculating the camera position every frame.
I like that, though it will take some serious reworking. I'm guessing one of the two angles you mention would be locked at 45 degrees and the other would be the rotation around the player. Is that right? I'll start looking into reworking it.
This is how I would do it:
var target : Transform;
var verticalDiff : float;
var elevationAngle : float;
var angle : float = 0;
private var horizontalDiff : float;
private var s : float;
private var c : float;
private var lengthRatios : float;
private var dir : Vector2;
function Start(){
HorizontalCalc();
}
function Update () {
HorizontalCalc();
s = $$anonymous$$athf.Sin(angle*$$anonymous$$athf.Deg2Rad);
c = $$anonymous$$athf.Cos(angle*$$anonymous$$athf.Deg2Rad);
dir = Vector2(s, c).normalized*horizontalDiff;
transform.position.x = target.position.x - dir.x;
transform.position.z = target.position.z - dir.y;
transform.position.y = target.position.y + verticalDiff;
transform.LookAt(target);
}
function HorizontalCalc(){
horizontalDiff = verticalDiff/$$anonymous$$athf.Tan(elevationAngle*$$anonymous$$athf.Deg2Rad);
}
you can remove the call to HorizontalCalc() in the Update function if you don't plan to change the height or angle of elevation during runtime. You can then set 'elevationAngle' to 45 and 'verticalDiff' to your desired height above the object.
Then you can rotate around the target by increasing or decreasing 'angle' (it will take values larger than 360 and smaller than 0 without complaints).
Scribe
That's one way of doing it, although it applies a slightly different set of constraints to the ones you describe.
As shown, you basically want an angle around the player (which will range through the full 360 degrees, or 2*PI in radians), and an angle of elevation (0 to 90 degrees , or 0.5*PI in radians). Once you add a 'distance' into the mix you have the exact constraint I think you're trying to acheive.
If you need a hand with the code, shout, but you can probably give it a go yourself first. It be something along the lines of:
start with camera at zero rotation, sat at the world origin
rotate about world x axis by your elevation (use the axis angle rotation supplied in the quaternion class)
rotate about world y axis by your angle around player
translate out by the camera's forward axis times the distance
add on the player's position
-Chris
Your answer
Follow this Question
Related Questions
RTS Camera Zoom w/ Rotation 0 Answers
How to make it so that you can orbit the mouse on mouse down? 1 Answer
Limiting Camera Movement 1 Answer
Camera scripting references 0 Answers