第一部分:人物移动(1)

        文章总结:        

第一人称:FaceDirection(面朝方向)与 鼠标的方向一致。

        移动:moveDirection 为 FaceDirection.forward * 上下方向的输入 + FaceDirection.right * 左右方向的输入。

        旋转:人物的forward 永远跟随FaceDirection.forward 。

第三人称:FaceDirection(面朝方向)为摄像机位置指向人物的位置(忽略y轴影响)。

        移动:非锁定:moveDirection 永远为 人物的forward;锁定:moveDirection 为 transform.forward * 上下方向的输入 + transform.right * 左右方向的输入。

        旋转:非锁定:moveDirection 为 FaceDirection.forward * 上下方向的输入 + FaceDirection.right * 左右方向的输入; 锁定:moveDirection为从人物指向敌人。

        在人物上挂载有FaceDirection(存储角色应该移动的前方),在第一人称下FaceDirection是人物的面向(也是摄像机的朝向),而在第三人称下FaceDirection指的是摄像机相关(想象一个在地面上的摄像机)的面向(即忽略掉摄像机的Y轴)。同时挂有FirstCamPos,存储第一人称摄像机应该所在的位置。 

一:第一人称

        摄像机朝向有两种方案:

(1)始终朝向鼠标所指的方向。(2)始终朝着人物面向的前方。

        FirstPersonCamera类:

要点:1:使用全局变量记录要旋转的值   

           2:调用 Quaternion.Euler 同时调整摄像机的角度和人物面朝方向的角度

//第一人称视角下摄像机的行为
public class FirstPersonCamera : MonoBehaviour
{
    [Header("第一人称视角相机 参数")]
    public float senX;      //X轴灵敏度
    public float senY;      //Y轴灵敏度

    [Header("组件")]
    public Transform playerFaceDirection;  //人物面向的方向

    public Transform camPosition;

    private PlayerController playerController;

    private MouseController mouseInput;

    private float xRotation;

    private float yRotation;

    private void Awake()
    {
        mouseInput = new MouseController();
        playerController = playerFaceDirection.GetComponentInParent<PlayerController>();
    }

    private void OnEnable()
    {
        mouseInput.Enable();
        GlobalEvent.switchToFirstPersonEvent += OnSwitchToFirstPerson;
        GlobalEvent.CallSwitchToFirstPersonEvent();
    }

    private void OnDisable()
    {
        mouseInput.Disable();
        GlobalEvent.switchToFirstPersonEvent -= OnSwitchToFirstPerson;
    }

    private void OnSwitchToFirstPerson()
    {
        //在从第三人称转到第一人称的时候 需要调整yRotation xRotation
        yRotation = Vector3.Angle(playerFaceDirection.forward, Vector3.forward);
        xRotation = 0;
        if (Vector3.Cross(playerFaceDirection.forward, Vector3.forward).y > 0) yRotation *= -1;
    }

    private void Update()
    {
        transform.position = camPosition.position;
        Vector2 mouse = mouseInput.GamePlay.MouseMove.ReadValue<Vector2>();
        yRotation += mouse.x * Time.deltaTime * senX; //绕y轴的旋转(控制左右)
        xRotation -= mouse.y * Time.deltaTime * senY; //绕x轴的旋转(控制上下)

        xRotation = Mathf.Clamp(xRotation, -60f, 60f);

        //调整摄像机的朝向 选择1:始终朝向鼠标所指的方向   选择2:始终朝向人物面部的前方
        transform.rotation = Quaternion.Euler(xRotation, yRotation, 0);
        //transform.forward = camPosition.forward;

        playerFaceDirection.rotation = Quaternion.Euler(0, yRotation, 0); //调整人物面朝的方向               
    }
}

        PlayerController类:(移动和旋转)

要点:1:人物根据面朝的方向前后左右移动   2:人物的面向 = faceDirection的面向

           3:moveDirection 根据 faceDirectiono的forward和right进行计算

    //第一人称方式移动人物
    private void MovePlayerInFirstPerson()
    {
        //如果移动方向有阻碍物:障碍,敌人等 返回
        if (playerAnimationInf.IsWalk == false) return;
        moveDirection = faceDirection.forward * inputDirection.y + faceDirection.right * inputDirection.x;
        if (physicalCheck.HaveBarrierInMoveDirection(transform.position + transform.up * 0.5f, moveDirection, moveDirection.normalized.magnitude * curSpeed * Time.deltaTime * 2)) return;
        characterController.Move(moveDirection.normalized * (curSpeed * Time.deltaTime));
    }

    //第一人称方式旋转人物
    private void RotatePlayerInFirstPerson()
    {
        transform.forward = faceDirection.forward;
    }

Cinemachine的参数设置(VirtualMachine,最普通的相机,没有特殊功能,可以随意调整)

二:第三人称

        鼠标的移动只会导致摄像机的移动(使用CinemachiineFreeLook),WASD根据的是摄像机的朝向进行转向和移动。

        ThirdPersonCamera类:

要点:摄像机的 viewDir = X的坐标 - 摄像机的坐标 (注意忽略y轴)faceDirection.forward=viewDir   ( 战斗视角下X为Player右上角一个点,普通视角下X为Player)


//第三人称视角下 摄像机的行为
public class ThirdPersonCamera : MonoBehaviour
{
    [Header("组件")]
    public Transform faceDirection;

