第一人称视角的角色移动

第一人称视角的角色移动

一、素材下载

1、在资源商店中,搜索名字进行下载:Low-Poly Simple Nature Pack。
在这里插入图片描述
2、下载完毕后,直接全部导入。
在这里插入图片描述

二、场景部署

1、打开Demo场景,用Demo场景来做练习。
在这里插入图片描述
2、右击新建一个空物体,重命名为Environment。
在这里插入图片描述
3、将除了相机外的所有对象选中,拖入Environment中,方便管理,将它折叠起来。
在这里插入图片描述
4、新建一个胶囊体,重命名为Player。用它来当我们控制的角色。
在这里插入图片描述
5、重置Transform位置。
在这里插入图片描述
6、稍微调整一下Player位置,不让它卡在地里。再将Cameras移到Player中,作为子对象。重置一下Cameras的Transform。

7、场景部署完毕,接下来就是敲代码时间。

三、敲定代码

(一)为Camaras添加脚本

1、新建文件夹,重命名Scripts,存放脚本。
在这里插入图片描述
2、新建CameraController脚本,控制相机。将CameraController脚本拖拽到Cameras中。

3、双击打开脚本。
(1)先定义两个float类型的变量,来获得鼠标移动的值。

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

(2)可以给鼠标增加一个灵敏度,用来控制鼠标移动的速度。

public float mouseSensitivity;  //鼠标灵敏度

(3)在Update方法中,使用输入系统中的GetAxis方法来获取鼠标移动的值,乘以鼠标灵敏度,再乘以Time.deltaTime。鼠标左右移动的值就这样得到了。

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

(4)通过控制Player的旋转的方法,来控制相机视角左右移动,所以需要一个Player的Transform。

public Transform player;

(5)回到Update方法中,使用Transform的Rotate()方法来旋转Player。这个方法有6个重构,我们只需要在里面填入一个Vector3的值就可以了。我们需要控制Player的Y轴旋转,才能让它左右旋转。

player.Rotate(Vector3.up * mouseX);

(6)接下来我们要旋转相机了,使用transform.localRotation的方法,让相机上下旋转。使用localRotation就可以不被父对象的旋转影响。因为localRotation是属性,所以我们还要给它赋值。让它等于Quaternion.Euler,Euler方法中需要传入三个值,这里填入-mouseY,0,0。

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

(7)回到Unity3D中,将需要设置的值设置上。
在这里插入图片描述
(8)运行时发现了一个问题,在鼠标上下移动的时候,视角一卡一卡的,并且移不动。问题出现在哪里呢?问题就在:Y轴的GetAxis方法,会返回-1到1之间的浮点数,在鼠标移动的时候,数值会随着方向的变化而变化,在鼠标不动时,数值会回弹到0。所以我们就会看见刚才那样的问题。我们只需要声明一个float变量来累加mouseY就可以了。

public float xRotation;

(9)在Update中写上:xRotation -= mouseY;,然后再把下面的-mouseY改为xRotation 。

(10)再回到Unity3D运行一下,会发现:玩家会无限制的上下旋转视角。有时候,我们需要做出一点限制,不至于让玩家呈现一种诡异的状态,再次回到代码中来。我们需要将xRotation的值限制在一个范围内,所以我们可以使用数学函数Mathf.Clamp()来限制,Clamp方法内需要填入三个值:第一个是需要限制的变量,第二个是限制的最小值,第三个是限制的最大值。

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

(11)最终CameraController 脚本代码如下。

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);
    }
}

(二)为Player添加脚本

1、新建PlayerController脚本,用来控制玩家的行动。
2、将PlayerController添加进Player对象中;删除胶囊控制器;添加角色控制器,它自带碰撞体和刚体。
在这里插入图片描述
在这里插入图片描述
3、双击打开代码。
(1)首先需要获得Player的CharacterController组件。

private CharacterController cc;

(2)定义Player的移动速度和跳跃速度。

public float moveSpeed;
public float jumpSpeed;

(3)定义获得按键值的两个变量。

private float horizontalMove, verticalMove;

(4)定义三维变量dir控制方向。

private Vector3 dir;

(5)在Start()函数中使用GetComponent方法获得CharacterController。

cc = GetComponent<CharacterController>();

(6)在Update中一样使用Input.GetAxis()方法获得按键的值。dir存储移动的方向。接下来使用CharacterController中的Move()方法来移动Player。

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

(7)回到Unity3D,将刚才定义的变量赋值。
在这里插入图片描述
(8)点击运行,现在可以移动了。将Player移到空中,它没有往下掉,很明显缺少重力,CharacterController是不带物体引擎的,所以我们要手动给它写个重力。

(9)回到代码中,定义两个变量,一个是重力,一个是速度。

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

(10)在Update中,velocity.y -= gravity * Time.deltaTime;,这样每秒它就会减去重力的值不断下降。再用Move()方法来移动Y轴。

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

(11)回到Unity3D中,将Player的位置提高,点击运行查看效果。发现了一个问题:刚开始可以顺畅的掉落,过一会就会一卡一卡的提不起来呢?我们鼠标放在Inspector视图的文字上,右键Debug。
在这里插入图片描述
在下面,我们可以看到刚才定义的velocity的y值正在不断减小,这就是问题所在。想要让它在落地后不再减小,我们需要回到代码中来。(重力手动设置为9.8)
在这里插入图片描述
(12)我们只需要检测Player是否在地上就可以了,这里可以使用Physics中的CheckSphere()方法。该方法的描述是:如果定义的球体和物体发生碰撞,返回真。所以为了使用这个方法,我们需要定义几个变量。

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

回到Update方法中,在最前面写代码:

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

(13)回到Unity3D,对刚刚设置的变量进行赋值。
在Player下面新建一个空对象,重命名为GroundCheck
在这里插入图片描述
再将它的位置拖到Player底部的位置,底部位置检测到它是否接触到地面
在这里插入图片描述
再将GroundCheck拖入,设置半径0.4
在这里插入图片描述
还有Ground Layer,可以点击右上角的Layer层,Add Layer…,自己添加一个Ground层就可以了。将Ground Layer修改为Ground。
在这里插入图片描述
在这里插入图片描述
(14)将Environment的Layer层改为Ground,然后会弹出一个对话框,直接点Yes,change children,它的子对象就会应用上Ground Layer。
在这里插入图片描述
在这里插入图片描述
(15)运行,自由落体得到了解决。现在还剩下跳跃功能没有实现。

(16)回到代码中。我们需要获取到跳跃按键的事件,所以我们使用Input系统中的GetButtonDown()方法,它会返回一个布尔值,当按下(按键)时才会返回真,其中的值Jump也可以在InputManager中查看。当按下跳跃键时,将velocity.y = jumpSpeed,这样就会在一瞬间有个向上的速度,在过程中也会随着重力慢慢下降。

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

(17)最终PlayerController脚本代码如下。

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);
    }
}

四、完成效果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46649692/article/details/116696818
今日推荐