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

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

一、按键的种类

简单来说,一般有三类,

  • 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类中,应该有两种延迟信号,一种是按下后,持续多久还,一种是按下后放下,继续保持多久。说起来有点乱,可以画图表示:

对每一个按钮,我们除了设计上面所说的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

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

 

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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值