[unity] Detailed explanation of several ways to move the perspective of the unity3D camera

Table of contents

I. Introduction

2. Transform basics

1. Several coordinate systems

2. position and localPosition attributes

3. rotation attribute

3. Camera panning

1. Keyboard control panning

2. Mouse control panning

3. Integration 

4. Camera rotation

1. Rotate around itself

2. Rotate around the target object

3. Integration 

5. Optimization function

1. Adjust the speed

2. Switch target objects

3. Set common camera observation points


I. Introduction

        In projects such as virtual simulation or digital twins, we often encounter scenes that require free movement of the perspective. I recently encountered this situation when using Unity to create a digital twin project for a 3D printer. This article will combine the perspective movement functions of Unity and Blender to introduce a perspective movement method similar to that of these two softwares.

2. Transform basics

        The Transform component in Unity3D is a component that every GameObject object has. It controls the position, rotation and scaling of the object. Before introducing the perspective movement, this article will first introduce the position and rotation attributes of transform and the coordinate system in unity.

1. Several coordinate systems

        There are two common coordinate systems in unity, namely global coordinates (World Space) and local coordinates (Local Space). These two coordinate systems can be switched in the unity scene window (Scene), as shown in the figure:

        Global coordinates: also called world coordinates, represent the absolute position and direction of an object in the scene. Global coordinates are relative to the scene's origin (0,0,0).

        Local coordinates: also called relative coordinates, represent the position and direction of an object relative to its parent object. Local coordinates are relative to the parent object's origin (0,0,0).

2. position and localPosition attributes

        Position and localPosition are both three-dimensional vectors (Vector3). The former is used to describe the absolute position of the object in the scene, that is, the position relative to the origin of the world; the latter describes the position of the object relative to its parent object, with the parent object as the origin.

        When the parent object is not set, the values ​​of Transform.position and Transform.localPosition are the same, which are equal to the global coordinates of the object.

        When object P is set as a child object of object Q, the Transform.localPosition of object P represents the relative position to the parent object Q. When only the Transform.position of the parent object Q is changed, the child object P will move with the parent object Q. Therefore, the Transform.position of the child object P changes with the object Q, but the relative position of the child object P relative to the parent object Q remains unchanged, so the Transform.localPosition of the child object P remains unchanged.

        It is worth mentioning that, in the Transform component of the Unity Inspector panel, the displayed position is localPosition. For objects without a parent object, It represents the global (world) coordinates, and for an object with a parent object, it represents the relative position of the two.

3. rotation attribute

        Like the attributes describing position, the attributes describing rotation are also divided into rotation and localRotation. It is a quaternion. The relationship between rotation and localRotation is the same as that between position and localPosition, so I won’t go into details here. However, it is worth noting that it is mentioned in the unity Chinese documentation:

        "Do not attempt to edit/modify rotation."

        "To rotate a Transform, use Transform.Rotate, which uses Euler angles."

3. Camera panning

        In the Unity scene window, we can hold down the mouse wheel to pan, and in Blender, we can hold down the left Shift + mouse wheel to pan the perspective. In addition, in Unity, we can also control the movement of the perspective through the up, down, left, and right keys on the keyboard. In the project, we will try to control the camera pan to simulate the above effect.

1. Keyboard control panning

        The code for keyboard control panning is very simple, but before that, the Input Manager should be set up in Unity's Project Setting. As shown below:

        Calling Input.GetAxis("Vertical") and Input.GetAxis("Horizontal") in the script will return a float value. Since the type is set to "Key or Mouse Button", -1, 0, and 1 will be returned. value.

        Input.GetAxis("Vertical") will return 1 when the W or ↑ key on the keyboard is pressed, -1 when the S or ↓ key is pressed, and 0 when no key is pressed; similarly, when the D or → key is pressed Input.GetAxis("Horizontal") will return 1, -1 when the A or ← key is pressed, and 0 if not pressed.

        Based on this attribute, the code for controlling translation can be obtained:

float moveZ = Input.GetAxis("Vertical") * moveSpeedWithKeyBoard * Time.deltaTime;
float moveX = Input.GetAxis("Horizontal") * moveSpeedWithKeyBoard * Time.deltaTime;
transform.position += transform.forward *  moveZ + transform.right * moveX;

2. Mouse control panning

        I will press the wheel and drag the mouse to control the camera to pan up, down, left and right, and roll the wheel to control the front and back pan.

        The first thing is to move back and forth and make sure your Input Manager settings are as shown in the picture:

        Get the forward and backward movement value by calling Input.GetAxis("Mouse ScrollWheel"). This function will also return a float value. If the wheel rolls forward, it will be positive, and if it rolls backward, it will be negative. code show as below:

float MouseScroll = Input.GetAxis("Mouse ScrollWheel") * moveSpeedWithScroll * Time.deltaTime;
transform.position += transform.forward * MouseScroll;

       

        Then move up, down, left, and right, and get the value of the mouse movement on the xy axis when the mouse wheel is pressed:

if (Input.GetMouseButton(2))
{
    float moveX = -Input.GetAxis("Mouse X") * moveSpeedWithMouse * Time.deltaTime;
    float moveY = -Input.GetAxis("Mouse Y") * moveSpeedWithMouse * Time.deltaTime;

    transform.position += transform.right * moveX + transform.up * moveY;
}

