《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制
11 游戏流程控制
使用协程来控制游戏流程
11.1 添加MessageText
首先添加一个Text来显示文字
设置GameMgr
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来实现对于坦克的控制。
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
TankMgr是直接挂载到Tank上面的
最终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坦克大战》4-坦克的移动和旋转
《杜增强讲Unity之Tanks坦克大战》9-发射子弹时蓄力
《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制
---------------------------我是目录分割线---------------------------
《杜增强讲Unity之Tanks坦克大战》11-游戏流程控制的更多相关文章
- 《杜增强讲Unity之Tanks坦克大战》10-相机控制
10 相机控制 本节主要学习如何控制相机自动调整位置和焦距,使两个坦克一直同时在视野内. image 在Hierarchy点击右键 image 点击 Create Empty,生成空对象,改名 ...
- 《杜增强讲Unity之Tanks坦克大战》9-发射子弹时蓄力
9 发射子弹时蓄力 实现效果如下 image 按下开火键(坦克1为空格键)重置力为最小力,一直按着的时候蓄力,抬起的时候发射.如果按着的时候蓄力到最大,则自动发射,此时在抬起则不会重复发射. 首先 ...
- 《杜增强讲Unity之Tanks坦克大战》4-坦克的移动和旋转
4 坦克移动和旋转 本节课的目标是实现同时wsad和上下左右控制两个坦克分别移动和旋转 4.1 本节代码预览 image 将上节课场景s2另存为s3. 4.2 添加车轮扬沙效果 从Prefabs里 ...
- 《杜增强讲Unity之Tanks坦克大战》1-准备工作
0.案例介绍 0.1开始界面 点击Play Now 进入游戏界面 左边的坦克使用ws控制前后移动,ad键左右旋转,空格键开火 右边的坦克使用方向键上下控制前后移动,方向键左右键实现左右旋转 ...
- 《杜增强讲Unity之Tanks坦克大战》2-场景设置
2 场景设置 2.1 本节效果预览 2.2 项目目录设置 点击Project面板的Create按钮,在根目录下面新建wm文件夹 Wm文件夹用于存放我们自己生成的Prefab和脚本等其他资源, ...
- 《杜增强讲Unity之Tanks坦克大战》3-添加坦克
3 添加坦克 3.1 本节效果预览 3.2 另存新场景 首先打开上次的场景s1,另存为s2,放到同一个文件夹下面. 3.3 添加坦克模型 在Model文件夹下面找到Tank模型 将Tank ...
- 《杜增强讲Unity之Tanks坦克大战》5-子弹
5 子弹 本节的任务是创建子弹的Prefab image 首先从Model/Shell找到子弹的模型,拖入Hierarchy中,添加刚体组件,所有属性默认值. 添加Capsule Collider ...
- 《杜增强讲Unity之Tanks坦克大战》6-发射子弹
6 发射子弹 本节完成发射子弹的功能,最终代码如下: image 首先,发射子弹得确定发射的位置和方向,还有发射的初始速度.具体的发射速度和按下发射按键的时间长短有关,这个关于子弹的蓄力我们在第九 ...
- 《杜增强讲Unity之Tanks坦克大战》7-坦克血条
7 坦克血条 点击菜单GameObject->UI->Slider创建Slider 选中EventSystem,设置Horizontal Axis为HorzontalUI,Vertic ...
随机推荐
- django直接操作MySQL,中文乱码
sql_insert = '''insert into sinfors_hvvms values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)''' c ...
- Coursera-AndrewNg(吴恩达)机器学习笔记——第四周编程作业(多分类与神经网络)
多分类问题——识别手写体数字0-9 一.逻辑回归解决多分类问题 1.图片像素为20*20,X的属性数目为400,输出层神经元个数为10,分别代表1-10(把0映射为10). 通过以下代码先形式化展示数 ...
- 乘风破浪:LeetCode真题_038_Count and Say
乘风破浪:LeetCode真题_038_Count and Say 一.前言 这一道题目,很类似于小学的问题,但是如果硬是要将输入和结果产生数值上的联系就会产生混乱了,因此我们要打破思维定势. ...
- COM动态添加删除成员,类似JavaScript中调用的对象
在JavaScript中调用对象时,可动态添加删除成员如: var obj=new Object; obj.member1='aaaaa'; obj.fun1=function() { alert(' ...
- 一段刚刚出炉的CSV文件转换为DataTable对象的代码
CSV是以文本形式保存的表格数据,具体是每列数据使用逗号分割,每行数据使用CRLF(\r\n)来结尾,如果数据值包含逗号或CRLF则使用双引号将数值包裹,如果数据值包含双引号则使用两个双引号做为转义. ...
- .join() ----- 是把列表中的元素用 "xx".join() 拼接成字符串
li = ["alex", "eric", "rain"] str1 = "_".join(li) # 是把列表中的元素 ...
- SVG绘制图形
一.SVG介绍 1.SVG指可伸缩矢量图片 2.SVG用来定义用于网络的基于矢量的图形 3.SVG使用XML格式定义图形 4.SVG图像在放大或改变尺寸的情况下其图形质量不会有损失 5.SVG是万维网 ...
- python中for、while循环、if嵌套的使用
1.for循环字符串就是一个有序的字符序列for i in range(5): print(i)定义一个死循环while True: pass2.break和continue肯定需要和 ...
- day3-课堂笔记
函数有2种: 1种是有返回值的,不改变对象本身 1种是没有返回值的,改变对象本身 eval函数就是实现list.dict.tuple与str之间的转化(只能把类似格式的字符串进行相应转换)str函 ...
- ConcurrentHashMap源码分析_JDK1.8版本
在jdk1.8中主要做了2方面的改进 改进一:取消segments字段,直接采用transient volatile HashEntry<K,V>[] table保存数据,采用table数 ...