欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity制作RPG游戏——按键功能的分类与实现

程序员文章站 2022-07-13 22:06:09
...

这一部分跟大家分享一个游戏开发中一个必须明白的问题,那就是怎么设计按键,有哪几种按键,怎么实现?

一、按键的种类

简单来说,一般有三类,

  • press signal :键位输入等,按下时获取并更新输入
  • once trigger signal:跳跃、(非蓄力)攻击等,当玩家按下按钮时,只执行一次便结束
  • double trigger signal:连击打combo,按键较少需要区分按下一次和短时间按下两次的功能时

先考虑前面两种状态,我们可以设计一个MyButton类,专门用于获取相应的状态。

public class MyButton_TEST
{
    //press signal
    public bool OnPressing;

    //once trigger
    public bool OnPressed;
    public bool OnReleased;

    private bool curstate;
    private bool laststate;

    //double trigger
    public bool isExtending;
    public bool isDelaying;


    public void Tick(bool input)
    {
        //按键输入
        curstate = input;
        OnPressing = curstate;

        OnPressed = false;
        OnReleased = false;

        if(curstate != laststate)
        {
            if(curstate == true)
            {
                OnPressed = true;
            }
            else
            {
                OnReleased = true;
            }
        }
        laststate = curstate;
    }
}

input脚本代码如下:

public class Input_TEST : MonoBehaviour
{
    public bool iswalk;

    public bool isjump;

    private MyButton_TEST iswalk_btn;
    private MyButton_TEST isjump_btn;
    // Start is called before the first frame update
    void Start()
    {
        iswalk_btn = new MyButton_TEST();
        isjump_btn = new MyButton_TEST();
    }

    // Update is called once per frame
    void Update()
    {
        iswalk_btn.Tick(Input.GetKey(KeyCode.W));
        isjump_btn.Tick(Input.GetKey(KeyCode.Space));

        iswalk = iswalk_btn.OnPressing;
        isjump = isjump_btn.OnPressed;

        print(iswalk);
        print(isjump);
    }
}

这样完整的将按钮的处理逻辑与其自身分离开来,符合里氏替换原则。untiy输出也是正确的。

下面我们来考虑double trigger的实现办法,由于double trigger需要计时操作,所以我们实现一个Mytimer类专门用来计时。

public class MyTimer_TEST 
{
    public enum STATE
    {
        IDLE,
        RUN,
        FINISHED
    }
    public float duration;
    private float elapsedtime;

    public STATE state = STATE.IDLE;

    public void Tick()
    {
        switch (state)
        {
            case STATE.IDLE:
                break;
            case STATE.RUN:
                elapsedtime += Time.deltaTime;
                if(elapsedtime >= duration)
                {
                    state = STATE.FINISHED;
                }
                break;
            case STATE.FINISHED:
                break;
            default:
                Debug.Log("Error");
                break;
        }
    }
    public void Go()
    {
        elapsedtime = 0;
        state = STATE.RUN;
    }
}

每一个button类中,应该有两种延迟信号,一种是按下后,持续多久还,一种是按下后放下,继续保持多久。说起来有点乱,可以画图表示:

Unity制作RPG游戏——按键功能的分类与实现

对每一个按钮,我们除了设计上面所说的OnPressed、OnPressing、OnReleased三种信号外,还会设计IsExtending和IsDelaying两种信号,这两种信号的实现依赖于上面所说的Timer。

对照上图,在时间点1的位置,OnPressed信号会获得true,其他时候都为false,在2时间段也就是delayTime时间段内,IsDelaying信号为true,其他信号的表示可以参考图左侧的描述。

对此,我们重新修改一下button类的结构,增加两种信号:

public class MyButton_TEST
{
    //press signal
    public bool OnPressing;

    //once trigger
    public bool OnPressed;
    public bool OnReleased;

    private bool curstate;
    private bool laststate;

    //double trigger
    public bool isExtending;
    public bool isDelaying;

    private MyTimer_TEST extendtimer = new MyTimer_TEST();
    private MyTimer_TEST delaytimer = new MyTimer_TEST();

    public void Tick(bool input)
    {
        extendtimer.Tick();
        delaytimer.Tick();

        //按键输入
        curstate = input;
        OnPressing = curstate;

        OnPressed = false;
        OnReleased = false;
        isExtending = false;
        isDelaying = false;

        if (curstate != laststate)
        {
            if (curstate == true)
            {
                OnPressed = true;
                StartTimer(delaytimer, 0.1f);
            }
            else
            {
                OnReleased = true;
                StartTimer(extendtimer, 0.1f);
            }
        }
        laststate = curstate;

        if (extendtimer.state == MyTimer_TEST.STATE.RUN)
        {
            isExtending = true;
        }
        if (delaytimer.state == MyTimer_TEST.STATE.RUN)
        {
            isDelaying = true;
        }
        
    }
    private void StartTimer(MyTimer_TEST timer, float duration)
    {
        timer.Go();
        timer.duration = duration;
    }
}

回到input脚本中,我们测试一下,这里设计一个doublekick字段,连按两下表示一次攻击,并修改walk字段的实现要求,当玩家按下walk,松开按钮的0.2秒的时间里,我们依然认为walk==true

Unity制作RPG游戏——按键功能的分类与实现

该设计就可以完成要求,可以在button的实现方法里将duration改为0.2即可。当然这里还可以修改一下button类,给予一个构造函数,该构造函数需要两个参数分别是delayingtime和extendingtime的值

Unity制作RPG游戏——按键功能的分类与实现

Unity制作RPG游戏——按键功能的分类与实现 

至此就修改完毕了,完成了对button按键的抽象,以此功能可以实现各种延迟按钮、各种combo效果。

相关标签: 游戏开发技术