3. Integration 

        Based on the above, it is not difficult to find the similarities between these pieces of code: receive input from the mouse or keyboard and calculate the movement values ​​​​of the camera in the three directions of forward, right, and up, then multiply the corresponding direction vectors and add them to the camera position, so it can be integrated into the following function:

/// <summary>
/// 相机移动
/// </summary>
public void Move()
{

    float moveX = 0;
    float moveY = 0;
    float moveZ = 0;

    // 接收键盘输入
    moveZ = Input.GetAxis("Vertical") * moveSpeedWithKeyBoard * Time.deltaTime;
    moveX = Input.GetAxis("Horizontal") * moveSpeedWithKeyBoard * Time.deltaTime;

    // 接收滚轮输入
    moveZ = Input.GetAxis("Mouse ScrollWheel") * moveSpeedWithScroll * Time.deltaTime;

    // 接收鼠标输入
    if (Input.GetMouseButton(2))
    {
        moveX = -Input.GetAxis("Mouse X") * moveSpeedWithMouse * Time.deltaTime;
        moveY = -Input.GetAxis("Mouse Y") * moveSpeedWithMouse * Time.deltaTime;
    }

    // 控制移动
    transform.position += transform.forward * moveZ + transform.right * moveX + transform.up * moveY;

}

4. Camera rotation

         There are two common types of camera rotation, namely the rotation of the camera itself and the rotation of the camera around the target object. In the scene window of Unity, hold down the mouse wheel to rotate around itself, and hold down the left Alt + left mouse button to rotate around the selected object. Below we will try to achieve the above effect.

1. Rotate around itself

        The idea of ​​rotating around itself is simple, just get the mouse input and change the rotation of the camera itself. code show as below:

if (Input.GetMouseButton(0))
{
    float rotateX = Input.GetAxis("Mouse X") * rotateSpeed * Time.deltaTime;
    float rotateY = Input.GetAxis("Mouse Y") * rotateSpeed * Time.deltaTime;

    Vector3 eulerAngles = transform.eulerAngles;

    eulerAngles.y += rotateX;
    eulerAngles.x -= rotateY;

    transform.eulerAngles = eulerAngles;
}
2. Rotate around the target object

        Rotating around the target object is more complicated and requires changing the values ​​of position and rotation at the same time. First determine the target object, and then change the position value. This process is the same as the mouse control translation above. Next, you need to change the rotation value to ensure that the camera is always facing the target object. Just call the transform.LookAt() function.

        Of course, using the above method can roughly achieve rotation around, but there is still a small problem, that is, the camera will gradually move away from the target object during the rotation. The reason is that every time we change the value of position, the distance between the two will increase a little. (Based on the principle that the hypotenuse of a triangle is greater than the right-angled side), and the subsequent steps did not offset this distance change.

        After all the above steps, the distance should be corrected and the camera position should be moved in the direction of the target object to a position where the distance remains unchanged. The final code is as follows:

if (Input.GetMouseButton(1))
{
    float rotateX = Input.GetAxis("Mouse X") * rotateSpeed * Time.deltaTime;
    float rotateY = Input.GetAxis("Mouse Y") * rotateSpeed * Time.deltaTime;

    float distance = Vector3.Distance(target.transform.position, transform.position);

    transform.position += transform.right * -rotateX + transform.up * -rotateY;

    transform.LookAt(target.transform);

    transform.position = target.transform.position + -transform.forward * distance;
}
3. Integration 

        ​ ​Similarly, we integrate and encapsulate the above two pieces of code into functions, and we can get the following code:

/// <summary>
/// 相机旋转
/// </summary>
public void Rotate()
{
    //接收输入
    float rotateX = Input.GetAxis("Mouse X") * rotateSpeed * Time.deltaTime;
    float rotateY = Input.GetAxis("Mouse Y") * rotateSpeed * Time.deltaTime;

    // 绕自身旋转
    if (Input.GetMouseButton(0))
    {
        Vector3 eulerAngles = transform.eulerAngles;

        eulerAngles.y += rotateX;
        eulerAngles.x -= rotateY;

        transform.eulerAngles = eulerAngles;
    }


    // 绕喷头旋转
    if (Input.GetMouseButton(1))
    {
        float distance = Vector3.Distance(target.transform.position, transform.position);

        transform.position += transform.right * -rotateX + transform.up * -rotateY;

        transform.LookAt(target.transform);

        transform.position = target.transform.position + -transform.forward * distance;
    }
}

5. Optimization function

1. Adjust the speed

        In the above method, the speed of movement is constant, which may cause the camera to appear to be moving very slowly when it is far away from the object, and too fast when it is very close to the object. You can write a function to determine the distance between the camera and the target object. Automatically adjusting the speed may give you a better feel.​ 

2. Switch target objects

        The above method does not mention the switching and selection of the target object. You can add a function to select the object in the game by clicking the mouse as the target object to rotate around. To switch the target, you only need to select other objects.

3. Set common camera observation points

        In actual projects, several commonly used camera positions can be set, and users can quickly switch to this position for observation through shortcut keys. For example, in the simulation of a 3D printer, an observation point can be set in front of the printer window to simulate the actual user's perspective of observing the 3D printer.

Guess you like

Origin blog.csdn.net/m0_67636792/article/details/134743760
Recommended