Unity3D手机游戏开发4.7 敌人生成器_Unity3D手机游戏开发4.7 敌人生成器试读-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > 编程 > Unity3D手机游戏开发 > 4.7 敌人生成器

Unity3D手机游戏开发——4.7 敌人生成器

4.7 敌人生成器 塔防游戏的敌人通常是成批出现,一波接着一波,因为敌人的数量众多,所以需要一个生成器按预先设置的顺序生成不同的敌人。为了提高工作效率,我们将在Excel中设置每一波出现的敌人,然后将其导出为XML格式,敌人生成器将读取这个XML文件,按其设置生成敌人。 4.7.1 在Excel中设置敌人 实际上我们也可以在Unity的Inspector窗口设置组件的数值,但对于一个复杂的项目来说,这么做会使项目的维护变得困难,而游戏策划又偏爱使用Excel表格,所以可以先在Excel中设置数据,再将其导入Unity,这会是一个非常好的选择。 首先要创建一个用于定义XML格式的数据源,使用任意文本编辑器输入如下文本,并存为template.xml(文件可任意命名)。 <?xml version="1.0" encoding="utf-8"?> <ROOT> <!-- content --> <table wave="" enemyname="" level="" wait="" /> <table wave="" enemyname="" level="" wait="" /> </ROOT> 这是一个简单的XML文件,里面没有什么内容,但定义了我们需要的格式:wave表示第几波,enemyname是敌人的名字,这个名字需要在Unity中与敌人关联,level表示敌人的等级,wait表示生成这个敌人需要等待的时间。 注意我们定义了两列一样的table,这是必须的,只有这样在Excel中才能批量映射数据元素。 启动Excel,笔者使用的版本是Excel2007。 在Excel的工具栏单击右键,选择【自定义快速访问工具栏】,如图4-13所示 图4-13 自定义工具栏 在【常用】选项中选中【在功能区显示“开发工具”选项卡】,如图4-14所示 图4-14 显示“开发工具”选项卡 在开发工具选项卡中选择【源】,如图4-15所示。 图4-15 源 在XML源窗口的下方选择【XML映射】,如图4-16所示。 图4-16 XML映射 选择【添加】打开之前准备的template.xml,如图4-17所示。 图4-17 添加XML映射数据源 在Excel中添加文本,名称与XML数据源一致,如图4-18所示。 图4-18 添加文本 在XML源中依次选择table下面的wave、enemyname、level、wait并拖曳至相应的文本表格中,如图4-19所示。 图4-19 映射 映射完成后,可以输入相应的数据,最后的效果如图4-20所示。因为本示例是教程的原因,数据都比较简单,实际的塔防游戏通常会设置很多敌人。 图4-20 映射 在enemyname中设置的敌人名字需要与Unity设置的名字完全一样,为了避免输入错误,可以通过设置数据有效性的方法避免错误。在【数据】选项卡中选择【数据有效性】,如图4-21所示。 图4-21 数据有效性 在【允许】中选择【序列】,然后在【来源】中输入敌人的所有名字,每个名字都用逗号隔开,这样在单元格中只能使用预先定义的名字,如图4-22所示。 图4-22 设置来源 最后,将Excel另存为XML数据格式,本示例保存为enemy.xml,它的内容类似下面这个样子。 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ROOT> <table wave="1" enemyname="ground" level="1" wait="3"/> <table wave="1" enemyname="ground" level="1" wait="3"/> <table wave="2" enemyname="air" level="2" wait="4"/> <table wave="2" enemyname="air" level="2" wait="4"/> <table wave="3" enemyname="ground" level="2" wait="3"/> <table wave="3" enemyname="air" level="3" wait="3"/> <table wave="4" enemyname="ground" level="3" wait="5"/> <table wave="4" enemyname="ground" level="3" wait="4"/> <table wave="5" enemyname="air" level="4" wait="4"/> <table wave="5" enemyname="air" level="4" wait="4"/> <table wave="6" enemyname="ground" level="4" wait="4"/> <table wave="6" enemyname="ground" level="4" wait="5"/> <table wave="7" enemyname="air" level="5" wait="4"/> <table wave="7" enemyname="ground" level="5" wait="3"/> <table wave="8" enemyname="air" level="5" wait="4"/> <table wave="8" enemyname="ground" level="5" wait="4"/> <table wave="9" enemyname="air" level="6" wait="4"/> <table wave="9" enemyname="air" level="6" wait="5"/> <table wave="10" enemyname="ground" level="7" wait="4"/> <table wave="10" enemyname="air" level="7" wait="4"/> </ROOT> 4.7.2 创建敌人生成器 敌人成生器的主要功能分为两个部分,一部分是读入XML定义的敌人数据,并将其存入到一个ArrayList中,另一部分是从ArrayList中读出敌人的数据并将其创建出来。 创建EnemySpawner.cs,首先在EnemySpawner类中定义两个类EnemyTable和SpawnData,它们都是用来帮助定义敌人的相关数据。 using UnityEngine; using System.Collections; public class EnemySpawner : MonoBehaviour { // 定义敌人标识 [System.Serializable] public class EnemyTable { public string enemyName = ""; public Transform enemyPrefab; } // XML数据 public class SpawnData { // 波数 public int wave = 1; public string enemyname = ""; public int level = 1; public float wait = 1.0f; } } 为EnemySpawner定义属性,m_enemies是一个数组,保存敌人的Prefab,xmldata将指向我们需要读入的XML文件,而读入后的数据将保存在m_enemylist中。 // 敌人 public EnemyTable[] m_enemies; // 起始路点 public PathNode m_startNode; // 存储敌人出场顺序的XML public TextAsset xmldata; // 保存所有的从XML读取的数据 ArrayList m_enemylist; // 距离下一个敌人出场的时间 float m_timer = 0; // 出场敌人的序列号 int m_index = 0; // 当前波的敌人数量,只有销毁当前波内所有敌人,才能进入下一波 public int m_liveEnemy = 0; void Start () { // 读取XML ReadXML(); // 获取下一个敌人 SpawnData data = (SpawnData)m_enemylist[m_index]; m_timer = data.wait; } // 读取XML void ReadXML() { m_enemylist = new ArrayList(); XMLParser xmlparse = new XMLParser(); XMLNode node = xmlparse.Parse(xmldata.text); XMLNodeList list = node.GetNodeList("ROOT>0>table"); for (int i = 0; i < list.Count; i++) { string wave = node.GetValue("ROOT>0>table>" + i + ">@wave"); string enemyname = node.GetValue("ROOT>0>table>" + i + ">@enemyname"); string level = node.GetValue("ROOT>0>table>" + i + ">@level"); string wait = node.GetValue("ROOT>0>table>" + i + ">@wait"); SpawnData data = new SpawnData(); data.wave = int.Parse(wave); data.enemyname = enemyname; data.level = int.Parse(level); data.wait = float.Parse(wait); m_enemylist.Add(data); } } ReadXML函数将XML中的数据读出,并存入到m_enemylist中。 这里我们并没有使用.NET中提供的标准XML功能读取XML文件,而是使用了Unity社区中的开源脚本,而且是.js格式的,它已经预先放入当前工程,保存在PluginsXMLParser目录内。这个脚本的发布网址是http://dev.grumpyferret.com/unity/,在这里可以获得最新的版本。 不使用.NET提供的XML功能是因为它会使游戏的体积变得较大,Unity官方不建议使用它,在Unity安装目录EditorDataDocumentationDocumentationImagesmanual下有一个文件Mono.Xml.zip,这是Unity官方提供的一个精简版的XML解析脚本。 为EnemySpawner脚本中添加生成敌人的函数: void Update () { SpawnEnemy(); } // 每隔一定时间生成一个敌人 void SpawnEnemy() { // 如果已经生成所有敌人 if (m_index >= m_enemylist.Count) return; // 获取下一个敌人 SpawnData data = (SpawnData)m_enemylist[m_index]; // 如果下一个敌人是下一波需要等待前一波的敌人全部消亡 if (GameManager.Instance.m_wave < data.wave && m_liveEnemy > 0) return; // 等待 m_timer -= Time.deltaTime; if (m_timer > 0) return; if (GameManager.Instance.m_wave < data.wave) { // 增加一波 GameManager.Instance.SetWave(data.wave); } // 查找敌人 Transform enemyprefab = FindEnemy(data.enemyname); // 生成敌人 if (enemyprefab != null) { Transform trans=(Transform)Instantiate(enemyprefab,this.transform.position, Quaternion.identity); Enemy enemy = trans.GetComponent<Enemy>(); // 设置敌人的出发路点 enemy.m_currentNode = m_startNode; // 设置敌人的生成点 enemy.m_spawn = this; // 设置敌人初始旋转方向 enemy.transform.LookAt(m_startNode.transform); float ry = enemy.transform.eulerAngles.y; enemy.transform.eulerAngles = new Vector3(0,ry,0); // 根据data.level设置敌人等级,本示例中略 } // 下一个 m_index++; if (m_index >= m_enemylist.Count) return; // 获得下一个敌人的数据 SpawnData nextdata = (SpawnData)m_enemylist[m_index]; // 生成下一个敌人需要等待的时间 m_timer = data.wait; } // 在EnemyTable查找enemy的prefab Transform FindEnemy(string enemyname) { foreach (EnemyTable enemy in m_enemies) { if (enemy.enemyName.CompareTo(enemyname) == 0) { return enemy.enemyPrefab; } } return null; } void OnDrawGizmos() { Gizmos.DrawIcon(transform.position, "spawner.tif"); } 在FindEnemy函数中,我们到m_enemies中按名字查找敌人的prefab。 生成敌人的主要功能都在SpawnEnemy函数中,我们首先在m_enemylist中获得下一个敌人的数据,如果是下一波的敌人,我们需要等待当前波内的敌人全部消亡,否则要等待几秒再将其生成出来。 打开脚本Enemy.cs,添加一个EnemySpawner属性,它是生成敌人的生成器,在Start函数中增加敌人数量,在Disable数量中减少敌人数量,OnDisable函数将在敌人游戏体被销毁时自动触发,但在这个函数中要注意检查需要销毁的对象是否存在。 public EnemySpawner m_spawn; void Start () { m_spawn.m_liveEnemy++; } void OnDisable() { if (m_spawn) m_spawn.m_liveEnemy--; } 创建一个空游戏体作为敌人生成器放置到场景通道左侧,为其指定EnemySpawner.cs脚本。在m_enemies中关联敌人的prefab,注意每个敌人都有一个名字,它必须与XML中定义的一致。在m_startNode中设置起始路点,在m_xmldata中关联XML文件,如图4-23所示。 图4-23 设置敌人prefab和起始路点 运行游戏,敌人会按照Excel表格中的设计逐个生成。

展开全文


推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

《Unity3D手机游戏开发》其他试读目录

• 3.1 策划
• 3.2 游戏场景
• 3.3 主角
• 3.4 敌人
• 3.5 UI界面
• 3.6 交互
• 3.7 出生点
• 小结
• 4.1 策划
• 4.2 游戏场景
• 4.3 摄像机
• 4.4 游戏管理器
• 4.5 路点
• 4.6 敌人
• 4.7 敌人生成器 [当前]
• 4.8 防守单位
• 4.9 生命条
• 4.10 自定义按钮
• 小结
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  •