Unity使用协程要求用户按顺序“一步一步”进行操作

Unity使用协程要求用户按顺序“一步一步”进行操作

许多游戏会在新手教程要求玩家按顺序操作,或者解谜游戏会要求玩家按顺序进行操作。
使用if语句未免不是一种方法,但是当步骤数特别多的时候,嵌套会使整段代码看上去非常臃肿,难以阅读。

使用协程去管理这些步骤,则不需要if语句去进行嵌套了。
此处抛砖引玉,演示一个极简的项目,要求用户按顺序依次点击ABC三个按钮,顺序正确则Debug打印按钮名字,错误则报错,并且从上一次按下的正确的按钮继续执行。
在这里插入图片描述

新建一个C#脚本命名为GameManager,并且新建空物体挂载这个脚本

代码

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

public class GameManager : MonoBehaviour
{
    int step;//当前进行到的步骤
    int pressed;//当前按下的按键,用来跟step进行比较判断是否点击正确
    bool check;

    private void Start()
    {
        step = 1;
        StartCoroutine("Begin");
    }

    public void Button_Press(int i)//每个按键并不执行输出功能,而只改变pressed值,然后在另一个方法判断是否点击正确并打印
    {
        pressed = i;
        check = true;//按下按键时使check为真,开始按键检测,检测完要将check重新设为false
    }

    void Error()//错误函数,每次按键错误“只会调用一次”该函数
    {
        Debug.Log("Wrong");
        //此处可以再调用一些动画机函数之类的方法,添加错误特效
    }

    bool Check()//检查按键是否正确,错误就报错
    {
        if (check)
        {
            if (pressed != step)
            {
                Error();
                check = false;
                return false;
            }
            check = false;
            return true;
        }
        return false;
    }

    IEnumerator Begin()
    {
        Debug.Log("开启协程");
        while (step <= 3)//step从1开始,“3”是总共的步骤数
        {
            yield return StartCoroutine("Step" + step);
            step++;
        }
        yield return null;
    }
    IEnumerator Step1()
    {
        Debug.Log("开始协程一");
        yield return new WaitUntil(() => Check() == true);//会一直调用Check()这个函数,直到这个函数返回true,
                                                          //但是因为加了check值,故每次错误只会调用一次报错函数
        Debug.Log("A");
        //此处可以加入想要执行的函数
        yield return null;
    }
    IEnumerator Step2()
    {
        Debug.Log("开始协程二");
        yield return new WaitUntil(() => Check() == true);
        Debug.Log("B");
        //此处可以加入想要执行的函数
        yield return null;
    }
    IEnumerator Step3()
    {
        Debug.Log("开始协程三");
        yield return new WaitUntil(() => Check() == true);
        Debug.Log("C");
        //此处可以加入想要执行的函数
        yield return null;
    }
}

在这里插入图片描述
给每一个按钮增添点击事件,“1”表示希望这个按钮第一个被点击,即顺序。

因为只有三个按钮,所以只加了三个协程,根据需要可以继续往下加Step4、Step5…
并不限于按钮,要点是改变pressed的值,故只要用户其他动作加入改变pressed值的代码即可。

补充

上述设计的思想是,每一个按钮会赋予全局变量pressed不同的值,并且启动检测机制判断preesed是否跟当前的步骤数相等,相等就执行相应的代码,否则就报错。
该设计一个弊端就是,因为step每次按钮点击正确就会自增1,而按钮的值是固定的,因此当同一个按钮需要被多次点击时就不适用了。
解决方案是
①修改pressed,每一个按钮增加一个int计数器计算点击次数,根据计数器值的不同改变不同的pressed值;
这样的话需要用if语句进行判断甚至嵌套,与我们设计的初衷违背。
②修改step,让它不再每次自增1。
StartCoroutine(“Step” + step)会根据函数名启用不同的协程,修改step意味着要修改函数名,而且后续新增步骤会带来麻烦。

故③修改检测机制。
原来的检测机制是step与pressed进行判断,那么只要不与step进行判断,而另起炉灶重载Check()函数,指定pressed跟我们需要的值进行判断即可。

bool Check(int i)
{
	//函数体与源代码一致,只需把step改为i
}
....
....
IEnumerator Step1()
    {
        Debug.Log("开始协程一");
        yield return new WaitUntil(() => Check(1) == true);
        Debug.Log("A");
        //此处可以加入想要执行的函数
        yield return null;
    }
IEnumerator Step2()
    {
        Debug.Log("开始协程二");
        yield return new WaitUntil(() => Check(1) == true);
        Debug.Log("A");
        //此处可以加入想要执行的函数
        yield return null;
    }

这样便可以使pressed指定与常量1进行比较,上述代码表示需要连续点击按钮A两次。

另外根据需要可以改变Check()的参数,例如

bool Check(int i,int j)
    {
        if (check)
        {
            if (pressed != i && pressed != j)
            {
                Error();
                check = false;
                return false;
            }
            check = false;
            return true;
        }
        return false;
    }

IEnumerator Step3()
    {
        Debug.Log("开始协程三");
        yield return new WaitUntil(() => Check(1, 2) == true);
        if (pressed == 1)
        {
            Debug.Log("A");
            //此处可以加入想要执行的函数,表示点击按钮A时执行的动作
        }
        else if( pressed == 2)
        {
            Debug.Log("B");
            //此处可以加入想要执行的函数,表示点击按钮B时执行的动作
        }
        //此处可以加入想要执行的函数,表示点击A、B都会执行的动作
        yield return null;
    }

就表示允许用户在特定的步骤里,既可以点击A,也可以点击B完成该步骤。

  • 8
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值