[Unity]尝试实现第三人称控制器(其二、移动控制①)

[Unity]尝试实现第三人称控制器(其二、移动控制①)


【声明】此第三人称控制器是复现unity明星资产中第三人称控制器,如果有需要可以直接下载该资产并学习。我个人是不喜欢重复造轮子的行为的,但是官方的控制器我使用时有些不尽如人意的BUG。尽管如此,该控制器的效果让我觉得很不错,虽然无法实现无缝动画,不过个人项目应该先想办法让其动起来才行。
【版本】此项目基于Unity【2021.3lts】版本制作

选择移动方式

目前主流的是两种:1.rig+collider.2.CharactorController
此处为了学习,并且考虑的自己做的类型并不需要过于频繁的物理模拟,选择了第二种。

使用CharactorController

【注意】此处是我的代码逐渐合理的思考过程,如果你想看代码直接拖到最后。

动起来

首先为角色挂载我们之前准备的Input部分,这在后边会使用。
然后创建MoveController,并将创建的脚本挂载在角色身上。
为角色挂载CharactorController
我们使用CharactorController的Move方法:

Vector3 targetDir = Vector3.forward;
_characterController.Move(targetDir);

回到游戏测试,角色向前运动。

控制方向

var _currentInput = new Vector3(_inputsMassage.move.x, 0, _inputsMassage.move.y);
Vector3 targetDir = currentInput;
_characterController.Move(targetDir * Time.deltaTime);

能够前后左右移动了,测试没问题,接下来需要思考一些东西了

思考角色行为

在任何时候,只要我们按下前,角色就应该向我们的前方行走。我们只需要提取出移动的大小即可
首先定义行走速度,然后再判断是否有输入:

public float walkSpeed = 1.5f;
private float _currentSpeed;
//首先将移动速度赋予临时变量,考虑到有可能在其他地方使用,我们将其存储起来
_currentSpeed = walkSpeed;
//判断是否进行移动输入
if (_inputsMassage.move == Vector2.zero) _currentSpeed = 0;

我们会将角色分为几个状态,我们首先处理行走。

_characterController.Move(targetDir * _currentSpeed * Time.deltaTime);

作为固定状态,其移动速度是固定的,所以我们认为输入的move是仅指导方向,大小是由状态来决定的。
我们将上方的_currentInput进行归一化操作,得到其单位向量(其实原本与单位向量是类似的,我们只是进行确认)

var _currentInput = new Vector3(_inputsMassage.move.x, 0, _inputsMassage.move.y).normalized;

那么现在考虑按下左右的情况:
当按下左或右的时候,我们的角色应该进行一个旋转,

if (_inputsMassage.move!=Vector2.zero)
{
		_targetRotation = Mathf.Atan2(currentInput.x, currentInput.z) * Mathf.Rad2Deg;
}

那么上方的targeteDir就该与这个角度一致:

 Vector3 targetDir = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;

这里使用欧拉角将forward转过需要的角度。
我们测试发现,这些和我们之前的效果没有任何区别,为什么要做这么多没有意义的事情呢?
这是为了之后的Camera控制方向而准备的,当然目前代码里并没有该内容;
好的,至此我们做到的事情是什么呢,让角色的移动方向确定。但我们的角色并没有改变其方向。接下来处理这个问题。
我们通过Mathf.SmoothDampAngle来进行旋转

[Tooltip("角色光滑旋转时间")]
private float RotationSmoothTime = 0.12f;
[Tooltip("在角色光滑旋转过程中的速度")]
private float _rotationVelocity;

if (_inputsMassage.move!=Vector2.zero)
{
		_targetRotation = Mathf.Atan2(currentInput.x, currentInput.z) * Mathf.Rad2Deg;
		float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity,RotationSmoothTime);
		transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
        }

至此,第一个移动部分该结束了。不要着急,移动还有十分多的问题没有解决,接下来会逐步去处理

代码

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

public class ThirdPlayerMoveController : MonoBehaviour
{
    CharacterController _characterController;

    PlayerInputsMassage _inputsMassage;

    [Header("设置")]
    [Tooltip("这将决定普通行走时的速度")]
    public float walkSpeed = 1.5f;

    private float _currentSpeed;
    private float _targetRotation = 0.0f;
    [Tooltip("角色光滑旋转时间")]
    private float RotationSmoothTime = 0.12f;
    [Tooltip("在角色光滑旋转过程中的速度")]
    private float _rotationVelocity;

    // Start is called before the first frame update
    void Start()
    {
        _characterController = GetComponent<CharacterController>();
        _inputsMassage = GetComponent<PlayerInputsMassage>();
    }

    private void FixedUpdate()
    {
        Move();
    }
    private void Move()
    {
        //首先将移动速度赋予临时变量,考虑到有可能在其他地方使用,我们将其存储起来
        _currentSpeed = walkSpeed;
        //判断是否进行移动输入
        if (_inputsMassage.move == Vector2.zero) _currentSpeed = 0;

        var currentInput = new Vector3(_inputsMassage.move.x, 0, _inputsMassage.move.y).normalized;

        if (_inputsMassage.move!=Vector2.zero)
        {
            _targetRotation = Mathf.Atan2(currentInput.x, currentInput.z) * Mathf.Rad2Deg;
            float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity,
                RotationSmoothTime);
            transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
        }

        Vector3 targetDir = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;

        _characterController.Move(targetDir.normalized * _currentSpeed * Time.deltaTime);
        //TODO:这里的Move可以执行垂直方向的速度,直接加上垂直的Vector就可以
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值