【Unity】设计一个基本的第一人称控制器

在这里插入图片描述
在这里插入图片描述
如图所示,创建一个胶囊体,将其放在一个空物体下,去除胶囊体的Collider。将Camera也放在空物体下。在空物体下加上一个capsule colliderr,同时给空物体加上rigibody,freeze其x和轴的旋转。
在这里插入图片描述
创建脚本 FPSMouseLook,将其挂在相机上,代码内容如下:

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

public class FPSMouseLook : MonoBehaviour
{
    //控制人物视野的脚本,挂在摄像机上
    public Transform characterTransform;//人物的Transform组件
    public float mouseSensitivity;
    public float maxX;
    public float minX;

    private Vector3 cameraRotation;
    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        cameraRotation.y += mouseX*mouseSensitivity;
        cameraRotation.x -= mouseY*mouseSensitivity;

        cameraRotation.x = Mathf.Clamp(cameraRotation.x, minX, maxX); //限制角色上下视野范围

        transform.rotation = Quaternion.Euler(cameraRotation.x, cameraRotation.y, 0);

        characterTransform.rotation = Quaternion.Euler(0, cameraRotation.y, 0);//控制角色的朝向
    }
}

创建脚本FPSMove,将其挂在那个空物体下,内容如下:

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

public class FPSMove : MonoBehaviour
{
    //控制人物视野的脚本,挂在人物上

    Rigidbody characterRigidbody;

    public float speed;
    void Start()
    {
        characterRigidbody = gameObject.GetComponent<Rigidbody>();
    }
    void FixedUpdate()//FixedUpdate是在固定的时间间隔执行,不受游戏帧率的影响
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        Vector3 currentDirection = new Vector3(h, 0, v); //当前输入所产生的方向

        currentDirection = transform.TransformDirection(currentDirection);//将此方向转换为世界方向
        currentDirection *= speed;//转换为速度

        Vector3 currentVelocity = characterRigidbody.velocity;//获取当前的人物速度
        Vector3 velocityChange = currentDirection - currentVelocity;//获得速度变化
        velocityChange.y = 0;//Y轴方向速度不需要变化

        characterRigidbody.AddForce(velocityChange, ForceMode.VelocityChange);//根据速度的变化添加力来控制移动
    }
}

完成!进入游戏试试吧!

拓展:
利用rigibody实现移动还是有很多bug的,比如抖动就无法避免,为此我们可以给游戏物体添加一个CharacterController,并且使用以下脚本控制移动。

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

public class FPSCharacterMove : MonoBehaviour
{
    private CharacterController characterController;
    private Vector3 moveDirection;
    public float walkSpeed;
    public float runSpeed;
    public float crouchSpeed;
    public float jumpHeight;
    public float gravity;

    public bool isRunning;
    public float currentSpeed;

    public bool isCrouched;
    public float crouchHeight;
    public float originHeight;
    private void Start()
    {
        characterController = gameObject.GetComponent<CharacterController>();
        isRunning = false;
        isCrouched = false;
        currentSpeed = walkSpeed;
        originHeight = characterController.height;
    }

    private void Update()
    {
        if(characterController.isGrounded)
        {
            float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");

            //MoveDirection存储移动的方向
            moveDirection = transform.TransformDirection(new Vector3(h, 0, v));

            //实现跳跃
            if (Input.GetKeyDown(KeyCode.Space))
                moveDirection.y = jumpHeight;

            //实现类似于使命召唤的按shift奔跑的效果
            if (Input.GetKeyDown(KeyCode.LeftShift) && Input.GetKey(KeyCode.W))
                isRunning = !isRunning;
            if (Input.GetKeyUp(KeyCode.W))
                isRunning = false;

            //使用协程实现下蹲,并且下蹲有不同的移动速度
            if (Input.GetKeyDown(KeyCode.Z))
            {
                float targetHeight = isCrouched ? originHeight : crouchHeight;
                StartCoroutine("DoCrouch",targetHeight);
                isCrouched = !isCrouched; 
            }

            currentSpeed = isRunning ? runSpeed : walkSpeed;
            currentSpeed = isCrouched ? crouchSpeed: currentSpeed;
        }
        //如果人物浮空,则下落
        moveDirection.y -= gravity * Time.deltaTime;
        //用不同的速度移动
        characterController.Move(moveDirection *currentSpeed * Time.deltaTime);
    }

    IEnumerator DoCrouch(float targetHeight)
    {
        float velocity = 0;
        while(Mathf.Abs(characterController.height-targetHeight)>0.1f)
        {
            yield return null;
            characterController.height=
                Mathf.SmoothDamp(characterController.height,targetHeight, ref velocity,Time.deltaTime * 5);
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值