美文网首页
Unity初学者实践与提高(四)---角色控制系统

Unity初学者实践与提高(四)---角色控制系统

作者: duanoldfive | 来源:发表于2022-06-29 15:40 被阅读0次
    效果

    输入系统

    上一章角色可以做不同的动作了,但是还是原地动作,现在我们让他真正的动起来。
    控制角色移动需要输入设备,PC上一般是用键盘控制,手机用触摸屏(软摇杆),其它硬件也有不同的配套输入设备,我们要给每种设备都写一套事件响应逻辑吗?显然不是一个好主意,Unity为我们提供了封装。
    以前的Unity版本中有Input,InputManager分别提供了读取设备输入值,以及通过虚拟轴映射游戏事件的作用,新版本提供了一套新的输入系统InputSystem.我们就介绍一下新输入系统的使用方法。
    首先打开包管理器: Window->Package Manager,选择Input System进行安装:


    安装

    随后弹出的对话框中选Yes.


    警告
    Unity将重新启动并禁用旧版Input Api,启用新版Input System.即使这里没有选Yes,我们也可以手动去切换输入系统,方法是打开项目设置: Edit->Project Setting->Player->Active Input Handling,选择Input System Package(New):
    设置

    遇到问题

    好了,输入系统切换完成,运行项目,发现UI不响应了,又发生了什么?
    其实这是因为UI默认采用的是老版输入系统作为其输入,我们只需要一个简单的设置就可以解决它。


    切换新输入系统

    在Hierarchy面板选中EventSystem,点击Inspector面板的 Replace with InputSystemUIInputModule.然后再运行项目,UI又恢复响应了。

    控制角色

    新输入系统准备好了,现在要开始控制角色了.
    控制角色有多种方式,可以用物理引擎控制,可以用Untiy提供的CharacterController来控制,我们为了学习,尝试自己实现一个简单的:
    先给角色加一个Player Input组件:


    PlayerInput组件

    在红框位置有一个CreateActions的按钮,按一下,选择文件位置,会创建一个Input Action Assets,同时会打开左边的面板。这里面定义好了一些Action,以及对输入设备的映射。
    写逻辑的时候,只要处理Action就好了,而不用管具体的是键盘输入的,还是手柄摇杆,达到了输入和逻辑相分离的目的。
    逻辑代码和Action关联的方式有多种,可以通过Player Input组件的Behavior来控制,它表示当有动作触发时的响应方式:

    • Send Messages
    • Broadcast Messages
    • Unity Events
    • CSharp Events

    这四种触发模式,从效率上看,Broadcast Messsages < Send Messages < Unity Events < Csharp Events。
    前两种很好接入,只要在脚本中添加 On{ActionName}()函数就可以。
    Unity Events 要在 Inspector 中分配各种回调函数,可视化操作,对新手友好,但在函数和动作逻辑较多时比较麻烦。
    最后一个比较高效,但是所有的动作共享同一个回调事件 event Action<InputAction.CallbackContext> onActionTriggerd,需要在这个函数中自行区分具体的触发动作。

    具体的接入方式可以参考Input System提供的Demo: 打开包管理器,选中Input System,在右边面板选中要查看的Demo,然后点击Import按钮(非必须):


    查看Demo

    现在我们来创建自己的角色控制逻辑,创建一个名为SimpleActorController的脚本,挂载到角色身上,代码如下:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.InputSystem;
    
    public class SimpleActorController : MonoBehaviour
    {
        public float moveSpeed; //角色移动速度
        
        private InputAction m_MoveAction;
        private Animator animator;
        private Vector3 rotationVector;
    
        
        private Vector2 m_Move;
    
        // Start is called before the first frame update
        void Start()
        {
            animator = GetComponent<Animator>();
    
            if (m_MoveAction == null)
            {
                PlayerInput input = GetComponent<PlayerInput>();
                m_MoveAction = input.actions["move"];
            }
        }
    
        private void Update()
        {
            MoveActor();
        }
    
        //移动角色
        public void MoveActor()
        {
            bool isMoving = false;
            if (m_MoveAction != null && m_MoveAction.IsPressed())
            {
                m_Move = m_MoveAction.ReadValue<Vector2>();
                if(m_Move.sqrMagnitude > 0.1f)
                {
                    Vector2 moveVector = m_Move * (moveSpeed * Time.deltaTime);
                    //求前进的方向
                    Vector3 dir = Camera.main.transform.localToWorldMatrix.MultiplyVector(new Vector3(moveVector.x, 0, moveVector.y));
                    dir.y = 0f;
                    dir = dir.normalized;
                    //把角色转向前进方向
                    transform.forward = Vector3.SmoothDamp(transform.forward, dir, ref rotationVector, 0.1f);
                    transform.position = transform.position + dir * moveVector.magnitude;
                    isMoving = true;
                }
            }
            
            animator.SetFloat("speed", isMoving ? moveSpeed : 0.0f);
        }
    }
    
    

    可以看到,我们用最简便快捷的方式,在Update函数中直接检测Action是否被按下,实际项目中不建议这么做。

    然后在Inspector面板中设置移动速度为5左右,现在运行程序,并尝试按方向按钮或者ASDW键,可以看到角色动起来了。

    再遇问题

    角色是可以移动了,但是好像反应迟钝,先滑步好长距离,才开始跑步,停下的时候也原地踏步半天才停下,这是什么原因呢?
    我们在实际项目中经常会遇到类似的状况,明明觉得该做的都做了,但总会出现一些意外。这就要考验大家知识掌握的是否扎实,或者经验是否老到。你可能会记起在学习Animator Controller的时候,有个Has Exit Time的选项,用来控制角色是否一定要播完上一个动作,再切换到下一个动作,目前这个现象很像是勾选了这个选项造成的,打开我们的RoleController,点击Idle状态,在Inspector面板中查看,果然是勾选状态,去掉勾选。


    去掉Has Exit Time

    我们还要能够举一反三,想想还有没有类似的问题,好像子状态机里面还有状态,好打开后进行同样的操作,保存再试.

    "果然好了,不那么迟钝了。可是为什么摄像机不跟着角色走呀?"

    因为我们还没有写摄像机控制的代码呀,游戏界有个名词叫 "3C" 就是 "Character Camera Control(角色、相机、控制)" 三个单词的缩写, 它的好坏直接影响到游戏体验,是游戏中十分重要的功能,我们的SimpleActorController是帮助大家入门,所以写的越简单越好,真正项目中要复杂的多,就等你去完善了。

    说到摄像机控制,我们下章再来实现吧。

    同样给出本章项目连接 角色控制系统


    返回主目录
    【转载请注明出处】

    相关文章

      网友评论

          本文标题:Unity初学者实践与提高(四)---角色控制系统

          本文链接:https://www.haomeiwen.com/subject/liowvrtx.html