项目场景:


需求:物体跟随鼠标所指引的方向移动,可以跳跃,奔跑,蹲下。

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对象的一些组件

unity 控制Linerender朝向 unity控制人物旋转_鼠标移动


代码展示

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对象的一些组件

unity 控制Linerender朝向 unity控制人物旋转_System_02

unity 控制Linerender朝向 unity控制人物旋转_鼠标移动_03


unity 控制Linerender朝向 unity控制人物旋转_鼠标移动_04


unity 控制Linerender朝向 unity控制人物旋转_System_05


代码展示

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变换这一块。