2.10 游戏UI和战斗管理
2.10.1 创建显示得分的UI界面
游戏的UI界面会显示当前得分、最高分和生命值,首先我们来创建一个UI界面,所有的操作都在编辑器内完成,不需要编写代码。
步骤 01 在Hierarchy窗口中单击鼠标右键,选择【UI】→【Canvas】创建一个UI根节点,这个操作同时还会自动创建一个EventSystem,用于处理UI事件。
步骤 02 确定Canvas处于选择状态,单击鼠标右键并选择【UI】→【Text】,创建一个文本控件,并将其命名为Text_score,用来显示得分。按照同样的方式再创建一个Text控件,命名为Text_best,用来显示最高得分;创建Text_life显示主角生命值,如图2-39所示。
图2-39 UI界面
步骤 03 在Scene窗口中调整文本位置,在Inspector窗口中选择对齐方式,这里生命值文本在屏幕左边,选择左上对齐,分数选择顶端对齐。在Text组件中可以改变文本的大小、颜色等,如图2-40所示。
图2-40 设置文本
运行游戏,会在屏幕上看到设置的UI文本,但它们还都只是静态文本,没有具体功能,如图2-41所示。
图2-41 UI界面
2.10.2 创建显示游戏失败的UI界面
在游戏失败时,会出现一个游戏失败界面,并有一个按钮可以重新游戏,下面我们将创建这个UI界面。
步骤 01 新建一个UI Canvas,为了和之前创建的UI加以区分,这里命名为Canvas_gameover,
步骤 02 确定Canvas_gameover处于选择状态,创建一个文本Text_gameover,显示“游戏失败”几个字。本示例中“游戏失败”几个字的字号较大,需要调整Rect Transform中的Width和Height,否则可能会看不到文字。选择【UI】→【Button】创建一个按钮,命名为Button_restart,按钮控件下面默认还包括一个文本控件,最后效果如图2-42所示。
图2-42 游戏失败的UI界面
步骤 03 运行游戏,效果如图2-43所示。
图2-43 游戏失败UI界面
2.10.3 编写脚本
现在的UI界面没有任何功能,下面我们将使用脚本控制UI界面的显示。
步骤 01 创建GameManager.cs脚本:
using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; [AddComponentMenu("MyGame/GameManager")] public class GameManager : MonoBehaviour { public static GameManager Instance; // 静态实例 public Transform m_canvas_main; // 显示分数的UI界面 public Transform m_canvas_gameover; // 游戏失败UI界面 public Text m_text_score; // 得分UI文字 public Text m_text_best; // 最高分UI文字 public Text m_text_life; // 生命UI文字 protected int m_score=0; //得分 public static int m_hiscore=0; //最高分 protected Player m_player; //主角 public AudioClip m_musicClip; // 背景音乐 protected AudioSource m_Audio; // 声音源 void Start () { Instance = this; m_Audio=this.gameObject.AddComponent<AudioSource>(); // 使用代码添加音效组件 m_Audio.clip=m_musicClip; // 指定音效 m_Audio.loop=true; // 循环播放 m_Audio.Play(); // 播放音乐 // 获取主角 m_player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>(); // 获得UI控件 m_text_score = m_canvas_main.transform.Find("Text_score").GetComponent<Text>(); m_text_best = m_canvas_main.transform.Find("Text_best").GetComponent<Text>(); m_text_life = m_canvas_main.transform.Find("Text_life").GetComponent<Text>(); m_text_score.text=string.Format("分数 {0}", m_score); // 初始化UI分数 m_text_best.text=string.Format("最高分 {0}", m_hiscore); // 初始化UI最高分 m_text_life.text=string.Format("生命 {0}", m_player.m_life); // 初始化UI生命值 var restart_button = m_canvas_gameover.transform.Find("Button_restart"). GetComponent<Button>(); // 获取重新开始游戏按钮 restart_button.onClick.AddListener(delegate() // 按钮事件回调 { SceneManager.LoadScene(SceneManager.GetActiveScene().name); // 重新开始关卡 }); m_canvas_gameover.gameObject.SetActive(false); // 默认隐藏游戏失败UI } // 增加分数 public void AddScore( int point ) { m_score += point; // 更新高分纪录 if (m_hiscore < m_score) m_hiscore = m_score; m_text_score.text=string.Format("分数 {0}", m_score); m_text_best.text=string.Format("最高分 {0}", m_hiscore); } // 改变生命值UI显示 public void ChangeLife(int life) { m_text_life.text=string.Format("生命 {0}", life); // 更新UI if ( life<=0) { m_canvas_gameover.gameObject.SetActive(true); // 如果生命为0,显示游戏失败UI } } }
① Instance是一个静态实例,在Start函数中指向自身,这样可以方便在其他类的对象中引用GameManager实例,这种做法通常用于只有一个实例的类。
② 在Update函数中,循环播放背景音乐。
③ SceneManager.LoadScene用来读取关卡,在读取下一个关卡的时候,当前关卡的游戏体都会被销毁,如果希望可以保存一些游戏变量的值,可以将这类变量设置为static。
步骤 02 创建空游戏体作为游戏管理器,指定GameManager.cs作为其脚本组件,将场景中的两个Canvas UI和GameManager的m_canvas_main、m_canvas_gameover相关联。
步骤 03 在资源文件中找到music.mp3,把它与游戏管理器的m_musicClip属性相关联。
步骤 04 打开Enemy.cs,为其添加一个分数属性,每消灭一个敌人获得一定分数。
public int m_point = 10;
步骤 05 在Enemy.cs的OnTriggerEnter函数中添加GameManager.Instance.AddScore(m_point)语句,当敌人被消灭时,我们会获得一定分数:
if (m_life <= 0) { GameManager.Instance.AddScore(m_point); // 添加代码,更新UI上的分数 Instantiate(m_explosionFX, m_transform.position, Quaternion.identity); Destroy(this.gameObject); // 自我销毁 }
步骤 06 在Player.cs的OnTriggerEnter函数中添加如下语句,当主角受到伤害时,更新UI界面上的生命值显示。
if(other.tag.CompareTo("PlayerRocket")! =0) // 如果与主角子弹以外的碰撞体相撞 { m_life-=1; // 减少生命 GameManager.Instance.ChangeLife(m_life); // 添加代码,更新UI
运行游戏,最后的效果如图2-44所示。
图2-44 游戏UI
如果UI上的中文显示为乱码,使用Visual Studio打开GameManager.cs脚本,在菜单栏中选择【Save】→【Advanced Save Options】,然后将其保存为UTF-8格式即可,如图2-45所示。
图2-45 将脚本存储为UTF-8格式