美文网首页
InputSystem和UGUI写法

InputSystem和UGUI写法

作者: 小飞不会飞_ | 来源:发表于2021-08-13 21:06 被阅读0次

    InputSystem是Unity新的输入系统,但在和UGUI结合使用的时候会出现问题。

    说一下现在项目中的做法,GamePlay的输入来源是封装在InputManager中,InputManager从InputSystem中去获取感兴趣的InputDevice收集的事件(信号),然后派发给游戏逻辑,或者调用游戏逻辑。这种做法是把输入和GamePlay的解耦开了。

    但是在UI这边,需要挂InputSystem组件(OnScreenContrl、OnScreenButton……),InputSystem组件相当于是游戏逻辑的输入源,不应该随着UI变化,换句话说无论UI怎么变化,游戏逻辑输入源都不该变化,输入源只会跟gameplay需求而变化。

    现在是和Button挂在一起,当UI隐藏的时候,InputSystem组件就会进行销毁,再显示的时候就会初始化,而InputSystem本身设计上应该是一个偏底层的系统,不应该随着UI显示和隐藏,它的生命周期应该是游戏的生命周期(或者小一点的级别)。

    InputSystem组件频繁的初始化和销毁,一方面性能会有问题,另一方面会出现事件被莫名打断的情况(OnEnable可能会重置数据)。

    如下一种基于InputSystem的代码设计,我觉得比较合理。


    InputManager设计.png
    • InputSystem:统一各种输入,包括不同硬件和UI。
    • InputManager:获取感兴趣的输入信号,派发或调用gameplay。
    • 硬件输入:InputSystem封装好了硬件输入,只需要配置就行。
    • UI:触摸或点击或拖拽屏幕按钮等输入。
    • 其它逻辑:有些逻辑可能需要模拟输入。

    下面有个简单封装例子
    InputSystem中按输入值类型分为三种:Button(Vector1),Vector2,Vector3
    如下包装:

    public class InputVector1Wrap:OnScreenControl
        {
            [InputControl( layout = "Button" )]
            [SerializeField]
            private string _controlPath;
    
            protected override string controlPathInternal
            {
                get => _controlPath;
                set => _controlPath = value;
            }
    
            public void SendValueToControl( float f )
            {
                base.SendValueToControl( f );
            }
        }
    
    public class InputVector2Wrap:OnScreenControl
        {
            [InputControl( layout = "Vector2" )]
            [SerializeField]
            private string _controlPath;
    
            protected override string controlPathInternal
            {
                get => _controlPath;
                set => _controlPath = value;
            }
    
            public void SendValueToControl( Vector2 v )
            {
                base.SendValueToControl( v );
            }
        }
    
    public class InputVector3Wrap:OnScreenControl
        {
            [InputControl( layout = "Vector3" )]
            [SerializeField]
            private string _controlPath;
    
            protected override string controlPathInternal
            {
                get => _controlPath;
                set => _controlPath = value;
            }
    
            public void SendValueToControl( Vector3 v )
            {
                base.SendValueToControl( v );
            }
        }
    
    public class InputManager : ManagerBase<InputManager>
        {
            public InputVector2Wrap move;
            public InputVector1Wrap jump;
            public InputVector1Wrap skill0;
            public InputVector1Wrap skill1;
            public InputVector1Wrap skill2;
            
            public void InputMove(Vector2 v)
            {
                move.SendValueToControl(v);
            }
    
            public void InputJump(float i)
            {
                jump.SendValueToControl(i);
            }
    
            public void InputSkill0(float i)
            {
                skill0.SendValueToControl(i);
            }
    
            public void InputSkill1(float i)
            {
                skill1.SendValueToControl(i);
            }
            
            public void InputSkill2(float i)
            {
                skill2.SendValueToControl(i);
            }
    
            private void Update()
            {
                //从InputSystem中获取不同事件,分发到游戏逻辑中
            }
        }
    

    UI这边的话,只需在点击技能按钮或者移动摇杆时调用

    InputManager.Instance.InputMove(delta);
    InputManager.Instance.InputJump(1);
    InputManager.Instance.InputSkill0(1);
    InputManager.Instance.InputSkill1(1);
    InputManager.Instance.InputSkill2(1);
    

    这样UI和GamePlay都不需要关心InputSystem了。

    相关文章

      网友评论

          本文标题:InputSystem和UGUI写法

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