IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity使用协程要求用户按顺序“一步一步”进行操作 -> 正文阅读

[游戏开发]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完成该步骤。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-07-07 11:54:15  更:2021-07-07 11:54:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 20:38:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计