关于unity3d:黑魂复刻游戏的手柄输入支持Unity随手记

明天实现的内容:
Input Manager
要配置好手柄,咱们将应用Unity自带的Input Manager,这个零碎可能很好的打消输出设施的差别,对立各项输出,还能自定义新输出,并提供了输出相干的参数可供批改。

仔细观察能够发现,默认的Input Manager里每种输出模式都设置了两个。以Horizontal为例,其中一个是键盘输入,另一个是手柄输出,当咱们应用键盘时,Horizontal失去的是应用键盘输入,换成手柄当前Horizontal会主动变成手柄,十分智能。当然如果你无意要区别手柄,你也能够将第二个Horizontal改个名字。
上面的图展现了我设置的XBOX手柄输出设置。

JoystickInput类
JoystickInput类对标原PlayerInput类,原PlayerInput类被咱们写成了键鼠专用,所以当初被我改名为MouseKeyboardInput。
!
JoystickInput代码如下,相似MouseKeyboardInput:

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

public class JoystickInput : MonoBehaviour
{
    [Header("==== 手柄按键 ====")]
    // 角色挪动管制轴
    public string movementAxis_X = "X axis";
    public string movementAxis_Y = "Y axis";
    // 摄像机管制轴
    public string cameraAxis_X = "4th axis";
    public string cameraAxis_Y = "5th axis";

    // 游戏功能键
    public string buttonRun_jab_roll = "A"; //冲刺/后跃/翻滚
    public string buttonJump = "LS"; //跳跃键
    public string buttonAttackRHand = "RB"; //攻打键
    public string keyD;

    [Header("==== 输入信号 ====")]
    // 角色管制信号 damp之后的 向上/向右 方向值
    public float dirUp;
    public float dirRight;
    // 玩家的输出模长量 用于当成向前量大小作为动画管制
    public float dirMag;
    // 玩家的方向 用于旋转模型
    public Vector3 dirVec;

    // 摄像机管制信号
    public float cameraUp;
    public float cameraRight;

    // 按压信号   
    public bool run; //奔跑信号 是否正在奔跑

    // 一次性信号
    public bool jab_roll; //后跃/翻滚信号
    public bool jump; //跳跃信号
    public bool attack; //攻打信号

    [Header("==== 其它参数 ====")]
    // 模块软开关
    public bool inputEnabled = true;

    // 输出的damp工夫
    protected float dampTime = 0.1f;
    // 向上/向右 的最终方向值 用于将四键输出转换为双轴输出
    protected float m_targetDirUp;
    protected float m_targetDirRight;
    // 向上/向右 damp的currentVelocity参数
    protected float m_velocityDirUp;
    protected float m_velocityDirRight;
    // 映射后的输出双轴
    protected Vector2 m_dirAxis;
    // 按键按压计时器
    protected float pressTimer;
    // 单击的间隔时间 小于等于这个工夫是单击 大于这个工夫是长按(Long Press)
    protected float clickIntervalTime = 0.2f;

    // Update is called once per frame
    void Update()
    {
        // 摄像机信号
        cameraUp = Input.GetAxis(cameraAxis_Y);
        cameraRight = Input.GetAxis(cameraAxis_X);

        // 角色信号
        // 将高低键的输出整合 计算向上方向的输出大小
        m_targetDirUp = Input.GetAxis(movementAxis_Y);
        // 将左右键的输出整合 计算向右方向的输出大小
        m_targetDirRight = Input.GetAxis(movementAxis_X);

        // 输出模块是否敞开 这段代码肯定要放在这个地位
        if (!inputEnabled)
        {
            m_targetDirUp = 0;
            m_targetDirRight = 0;
        }

        // 使用SmoothDamp来取得突变的输出变动
        dirUp = Mathf.SmoothDamp(dirUp, m_targetDirUp, ref m_velocityDirUp, dampTime);
        dirRight = Mathf.SmoothDamp(dirRight, m_targetDirRight, ref m_velocityDirRight, dampTime);

        // 计算输出模长 
        dirMag = Mathf.Sqrt(dirUp * dirUp + dirRight * dirRight);
        // 计算玩家的方向
        dirVec = dirRight * transform.right + dirUp * transform.forward;

        // 冲刺/后跃/翻滚信号
        Jab_RollOrRun(buttonRun_jab_roll);
        // 攻打信号
        attack = Input.GetButtonDown(buttonAttackRHand);
        // 跳跃信号
        if (run && Input.GetButtonDown(buttonJump))
            jump = true;
        else
            jump = false;
    }

