Character movement from a first-person perspective

Character movement from a first-person perspective

1. Material download

1. In the resource store, search for the name to download: Low-Poly Simple Nature Pack.
insert image description here
2. After the download is complete, import all directly.
insert image description here

2. Scenario deployment

1. Open the demo scene and use the demo scene to do exercises.
insert image description here
2. Right-click to create an empty object and rename it Environment.
insert image description here
3. Select all the objects except the camera, drag them into the Environment for easy management, and fold it up.
insert image description here
4. Create a new capsule and rename it to Player. Use it as the character we control.
insert image description here
5. Reset the Transform position.
insert image description here
6. Adjust the position of the Player slightly so that it does not get stuck in the ground. Then move the Cameras to the Player as a child object. Reset the Transform of Cameras.

7. After the scene is deployed, the next step is to code.

3. Finalize the code

(1) Adding scripts to Camaras

1. Create a new folder, rename Scripts, and store scripts.
insert image description here
2. Create a new CameraController script to control the camera. Drag the CameraController script into Cameras.

3. Double-click to open the script.
(1) First define two variables of type float to obtain the value of mouse movement.

private float mouseX, mouseY;  //获取鼠标移动的值

(2) A sensitivity can be added to the mouse to control the speed of the mouse movement.

public float mouseSensitivity;  //鼠标灵敏度

(3) In the Update method, use the GetAxis method in the input system to obtain the value of the mouse movement, multiply it by the mouse sensitivity, and then multiply it by Time.deltaTime. The value of the left and right mouse movement is obtained in this way.

private void Update()
{
    
    
    mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
    mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
}

(4) By controlling the rotation of the Player, the camera angle of view is controlled to move left and right, so a Transform of the Player is required.

public Transform player;

(5) Back in the Update method, use the Transform's Rotate() method to rotate the Player. This method has 6 refactorings, we only need to fill in a Vector3 value in it. We need to control the Y-axis rotation of the Player to make it rotate left and right.

player.Rotate(Vector3.up * mouseX);

(6) Next, we need to rotate the camera. Use the transform.localRotation method to rotate the camera up and down. Using localRotation will not be affected by the rotation of the parent object. Because localRotation is an attribute, we also need to assign it a value. Let it be equal to Quaternion.Euler, three values ​​need to be passed in to the Euler method, here fill in -mouseY,0,0.

transform.localRotation = Quaternion.Euler(-mouseY, 0, 0);

(7) Go back to Unity3D and set the value that needs to be set.
insert image description here
(8) A problem was found during operation. When the mouse moved up and down, the viewing angle was stuck one by one and could not move. Where is the problem? The problem is: the GetAxis method of the Y axis will return a floating point number between -1 and 1. When the mouse moves, the value will change with the direction. When the mouse does not move, the value will rebound to 0 . So we will see the problem just now. We just need to declare a float variable to accumulate mouseY.

public float xRotation;

(9) Write in Update: xRotation -= mouseY;, and then change the following -mouseY to xRotation.

(10) Go back to Unity3D and run it again, and you will find that the player will rotate the viewing angle up and down without limit. Sometimes, we need to make a little restriction so that the player will not be in a weird state and come back to the code again. We need to limit the value of xRotation within a range, so we can use the mathematical function Mathf.Clamp() to limit. Three values ​​need to be filled in the Clamp method: the first is the variable that needs to be limited, and the second is the limit The minimum value, the third is the maximum limit.

xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -70f, 70f);

(11) The final CameraController script code is as follows.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour
{
    
    
    public Transform player;
    private float mouseX, mouseY;  //获取鼠标移动的值
    public float mouseSensitivity;  //鼠标灵敏度
    public float xRotation;
    private void Update()
    {
    
    
        mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -70f, 70f);

        player.Rotate(Vector3.up * mouseX);
        transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
    }
}

(2) Add scripts for Player

1. Create a new PlayerController script to control the player's actions.
2. Add PlayerController to the Player object; delete the capsule controller; add the character controller, which has its own collision body and rigid body.
insert image description here
insert image description here
3. Double-click to open the code.
(1) First, you need to obtain the CharacterController component of the Player.

private CharacterController cc;

(2) Define the player's moving speed and jumping speed.

public float moveSpeed;
public float jumpSpeed;

(3) Define two variables to obtain the key value.

private float horizontalMove, verticalMove;

(4) Define the three-dimensional variable dir to control the direction.

private Vector3 dir;

(5) Use the GetComponent method in the Start() function to obtain CharacterController.

cc = GetComponent<CharacterController>();

(6) Use the Input.GetAxis() method to obtain the value of the button in Update as well. dir stores the direction of movement. Next use the Move() method in CharacterController to move the Player.

