- Home /
How can I do this kind of 3D camera movement explained below?
This is a school project. I have a big cube which is like a planet. I have a small cube that can move on every side of the cube planet. The player moves forward automatically on its local z axis and I rotate it by 90 or -90 degrees to move left or right- but the player can control it like it's an up-down-left-right movement (made a script so they don't have to rotate the cube with 2 keys). It's like a Tron game so if I press the up key, I can't press down immediately because I leave a trail so I have to press the left or right keys. I have a problem with my camera movement. The camera follows the little cube from above, but I want it to lean a little when the little cube player gets close to the edge of a side so it lets me see the other side - where I'm planning to go.
I have a script where I use the center of the cube planet and the player's center as the direction vector and multiply it with the camera-player distance.
Vector3 direction = (target.position - center.position).normalized;
transform.position = target.position + direction * distance;
Then I point my camera's forward vector to the player cube's direction. I tried two codes but none of them worked perfectly. First I tried to rotate the camera with:
transform.rotation = Quaternion.LookRotation(-direction);
Shown in video. The problem with this is that since I don't tell the program the Up and Right vectors (I think), it sets them for itself to some random numbers so the camera sometimes do its own thing like it does a pirouette.
Next I tried this:
Quaternion rot = Quaternion.FromToRotation(transform.forward, -direction);
transform.Rotate(rot.eulerAngles, Space.World);
Shown in video. It's almost good but as the little cube moves, the camera starts steering slightly in the beginning and it gets worse and worse.
Do you have any ideas how can I make it work? I hope you understand what I would like to achieve. I'm trying to set the camera as to always show that when I press Up, my cube moves upward, when I press Right my cube always goes right etc. and when I reach the edge of my side the camera leans a bit towards the side I'm moving to.
I agree it does seem like you need to specify your up direction in the Quaternion.LookRotation call (I wouldn't personally use the second method it kind of complicates things). Have you tried giving it the desired up direction?
I've just tried
transform.rotation = Quaternion.LookRotation(-direction, transform.up);
It's maybe a bit better but it still kind of does the same thing. Do you have any idea why is it happening or how can I solve it?
So you have your camera basically moving on the surface of a sphere which encloses the large cube, and you are trying to tell it which way to rotate. You give it the forward vector that you want, but don't tell it how much to tilt. If you don't give it an up direction, Unity assumes that you want Vector3.up, or at least the closest thing to it. Ideally when you call LookRotation you give it two orthogonal vectors as the forward and up directions of the final rotation will be orthogonal. But really you can give it any two vectors, and Unity will set the forward vector then get as close as it can with the up vector.
So this is the reason you see the spin when the player reaches the bottom side of the cube, the new closest up vector to global up flips 180 degrees as you pass under the bottom pole of the cube. Giving it a suggested up vector should fix this, but then the question is what vector exactly should you be giving it? Giving it transform.up may make it a little better, but since the rotation is going to change transform.up anyway then this is not really a consistent way to do it. You need to know the desired up vector of the camera regardless of its current rotation.
This is were it gets a little tricky, and since I don't quite understand exactly how you want your camera to work I'll need some feedback from you to help, but here is my guess. Imagine you start off with your player on the bottom of the cube. Which way should the camera up be? Well this isn't enough information. It depends on the direction the player is traveling, because we need to know what forward, left, right, down is for the player. So you need to keep track of what forward means for the cube (and I don't mean transform.forward, i mean the direction it will travel if you hit the Up key). Then you can use this as the up vector for your rotation. I just don't know how your movement is really implemented so I can't give you much more advice than that. If this forward direction for the player changes rapidly, it is probably then also worth putting in some rotational smoothing for the camera rotation.
Answer by mezeyroxana · Feb 24, 2020 at 10:12 PM
Thank you for your help. The problem's already been solved with this code.
Vector3 closestToUp = target.forward;
float greatestDot = 0f;
foreach (Vector3 dir in new Vector3[]{
target.forward, target.right, -target.forward, -target.right})
{
float curDot = Vector3.Dot(dir, transform.up);
if (curDot > greatestDot)
{
greatestDot = curDot;
closestToUp = dir;
}
}
transform.rotation = Quaternion.LookRotation(-direction, closestToUp);
Your answer