11 游戏流程控制

使用协程来控制游戏流程

11.1 添加MessageText

首先添加一个Text来显示文字

 
image

设置GameMgr

 
image

11.2 游戏整体流程

下面GameMgr.cs最终代码预览,后面我们逐个讲解.

using UnityEngine;

using UnityEngine.UI;

using System.Collections;

public class GameMgr : MonoBehaviour

{

private int roundNumber = 0;  // 轮次.

public Text messageText; // ui text

private bool gameOver = false; // 本轮游戏是否已结束

// Use this for initialization

void Start ()

{

    StartCoroutine ( GameLoop ());

}

private IEnumerator GameLoop () // 游戏主循环逻辑

{

    yield return StartCoroutine (RoundStart ()); // 开始本轮游戏.

    yield return StartCoroutine (RoundPlay ()); // 游戏进行中.

    yield return StartCoroutine (RoundEnd ()); // 本轮游戏结束.

    StartCoroutine (GameLoop ()); // 开始下一轮游戏

}

private IEnumerator RoundStart ()

{

    roundNumber++; // 累计轮数

    messageText.text = "ROUND " + roundNumber;

    yield return new WaitForSeconds (2f);// 等待2s继续

}

private IEnumerator RoundPlay ()

{

    messageText.text = string.Empty; // 清空 "GamePlaying";//

    while (!gameOver) // 游戏结束才跳出

    {

        yield return null;

    }

}

private IEnumerator RoundEnd ()

{

    string message = "GameEnd"; // 显示分数

    messageText.text = message;

    yield return new WaitForSeconds (2f);// 等待2s继续

}

}

11.3 开始本轮游戏 RoundStart()

开始新一轮游戏是需要做三件事情

ResetTanks (); // 重置坦克

DisableTanksControl (); // 禁用坦克操作

camera.SetStartPositionAndSize ();// 重置相机

为了方便对坦克进行操作,我们写了TankMgr来实现对于坦克的控制。

 
image

TankMgr.cs

using UnityEngine;

using System.Collections;

public class TankMgr : MonoBehaviour {

public Transform spawnPoint; // 出生点

public void Reset(){// 重置坦克

    transform.position = spawnPoint.position;//坐标

    transform.rotation = spawnPoint.rotation;//旋转角度

    GetComponent<Health> ().blood = 100;//血值

}

public void EnableControl(){// 启用控制

    GetComponent<TankMove> ().enabled = true;

    GetComponent<TankShoot> ().enabled = true;

}

public void DisableControl(){ // 禁用控制

    GetComponent<TankMove> ().enabled = false;

    GetComponent<TankShoot> ().enabled = false;

}

}

还需要设置两个GameObject作为SpawnPosition

 
image
 
image

TankMgr是直接挂载到Tank上面的

 
image

最终RoundStart()函数里面是这样的

private IEnumerator RoundStart ()// 开始本轮游戏.

{

    ResetTanks (); // 重置坦克

    DisableTanksControl (); // 禁用坦克操作

camera.SetStartPositionAndSize ();// 重置相机

    roundNumber++; // 累计轮数

    messageText.text = "ROUND " + roundNumber;

    yield return new WaitForSeconds (2f);// 等待2s继续

}

因为要控制所有坦克,所以需要一个数组保存所有坦克。

public TankMgr[] tanks; // 所有坦克

private void ResetTanks(){ // 重置坦克状态

foreach( TankMgr tm in tanks)

    tm.Reset();

}

private void DisableTanksControl(){ // 禁用坦克操作

foreach( TankMgr tm in tanks)

    tm.DisableControl();

}

然后当游戏开始的时候重新起来坦克控制

IEnumerator RoundPlay(){

    foreach( TankMgr t in tanks){

        t.EnableControls ();

    }

    messageText.text = "Playing";

    while( true ){// 一直运行,直到有一个坦克挂掉

        yield return null;

    }

}

这是游戏处理运行过程,我们需要判断什么时候有坦克已经挂掉.

这时候我们发现按照之前在Health.cs里面的处理,坦克是直接被Destroy掉的.所以这个地方我们做一些调整.当坦克挂掉之后,我们把它SetActive(false)

