乐趣区

关于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;
            }
        }
    }
退出移动版