How To Rotate A Camera Around Object In Vuforia
[Tutorial] How to rotate the camera around an object in Unity3D
In this Unity3D tutorial you lot volition larn a simple mode to move the photographic camera around an object in the scene while always looking at it. I shared all of the code, and I added a link to where you can download the total Unity project likewise.
If y'all have tried RotateAround()
and it's not working for you, you have come to the right place.
You lot can jump to the solution at the end of the post, download the total projection, or follow the tutorial in video format.
Table of contents
- Detecting the drag
- Computing the rotation
- Moving the camera
- The solution
- Extra credit: Alter the rotation speed
We want to program the camera so that information technology rotates around an object in the scene, while looking at information technology, responding to player input.
As you can see, the photographic camera is doing the yaw and pitch rotations.
(Annotation: The method explained in this post can be applied to movement caused by any script too, it's not restricted to user input.)
Nosotros desire that a drag from one side of the screen to the other rotates u.s. 180º around the object. How practice we do that?
The screen (the viewport rather) has a size of 1x1 in viewport coordinates.
Since a drag from left to right of the screen will have a distance of one, we take simply defined our relation:
1 unit in viewport coordinates < == > 180 degrees of camera rotation
Step 1: Discover the elevate (= user input)
For this, I created an empty GameObject
in the scene (I named it "InputController"), and added a script to information technology (that I created, and named "CameraMovement"). These are the steps:
- Get to the Unity Editor.
- In the Scene hierarcy, right click.
- Create > Game Object > Emtpy. I named it "InputController".
- In the InputController's Inspector, click "Add Script".
- Type "CameraMovement", hit enter. This created a "CameraMovement.cs" file in your Assets folder, which contains an empty CameraMovement class that extends MonoBehaviour.
(This is the about basic setup working with an empty project. Of class you can adapt your files and classes yet you prefer.)
Open CameraMovement.cs with your editor, time to code!
public class CameraMovement : MonoBehaviour { void Update() { if (Input.GetMouseButtonDown(0)) { // Volition exist true only in the 1st frame in which information technology detects the mouse is down (or a tap is happening) } else if (Input.GetMouseButton(0)) { // Will be true equally long as the mouse is downward or a touch is happening. } } }
In Unity games, information technology is mutual practice to employ the Update
part to detect role player input. (Information technology is too skillful do not to handle it in the Update
office directly, but this is the smallest of projects and we're not going to over-engineer it.)
We are using the functions Input.GetMouseButtonDown(0)
and Input.GetMouseButton(0)
to discover whether the user clicked/tapped or dragged the pointer over the screen.
The Input
class also has a convenient mousePosition
field which gives us the position of the pointer (mouse or finger) in screen coordinates. We'll apply it in the next step.
Now that we take the problem defined and the drag detected, nosotros can move the photographic camera.
Pace two: Calculate the rotation
Every frame we volition summate how much the cursor/finger moved since last frame, and translate it into how many degrees the camera should rotate according to our previously defined relation:
1 unit in viewport coordinates < == > 180 degrees of camera rotation
In guild to do that, we need to store the previous position in a individual field (previousPosition
).
This is how the code looks:
public form CameraMovement : MonoBehaviour { private Vector3 previousPosition void Update() { if (Input.GetMouseButtonDown(0)) { previousPosition = cam.ScreenToViewportPoint(Input.mousePosition); } else if (Input.GetMouseButton(0)) { Vector3 currentPosition = cam.ScreenToViewportPoint(Input.mousePosition); Vector3 management = previousPosition - currentPosition; float rotationAroundYAxis = -direction.x * 180; // camera moves horizontally bladder rotationAroundXAxis = direction.y * 180; // camera moves vertically previousPosition = currentPosition; } } }
On the first frame in which the mouse is downward (or the finger touches the screen), nosotros store that position equally our previousPosition
.
In each subsequent frames, we calculate management
, which is the difference between the current mousePosition
and previousPosition
.
rotationAroundYAxis
and rotationAroundXAxis
are the rotations nosotros must add together to the current rotation each frame. They are calculated using this very advanced mathematical formula:
(i / 180º) = (direction / rotationAroundAxis)
In UnityEngine, the forward
vector is by convention (0, 0, 1). This is why we are working with the assumption that the camera starts looking "forward", and will rotate around the X and Y axes.
At the cease of the part, don't forget to store our currentPosition
as our previousPosition
!
Okay, but how practise we ACTUALLY Motility THE Photographic camera?
Pace iii: Move the camera
UnityEngine's transform
class has a convenient function RotateAround(Vector3 point, Vector3 centrality, float angleInDegrees)
. Here you would use it like this:
cam.transform.RotateAround(target.transform.position, new Vector3(ane, 0, 0), rotationAroundXAxis); cam.transform.RotateAround(target.transform.position, new Vector3(0, one, 0), rotationAroundYAxis);
Equally you can see, information technology works, but information technology probably doesn't yield the issue y'all want:
RotateAround()
produces a weird motion that we can't control, awful UX, 0 stars, thumbs down. (This is due to the fact that when we rotate around 1 axis we are moving the other, and viceversa. RotateAround()
works well when you only allow rotation around 1 axis.)
But don't worry! At that place's a way!
Nosotros will apply Rotate(Vector3 centrality, float angleInDegrees, Infinite relativeTo)
instead.
Solution
public class CameraMovement : MonoBehaviour { [SerializeField] private Camera cam; [SerializeField] private Transform target; [SerializeField] private float distanceToTarget = x; private Vector3 previousPosition; void Update() { if (Input.GetMouseButtonDown(0)) { previousPosition = cam.ScreenToViewportPoint(Input.mousePosition); } else if (Input.GetMouseButton(0)) { Vector3 newPosition = cam.ScreenToViewportPoint(Input.mousePosition); Vector3 direction = previousPosition - newPosition; float rotationAroundYAxis = -management.x * 180; // camera moves horizontally float rotationAroundXAxis = management.y * 180; // photographic camera moves vertically cam.transform.position = target.position; cam.transform.Rotate(new Vector3(i, 0, 0), rotationAroundXAxis); cam.transform.Rotate(new Vector3(0, 1, 0), rotationAroundYAxis, Space.Earth); // <— This is what makes it work! cam.transform.Translate(new Vector3(0, 0, -distanceToTarget)); previousPosition = newPosition; } } }
Caption
We created the following private serialized fields, that you must assign in the Unity Editor (only elevate the objects into their corresponding box):
-
cam
references the camera that you want to motion. -
target
is thetransform
component of thegameObject
around which we want to rotate. -
distanceToTarget
is the altitude from the target that nosotros want the photographic camera to exist.
What makes this method work is the fact that we are rotating around the world'south Y axis.
By default, Rotate()
and RotateAround()
employ the GameObject
's local axes (in our case, the camera's). Since rotating around one axis messes up the other, we need to rotate around the world's centrality instead of ours.
Rotate()
but rotates the object in its place. When you rotate around something, you are also translating. That's why we must call cam.transform.Interpret()
. The society in which you practice information technology matters:
- If you
Rotate()
first andTranslate()
second, you are rotating your axes, and so moving "co-ordinate" to them. - If you
Translate()
first andRotate()
second, yous are moving "according" to the world's axes, and then rotating effectually yourself in your new position.
So what we demand to do for this application is:
Each frame, we set the camera'due south position equally the target's position. So we apply the rotations. Finally, we translate the camera back distanceToTarget
units in -Z.
Nosotros divers the rotation speed by the relation:
1 unit of measurement in viewport coordinates < == > 180 degrees of photographic camera rotation
While it is one that works very well, and is very intuitive from a UX perspective, yous could make the argument that 180 is a hadcoded arbitrary number.
Therefore, we tin turn the relationship into a private serialized field, so nosotros tin can edit it in the inspector:
[SerializeField] [Range(0, 360)] individual int maxRotationInOneSwipe = 180;
And the code for calculating the photographic camera rotation will look like this:
bladder rotationAroundYAxis = -direction.x * maxRotationInOneSwipe; // camera moves horizontally bladder rotationAroundXAxis = direction.y * maxRotationInOneSwipe; // camera moves vertically
Source: https://emmaprats.com/p/how-to-rotate-the-camera-around-an-object-in-unity3d/
Posted by: freyfacharnmethe.blogspot.com
0 Response to "How To Rotate A Camera Around Object In Vuforia"
Post a Comment