public void TakeDamage( float damage){

    currentBlood -= damage; // 掉血

    slider.value = currentBlood; // 更新血槽显示

    if (currentBlood <= 0) {

        // die

        //ps.transform.parent = null;

        ps.Play ();

        audioSource.clip = explosionAudio;

        audioSource.Play ();

        //Destroy (ps.gameObject, ps.duration);

        //Destroy (gameObject);

        gameObject.SetActive ( false );

    }

}

这样当坦克挂掉之后并不是真的把它销毁了,我们可以使用gameObject.activeSelf来判断坦克是否已经挂掉

bool OneTankLeft(){ // 判断是否有坦克挂掉

    foreach( TankMgr t in tanks){

        if (t.gameObject.activeSelf == false)

            return true;

    }

    return false;

}

这样我们就可以终止RoundPlay里面的while语句了

IEnumerator RoundPlay(){

    foreach( TankMgr t in tanks){

        t.EnableControls (); // 启用坦克控制

    }

    messageText.text = "";

    while( !OneTankLeft() ){// 一直运行,直到有一个坦克挂掉

        yield return null;

    }

}

这样程序就可以执行到下一个阶段,就是RoundEnd函数里面了.

在游戏结束的时候我们需要知道玩家到底是谁,所以我们什么一个winner来保持赢家

private int winner; // 赢家

int GetWinner(){ // 谁是赢家

    for(int i=0;i<tanks.Length;i++){

        if (tanks [i].gameObject.activeSelf == true)

            return i;

    }

    return 0;

}

这个方法在如果有一个坦克挂掉的时候就返回此坦克在Tanks数组中的索引.如果两个坦克都挂掉了(是有这种可能的),现在返回的仍然是0,可以返回一个-1,单独处理,这个我们在这就不讲了,大家下去自己实现一些.

IEnumerator RoundEnd(){ // 本轮游戏结束

    winner = GetWinner ();

    messageText.text = "Player "+(winner+1)+" wins!";// 显示赢家

    yield return new WaitForSeconds (2f);

}

这样游戏就可以一轮一轮的进行下去了,如果我们想在某一轮后结束游戏,可以判断roundNum来实现.

---------------------------我是目录分割线---------------------------

《杜增强讲Unity之Tanks坦克大战》1-准备工作

《杜增强讲Unity之Tanks坦克大战》2-场景设置

《杜增强讲Unity之Tanks坦克大战》3-添加坦克

《杜增强讲Unity之Tanks坦克大战》4-坦克的移动和旋转

《杜增强讲Unity之Tanks坦克大战》5-子弹

《杜增强讲Unity之Tanks坦克大战》6-发射子弹

《杜增强讲Unity之Tanks坦克大战》7-坦克血条

《杜增强讲Unity之Tanks坦克大战》8-子弹碰撞处理

《杜增强讲Unity之Tanks坦克大战》9-发射子弹时蓄力

《杜增强讲Unity之Tanks坦克大战》10-相机控制

《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制

---------------------------我是目录分割线---------------------------

《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制的更多相关文章

  1. 《杜增强讲Unity之Tanks坦克大战》10-相机控制

    10 相机控制 本节主要学习如何控制相机自动调整位置和焦距,使两个坦克一直同时在视野内.   image 在Hierarchy点击右键   image 点击 Create Empty,生成空对象,改名 ...

  2. 《杜增强讲Unity之Tanks坦克大战》9-发射子弹时蓄力

    9 发射子弹时蓄力 实现效果如下   image 按下开火键(坦克1为空格键)重置力为最小力,一直按着的时候蓄力,抬起的时候发射.如果按着的时候蓄力到最大,则自动发射,此时在抬起则不会重复发射. 首先 ...

  3. 《杜增强讲Unity之Tanks坦克大战》4-坦克的移动和旋转

    4 坦克移动和旋转 本节课的目标是实现同时wsad和上下左右控制两个坦克分别移动和旋转 4.1 本节代码预览   image 将上节课场景s2另存为s3. 4.2 添加车轮扬沙效果 从Prefabs里 ...

  4. 《杜增强讲Unity之Tanks坦克大战》1-准备工作

    0.案例介绍 0.1开始界面   点击Play Now 进入游戏界面   左边的坦克使用ws控制前后移动,ad键左右旋转,空格键开火   右边的坦克使用方向键上下控制前后移动,方向键左右键实现左右旋转 ...

  5. 《杜增强讲Unity之Tanks坦克大战》2-场景设置

    2  场景设置 2.1 本节效果预览   2.2 项目目录设置 点击Project面板的Create按钮,在根目录下面新建wm文件夹   Wm文件夹用于存放我们自己生成的Prefab和脚本等其他资源, ...

  6. 《杜增强讲Unity之Tanks坦克大战》3-添加坦克

    3 添加坦克 3.1 本节效果预览   3.2 另存新场景 首先打开上次的场景s1,另存为s2,放到同一个文件夹下面.   3.3 添加坦克模型 在Model文件夹下面找到Tank模型   将Tank ...

  7. 《杜增强讲Unity之Tanks坦克大战》5-子弹

    5 子弹 本节的任务是创建子弹的Prefab   image 首先从Model/Shell找到子弹的模型,拖入Hierarchy中,添加刚体组件,所有属性默认值. 添加Capsule Collider ...

  8. 《杜增强讲Unity之Tanks坦克大战》6-发射子弹

    6 发射子弹 本节完成发射子弹的功能,最终代码如下:   image 首先,发射子弹得确定发射的位置和方向,还有发射的初始速度.具体的发射速度和按下发射按键的时间长短有关,这个关于子弹的蓄力我们在第九 ...

  9. 《杜增强讲Unity之Tanks坦克大战》7-坦克血条

    7 坦克血条 点击菜单GameObject->UI->Slider创建Slider   选中EventSystem,设置Horizontal Axis为HorzontalUI,Vertic ...