    // 长按还是单击 决定是冲刺还是翻滚/后跃
    private void Jab_RollOrRun(string _key)
    {
        if (Input.GetButtonDown(_key))
        {
            pressTimer = 0;
        }

        if (Input.GetButtonUp(_key) && pressTimer <= clickIntervalTime)
        {
            jab_roll = true;
        }
        else
        {
            jab_roll = false;
        }

        if (Input.GetButton(_key))
        {
            pressTimer += Time.deltaTime;
            if (pressTimer > clickIntervalTime)
                run = true;
        }
        else
        {
            run = false;
        }
    }
}

用抽象类对立不同的输出设施
到目前为止,咱们的游戏键鼠输出和手柄输出是离开的,其中有很多一样的货色,咱们能够应用一个抽象类来将这些不同的输出设施对立起来。咱们这个新的抽象类就取以前的老名字,叫IPlayerInput,I示意它做为接口。

public abstract class IPlayerInput : MonoBehaviour
{
    [Header("==== 输入信号 ====")]
    // 角色管制信号 damp之后的 向上/向右 方向值
    public float dirUp;
    public float dirRight;
    // 玩家的输出模长量 用于当成向前量大小作为动画管制
    public float dirMag;
    // 玩家的方向 用于旋转模型
    public Vector3 dirVec;

    // 摄像机管制信号
    public float cameraUp;
    public float cameraRight;

    // 按压信号   
    public bool run; //奔跑信号 是否正在奔跑

    // 一次性信号
    public bool jab_roll; //后跃/翻滚信号
    public bool jump; //跳跃信号
    public bool attack; //攻打信号

    [Header("==== 其它参数 ====")]
    // 模块软开关
    public bool inputEnabled = true;

    // 输出的damp工夫
    protected float dampTime = 0.1f;
    // 向上/向右 的最终方向值 用于将四键输出转换为双轴输出
    protected float m_targetDirUp;
    protected float m_targetDirRight;
    // 向上/向右 damp的currentVelocity参数
    protected float m_velocityDirUp;
    protected float m_velocityDirRight;
    // 映射后的输出双轴
    protected Vector2 m_dirAxis;
    // 按键按压计时器
    protected float pressTimer;
    // 单击的间隔时间 小于等于这个工夫是单击 大于这个工夫是长按(Long Press)
    protected float clickIntervalTime = 0.2f;
}

接下来,咱们的具体输出设施类只有继承自IPlayerInput,就不再须要再申明IPlayerInput中已有的变量了。当初,PlayerController和CameraController中的pi只有是IPlayerInput类型,在代码中就不须要指明当初应用何种输出类。

    // 以后应用的输出模块
    private IPlayerInput current_pi;

因为咱们理论有两个输出模块,所以咱们须要抉择咱们想要的那个输出类赋值到current_pi,上面的代码让咱们能够通过勾销沟选所有不必的输出模块来通知代码咱们要应用特定的输出模块,比方咱们想应用手柄,那么咱们能够勾销游戏对象上挂载的MouseKeyboardInput勾选。

    // 所有输出模块
    private IPlayerInput[] inputs;

    void Awake()
    {
        // ... 
        
        inputs = GetComponents<IPlayerInput>();
        foreach (var input in inputs)
        {
            if (input.enabled)
            {
                current_pi = input;
                break;
            }
        }
    }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理