horizontalMove = Input.GetAxis("Horizontal") * moveSpeed;
verticalMove = Input.GetAxis("Vertical") * moveSpeed;
dir = transform.forward * verticalMove + transform.right * horizontalMove;
cc.Move(dir * Time.deltaTime);

(7) Back to Unity3D, assign the variables just defined.
insert image description here
(8) Click to run, now you can move. Move the Player into the air, it does not fall down, obviously lacks gravity, CharacterController does not have an object engine, so we have to manually write gravity for it.

(9) Go back to the code and define two variables, one is gravity and the other is speed.

public float gravity;
private Vector3 velocity;  //用来控制Y轴加速度

(10) In Update, velocity.y -= gravity * Time.deltaTime;, so that every second it will subtract the value of gravity and keep dropping. Then use the Move() method to move the Y axis.

velocity.y -= gravity * Time.deltaTime;  //每秒它就会减去重力的值不断下降
cc.Move(velocity * Time.deltaTime);

(11) Go back to Unity3D, increase the position of the Player, and click Run to view the effect. I found a problem: It can be dropped smoothly at the beginning, but after a while, it will be stuck one by one and can't be picked up? We put the mouse on the text of the Inspector view and right-click Debug.
insert image description here
Below, we can see that the y value of the velocity we just defined is decreasing, which is the problem. To make it stop shrinking after landing, we need to go back to the code. (Gravity is manually set to 9.8)
insert image description here
(12) We only need to detect whether the Player is on the ground, here we can use the CheckSphere() method in Physics. The description of this method is: If the defined sphere collides with the object, return true. So in order to use this method, we need to define a few variables.

public Transform groundCheck;  //检测点的中心位置
public float checkRadius;  //检测点的半径
public LayerMask groundLayer;  //检测的图层
public bool isGround;  //布尔值来存储Physics.CheckSphere的返回值

Back in the Update method, write the code at the front:

isGround = Physics.CheckSphere(groundCheck.position, checkRadius, groundLayer);
if (isGround && velocity.y < 0)
{
    
    
    velocity.y = -3f;  //小于0旁边的数都行
}

(13) Go back to Unity3D and assign values ​​to the variables just set.
Create a new empty object under the Player, rename it GroundCheck
insert image description here
and drag its position to the bottom of the Player. The bottom position detects whether it touches the ground
insert image description here
and then drags GroundCheck in. Set the radius to 0.4
insert image description here
and the Ground Layer. You can click on the upper right The Layer layer of the corner, Add Layer..., just add a Ground layer by yourself. Change the Ground Layer to Ground.
insert image description here
insert image description here
(14) Change the Layer layer of Environment to Ground, and then a dialog box will pop up, just click Yes, change children, and its child objects will be applied to the Ground Layer.
insert image description here
insert image description here
(15) Run, free fall is solved. Now there is still a jump function that has not been implemented.

(16) BACK IN CODE. We need to get the event of the jump button, so we use the GetButtonDown() method in the Input system, which will return a boolean value, which will return true when the (button) is pressed, and the value Jump can also be viewed in the InputManager . When pressing the jump button, set velocity.y = jumpSpeed, so that there will be an upward speed in an instant, and it will slowly fall with gravity during the process.

if (Input.GetButtonDown("Jump") && isGround)
{
    
    
    velocity.y = jumpSpeed;
}

(17) The final PlayerController script code is as follows.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    
    
    private CharacterController cc;
    public float moveSpeed;
    public float jumpSpeed;
    private float horizontalMove, verticalMove;
    private Vector3 dir;
    public float gravity;
    private Vector3 velocity;  //用来控制Y轴加速度

    public Transform groundCheck;  //检测点的中心位置
    public float checkRadius;  //检测点的半径
    public LayerMask groundLayer;  //检测的图层
    public bool isGround;  //布尔值来存储Physics.CheckSphere的返回值
    private void Start()
    {
    
    
        cc = GetComponent<CharacterController>();
    }
    private void Update()
    {
    
    
        isGround = Physics.CheckSphere(groundCheck.position, checkRadius, groundLayer);
        if (isGround && velocity.y < 0)
        {
    
    
            velocity.y = -3f;  //小于0旁边的数都行
        }
        horizontalMove = Input.GetAxis("Horizontal") * moveSpeed;
        verticalMove = Input.GetAxis("Vertical") * moveSpeed;

        dir = transform.forward * verticalMove + transform.right * horizontalMove;
        cc.Move(dir * Time.deltaTime);

        if (Input.GetButtonDown("Jump") && isGround)
        {
    
    
            velocity.y = jumpSpeed;
        }

        velocity.y -= gravity * Time.deltaTime;  //每秒它就会减去重力的值不断下降
        cc.Move(velocity * Time.deltaTime);
    }
}

4. Complete the effect

insert image description here

Guess you like

Origin blog.csdn.net/qq_46649692/article/details/116696818