随机推荐

  1. tcp的半连接与完全连接队列

    队列及参数 https://segmentfault.com/a/1190000008224853 server端的半连接队列(syn队列) 在三次握手协议中,服务器维护一个半连接队列,该队列为每个客 ...

  2. Huawei DHCP 全局配置与接口配置

    网络拓扑图如下所示: 说明: 1.交换机Ge0/0/1口和Ge0/0/2口配置基于全局的DHCP: 2.交换机Ge0/0/3口配置基于端口的DHCP: 3.交换机上配置vlan 10 .vlan 20 ...

  3. java调用Linux执行Python爬虫,并将数据存储到elasticsearch--(环境脚本搭建)

    java调用Linux执行Python爬虫,并将数据存储到elasticsearch中 一.以下博客代码使用的开发工具及环境如下: 1.idea: 2.jdk:1.8 3.elasticsearch: ...

  4. python第三十二课——队列

    队列:满足特点 --> 先进先出,类似于我们生活中的买票.安检 [注意] 对于队列而言:python中有为其封装特定的函数,在collections模块中的deque函数就可以获取一个队列对象; ...

  5. BZOJ5102:[POI2018]Prawnicy(贪心,堆)

    Description 定义一个区间(l,r)的长度为r-l,空区间的长度为0. 给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大. Input 第一行包含两个正整数n,k(1<= ...

  6. Jmeter遇到线程链接被重置(Connection reset by peer: socket write error)的解决方法

    做性能测试的时候遇到一个很奇怪的问题,多线程的计划,有一个线程第一次能跑过,第二次确跑不过,单独跑这个线程跑多少次都没有问题,把思考时间改短也没有问题,唯独出现在特定的状态下,特定状态是啥,也不得而知 ...

  7. Odoo进销存业务思路浅析

    转载请注明原文地址:https://www.cnblogs.com/cnodoo/p/9307485.html  一:采购业务(进) 1:根据采购对象和性质,采购业务主要分为四类: 生产性采购:采购企 ...

  8. 谷歌开源漏洞跟踪工具 Monorail 存在跨站点搜索漏洞

    一名安全研究员表示,在谷歌开源漏洞跟踪工具 Monorail 中找到一个漏洞,可被用于执行跨站点搜索 (XS-Search) 攻击. Monorail 用于检查和 Chromium 相关项目中的问题, ...

  9. python3——print使用

        print的初步认识:对于科班出身的或有相关经验的人来说,学习python是相当有趣的事,因为可以做日常任务, 比如自动备份你的MP3:可以做网站,如YouTube就是Python写的:可以做 ...

  10. 基于Docker一键部署大规模Hadoop集群及设计思路

    一.背景: 随着互联网的发展.互联网用户的增加,互联网中的数据也急剧膨胀.每天产生的数据量数以万计,本地文件系统和单机CPU已无法满足存储和计算要求.Hadoop分布式文件系统(HDFS)是海量数据存 ...