【Unity】人物控制 移动/跳跃/蹲下/奔跑/视野旋转 代码

项目场景:

需求:物体跟随鼠标所指引的方向移动,可以跳跃,奔跑,蹲下。
1.视野跟随鼠标移动
2.由键盘控制物体的上下左右移动过程
3.可以跳跃和奔跑等

解决方案:

有很多在中解决方法,这里讨论两种

1.刚体+胶囊碰撞检测+脚本
2.CharcterController + 脚本


详细讲解:

方案一

思路阐述
1.创建一个GameObject,重命名为FPController
2.在FPController下,创建一个Capsule对象,并给FPController添加 Capsule Collider组件
3.将Camera移动到FPController下
4.给FPController添加RigidBody组件,并限制Rotation x,z,Use Gravity去除。
5.创建FPMouseLook脚本挂载Camera对象上,此脚本的主要作用是根据鼠标的移动,来使照相机的视野发生旋转。 6.创建FPMovement脚本来控制物体的移动
具体结构

FPController对象的一些组件
在这里插入图片描述


代码展示

1.FPMouseLook(挂在Camera上的)

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

public class FPMouseLook : MonoBehaviour
{

    //该脚本挂在Main Camera上
    //摄像机的视野跟随着鼠标的移动而移动
    private Transform cameraTransform;//摄像机所在的位置
    [SerializeField] private Transform charcterTransform;//FPController 的transform
    private Vector3 cameraRotation;//摄像机应该旋转的角度
    public float MouseSensitivity;//鼠标灵敏度
    public Vector2 MaxminAngle;//限制上下所能移动的最大角度
    private void Start()
    {
        cameraTransform = transform;
    }
    private void Update()
    {
        
        var tmp_mouseX = Input.GetAxis("Mouse X");//获取鼠标移动的x轴
        var tmp_mouseY = Input.GetAxis("Mouse Y");//获取鼠标移动的y轴

        cameraRotation.y += tmp_mouseX * MouseSensitivity;//根据鼠标灵敏度*x轴移动距离 = Y方向上偏移的角度
        cameraRotation.x -= tmp_mouseY * MouseSensitivity;//根据鼠标灵敏度*y轴移动距离 = X方向上偏移的角度

        cameraRotation.x = Mathf.Clamp(cameraRotation.x,MaxminAngle.x,MaxminAngle.y);//要将垂直方向上偏移的角度控制在设置的范围内

        cameraTransform.rotation = Quaternion.Euler(cameraRotation.x,cameraRotation.y,0);//改变摄像机的角度
        charcterTransform.rotation = Quaternion.Euler(0, cameraRotation.y, 0);//将FPController的rotation的水平方向,即FPController需要跟着鼠标移动的水平方向移动
        //不需要关注垂直方向的变化,简言之,就是头看天,人也不能忘天上走,还是要在水平方向走。

    }
}

2.FPMovement(挂在FPController上)

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

public class FPMovement : MonoBehaviour
{
    public float Speed;//行走速度
    private Transform characterTransform;//当前人物的transform
    private Rigidbody charcterRigidBody;//刚体
    private bool isGrounded;//是否着地
    public float Gravity;//重力
    public float JumpHeight;//跳跃高度
   
    private void Start()
    {
        characterTransform = transform;
        charcterRigidBody = GetComponent<Rigidbody>();
    }
    private void FixedUpdate()
    {
        if (isGrounded)
        {
        //在着地情况下才能移动
            var tmp_Horizontal = Input.GetAxis("Horizontal");
            var tmp_Vertical = Input.GetAxis("Vertical");

            var tmp_CurrentDirection = new Vector3(tmp_Horizontal, 0, tmp_Vertical);// 将用户的移动封装成一个Vector向量

            tmp_CurrentDirection = characterTransform.TransformDirection(tmp_CurrentDirection); //FPController需要根据这个方向行动

            tmp_CurrentDirection *= Speed;//行动方向*速度 = 矢量

            var tmp_CurrentVelocity = charcterRigidBody.velocity;//刚体现有速度

            var tmp_VelocityChange = tmp_CurrentDirection - tmp_CurrentVelocity;//矢量相减得到现有速度

            tmp_VelocityChange.y = 0;//只关注x,z轴,y轴的矢量为0

            charcterRigidBody.AddForce(tmp_VelocityChange, ForceMode.VelocityChange);//刚体添加力
            if (Input.GetButtonDown("Jump"))
            {
                charcterRigidBody.velocity = new Vector3(tmp_CurrentVelocity.x,CalculateJumpHeightSpeed(), tmp_CurrentVelocity.z);
            }
        }
        charcterRigidBody.AddForce(new Vector3(0,-Gravity*charcterRigidBody.mass,0));
       

    }
    private float CalculateJumpHeightSpeed()
    {
    //物理公式,v=开方2gh
        return Mathf.Sqrt(2 * Gravity * JumpHeight);

    }
    private void OnCollisionStay(Collision collision)
    {
        isGrounded = true;
    }
    private void OnCollisionExit(Collision collision)
    {
        isGrounded = false;
    }
}