    public Transform combatLookAt;

    public Transform player;

    private CinemachineFreeLook cinemachine;

    private void Awake()
    {
        cinemachine=GetComponent<CinemachineFreeLook>();
    }

    private void OnEnable()
    {
        //在从第一人称转到第三人称的时候 需要调整 XAxis.Value
        float angle = Vector3.Angle(player.forward, Vector3.forward);
        if (Vector3.Cross(player.forward, Vector3.forward).y > 0) angle *= -1;
        cinemachine.m_XAxis.Value = angle;
    }

    private void Update()
    {
        //faceDirection.position = new Vector3(transform.position.x, cinemachine.LookAt.position.y, transform.position.z);
        //faceDirection.LookAt(cinemachine.LookAt);
        if (CameraManager.Instance.currentCameraStyle == CameraStyle.ThirdPersonNormal || CameraManager.Instance.currentCameraStyle == CameraStyle.ThirdPersonTopDown) 
        {
            Vector3 viewDir = player.position - new Vector3(transform.position.x, player.position.y, transform.position.z);
            faceDirection.forward = viewDir.normalized;
        }
        else if(CameraManager.Instance.currentCameraStyle==CameraStyle.ThirdPersonCombat)
        {
            Vector3 viewDir = combatLookAt.position - new Vector3(transform.position.x, combatLookAt.position.y, transform.position.z);
            faceDirection.forward = viewDir.normalized;
        }
    }
}

        PlayController类:

要点: 1:人物移动方向永远是面朝的方向     2:人物的面向根据 摄像机的viewDir(忽略掉Y轴后摄像机的面向)和输入共同调整(使用Slerp实现平滑转动)

    //第三人称方式移动人物
    private void MovePlayerInThirdPerson()
    {
        //人物的实际移动:始终朝着面朝的方向进行移动
        characterController.Move(transform.forward * curSpeed * Time.deltaTime);

    }

    //第三人称方式旋转人物
    private void RotatePlayerInThirdPerson()
    {

        moveDirection = faceDirection.forward * inputDirection.y + faceDirection.right * inputDirection.x;
        if(moveDirection!=Vector3.zero)
        {
            transform.forward = Vector3.Slerp(transform.forward, moveDirection, rotationSpeed * Time.deltaTime);
        }
    }

补充:第三人称视角还分成了3个:常规视角,战斗视角,俯视角

常规视角:

        Cinemachine设置:

        跟随和朝向都是Player,轨道设置如下:

战斗视角:

        人物保持在屏幕的左下方(通过将朝向设置为人物右上角的一个位置即可,在摄像机的viewDir计算时要变化),轨道设置如下:

俯视角:基本同常规视角,轨道设置如下:

不同视角的切换:切换动画由CinemachineBrain控制

        CameraManager类:

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

public class CameraManager : Singleton<CameraManager>
{
    [Header("不同摄像机")]
    public GameObject firstPersonCamera;
    public GameObject thirdPersonNormalCamera;
    public GameObject thirdPersonCombatCamera;
    public GameObject thirdPersonTopDownCamera;

    public CinemachineBrain cinemachineBrain;

    [Header("游戏状态")]
    public CameraStyle currentCameraStyle;          //当前摄像机所处的状态

    private void Start()
    {
        SwitchCameraStyle(CameraStyle.ThirdPersonNormal);
        cinemachineBrain.m_DefaultBlend.m_Style = CinemachineBlendDefinition.Style.EaseIn;
    }

    private void Update()
    {
        //按键设置
        if(Input.GetKeyDown(KeyCode.V))
        {
            if (currentCameraStyle != CameraStyle.FirstPerson)
                SwitchCameraStyle(CameraStyle.FirstPerson);
            else SwitchCameraStyle(CameraStyle.ThirdPersonNormal);
        }
    }

    public void SwitchCameraStyle(CameraStyle newStyle)
    {
        //先设置所有相机为false 在选择激活新相机

        firstPersonCamera.SetActive(false);
        thirdPersonNormalCamera.SetActive(false);
        thirdPersonCombatCamera.SetActive(false);
        thirdPersonTopDownCamera.SetActive(false);
        if (newStyle == CameraStyle.FirstPerson || currentCameraStyle == CameraStyle.FirstPerson) 
            cinemachineBrain.m_DefaultBlend.m_Style = CinemachineBlendDefinition.Style.Cut;
        else
            cinemachineBrain.m_DefaultBlend.m_Style = CinemachineBlendDefinition.Style.EaseIn;
        switch (newStyle)
        {
            case CameraStyle.FirstPerson:
                firstPersonCamera.SetActive(true);
                GlobalEvent.CallSwitchToFirstPersonEvent();
                break;
            case CameraStyle.ThirdPersonNormal:
                thirdPersonNormalCamera.SetActive(true);
                break;
            case CameraStyle.ThirdPersonCombat:
                thirdPersonCombatCamera.SetActive(true);
                break;
            case CameraStyle.ThirdPersonTopDown:
                thirdPersonTopDownCamera.SetActive(true);
                break;
        }
        currentCameraStyle = newStyle;
    }

}

在第一人称切换到第三人称时:保证切换后摄像机在人物的后方

在第三人称切换到第一人称时:需要手动调整yRotation

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值