方案二

思路阐述
1.创建一个GameObject,重命名为CharcterController
2.在FPController下,创建一个Capsule对象
3.将Camera移动到CharcterController下
4.创建FPMouseLook脚本挂载Camera对象上,此脚本的主要作用是根据鼠标的移动,来使照相机的视野发生旋转。 5.创建FPCharcterControllerMovement脚本控制移动,不同的是,该对象具有charcterController组件,代码很简单。
#### 具体结构

FPController对象的一些组件
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


代码展示

1.FPMouseLook(挂在Camera上的)

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

public class FPMouseLook : MonoBehaviour
{

    //该脚本挂在Main Camera上
    //摄像机的视野跟随着鼠标的移动而移动
    private Transform cameraTransform;//摄像机所在的位置
    [SerializeField] private Transform charcterTransform;//FPController 的transform
    private Vector3 cameraRotation;//摄像机应该旋转的角度
    public float MouseSensitivity;//鼠标灵敏度
    public Vector2 MaxminAngle;//限制上下所能移动的最大角度
    private void Start()
    {
        cameraTransform = transform;
    }
    private void Update()
    {
        
        var tmp_mouseX = Input.GetAxis("Mouse X");//获取鼠标移动的x轴
        var tmp_mouseY = Input.GetAxis("Mouse Y");//获取鼠标移动的y轴

        cameraRotation.y += tmp_mouseX * MouseSensitivity;//根据鼠标灵敏度*x轴移动距离 = Y方向上偏移的角度
        cameraRotation.x -= tmp_mouseY * MouseSensitivity;//根据鼠标灵敏度*y轴移动距离 = X方向上偏移的角度

        cameraRotation.x = Mathf.Clamp(cameraRotation.x,MaxminAngle.x,MaxminAngle.y);//要将垂直方向上偏移的角度控制在设置的范围内

        cameraTransform.rotation = Quaternion.Euler(cameraRotation.x,cameraRotation.y,0);//改变摄像机的角度
        charcterTransform.rotation = Quaternion.Euler(0, cameraRotation.y, 0);//将FPController的rotation的水平方向,即FPController需要跟着鼠标移动的水平方向移动
        //不需要关注垂直方向的变化,简言之,就是头看天,人也不能忘天上走,还是要在水平方向走。

    }
}

2.FPCharcterControllerMovement(挂在CharcterController上)

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

public class FPCharcterControllerMovement : MonoBehaviour
{
    private CharacterController characterController;
    private Transform charcterTransform;
    private float Gravity = 9.8f;
    private Vector3 movementDirection;
    private bool isCrouch;
    public float crouchHeight = 1f;
    private float originHeight;
    public float walkSpeed;
    public float jumpHeight;
    public float sprintingSpeed;
    public float sprintingSpeedCrouched;
    public float walkSpeedCrouched;
    void Start()
    {
        characterController = GetComponent<CharacterController>();
        charcterTransform = transform;
        originHeight = characterController.height;
    }

    // Update is called once per frame
    void Update() 
    {
        float tmp_Speed = walkSpeed;
        if (characterController.isGrounded)
        {
            var tmp_Horizontal = Input.GetAxis("Horizontal");
            var tmp_Vertical = Input.GetAxis("Vertical");

            movementDirection =
                charcterTransform.TransformDirection(new Vector3(tmp_Horizontal, 0, tmp_Vertical));
            if (Input.GetButtonDown("Jump"))
            {
                movementDirection.y = jumpHeight;
            }
            if (isCrouch)
            {
                tmp_Speed = Input.GetKey(KeyCode.LeftShift) ? sprintingSpeedCrouched : walkSpeedCrouched;
            }
            else
            {
                tmp_Speed = Input.GetKey(KeyCode.LeftShift) ? sprintingSpeed : walkSpeed;
            }
           

            if (Input.GetKeyDown(KeyCode.C))
            {
                var temp_CurentHeight = isCrouch ? originHeight : crouchHeight;
                StartCoroutine(DoCrouch(temp_CurentHeight));
                isCrouch = !isCrouch;
            }
           
        }
        movementDirection.y -= Gravity * Time.deltaTime;
        characterController.Move(movementDirection * Time.deltaTime * tmp_Speed);
    }
   IEnumerator  DoCrouch(float target)
    {
        float tmp_CurrentHeight = 0;
        while (Mathf.Abs(characterController.height - target) > 0.1f)
        {
            yield return null;
            characterController.height = Mathf.SmoothDamp(characterController.height,target,ref tmp_CurrentHeight,Time.deltaTime*5);
        }
        
    }
}


总结:

通过两种不同的方式来移动对象,学习到了很多知识,尤其是transform变换这一块。
  • 26
    点赞
  • 153
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder .

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值