这篇文章进行对游戏ui逻辑的总结。
在上一篇机器人的控制脚本创建完成后,可以给机器人添加一个血条的效果,在机器人的游戏物体下创建一个画布,并添加一个slider,只保留其中的Fill Area,把其他的删掉,如图。
将Fill中的image修改为红色,然后给slider添加一个脚本,主要功能是让slider的value的值与血量占比相当
using UnityEngine;
using UnityEngine.UI;
public class follower : MonoBehaviour
{
[SerializeField]
private float m_offsety;
public Transform m_robot;
private float m_robotinithp;//机器人初始的hp
private void Start()
{
m_robotinithp = m_robot.gameObject.GetComponent<RobotController>().M_hp;
}
private void Update()
{
//确定血条位置
gameObject.transform.position =
new Vector3(m_robot.position.x, m_robot.position.y + m_offsety, m_robot.position.z);
//根据实际情况扣血
gameObject.GetComponent<Slider>().value=
((m_robot.gameObject.GetComponent<RobotController>().M_hp / m_robotinithp));
}
}
然后对该画布的Canvas组件中的Render Mode进行如图设置:
创建一个新的相机,将它拖入Canvas组件中的Render Camera,在第三篇文章中的gamemanager类中拥有该相机的引用,名为m_secondcamera,并将其与主相机同步。这样子就相当与每个机器人都拥有一个与血量相当slider,并且它时刻面向玩家的视角,形成血条的效果。
血条设置好以后,创建多个scene存储关卡(关卡数+1个),把每个scene的地图自己div一下,将多个机器人放置其中并设置好巡逻点。然后开始进行ui脚本的创建。
首先是第一个scene也就是主菜单,创建一个名为UI的空物体,在它下面创建三个画布,再为每个画布添加各种功能对象,如图:
创建脚本进行管理,挂在ui上
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class menuui : MonoBehaviour {
public GameObject m_setcanvas;
public GameObject m_Authorcanvas;
public GameObject m_volumeslider;
private void Start()
{
m_setcanvas.SetActive(false);
m_Authorcanvas.SetActive(false);
m_volumeslider.GetComponent<Slider>().value = datamanager.m_volume;
}
private void Update()
{
//音量调节
datamanager.m_volume = m_volumeslider.GetComponent<Slider>().value;
}
//下面的方法全都挂在不同的Button上
public void OnStart()
{
SceneManager.LoadScene(1);
}
public void OnExit()
{
Application.Quit();
}
public void OnSetOpen()
{
m_setcanvas.SetActive(true);
}
public void OnSetClose()
{
m_setcanvas.SetActive(false);
}
public void OnAuthorOpen()
{
m_Authorcanvas.SetActive(true);
}
public void OnAuthorClose()
{
m_Authorcanvas.SetActive(false);
}
}
还创建一个空物体负责播放bgm,也挂一个脚本控制音量,在其他scene中也有这个物体
using UnityEngine;
public class bgm : MonoBehaviour {
void Update ()
{
gameObject.GetComponent<AudioSource>().volume = datamanager.m_volume;
}
}
然后是开始游戏后的ui,之前在创建武器系统时做了一部分,现在补充完整
创建脚本对其进行管理
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
//游戏界面状态
enum PlayUiState
{
BATTLE,
END,
SET
}
public class playui : MonoBehaviour
{
private PlayUiState m_state;//当前界面状态
private gun m_gun;
private playerhp m_playerhp;
private player m_player;
private gamemanager m_manager;
public GameObject m_hptext;//获取画布中的一个text
public GameObject m_bulletText;//子弹数文本
public GameObject m_snipertexture;//瞄准时加载的图片
public GameObject m_aimtexture;
public GameObject m_time;
public GameObject m_endcanvas;
public GameObject m_endtext;
public GameObject m_playerstatetext;
public GameObject m_hurtimage;
public GameObject m_warningtext;
public GameObject m_scoretext;
public GameObject m_setcanvas;
public GameObject m_bgm;
public GameObject m_volumeslider;
public GameObject m_mouseslider;
private Color m_flashcolor; //记录受伤图片的色彩值
public float m_flashspeed = 2;
private float m_musictime = 0;//记录音乐播放位置
private bool m_dead = false;
private float m_finaltime = 0;
void Start()
{
m_state = PlayUiState.BATTLE;
m_player = FindObjectOfType<player>();
m_playerhp = FindObjectOfType<playerhp>();
m_manager = FindObjectOfType<gamemanager>();
m_playerhp.diedelegate += OnDie;//添加委托事件
m_volumeslider.GetComponent<Slider>().value = datamanager.m_volume;
m_mouseslider.GetComponent<Slider>().value = datamanager.m_mosen;
//记录当前设置好的受伤图片的颜色值
m_flashcolor = m_hurtimage.GetComponent<Image>().color;
//将受伤图片先设置为透明
m_hurtimage.GetComponent<Image>().color = Color.clear;
m_setcanvas.SetActive(false);
m_endcanvas.SetActive(false);
m_hurtimage.SetActive(true);
m_playerstatetext.SetActive(false);
m_warningtext.SetActive(false);
//若是第一关 为玩家显示提示
if (datamanager.M_gamelevel == 1)
{
StartCoroutine(FirstWarning());
}
Cursor.visible = false;//隐藏鼠标
}
void Update()
{
#region 战斗界面
if (m_state == PlayUiState.BATTLE)
{
m_gun = FindObjectOfType<gun>();
FreshHpText();
FreshBulletText();
ShowAimImage();
ShowTheTime();
//当玩家处于休息状态 显示提示
if (playerstatemanager.m_state == PlayerState.RELAXE)
{
m_playerstatetext.GetComponent<Text>().text = "Relaxing...";
m_playerstatetext.SetActive(true);
}
else m_playerstatetext.SetActive(false);
//将受伤图片的颜色渐变为透明
m_hurtimage.GetComponent<Image>().color =
Color.Lerp
(
m_hurtimage.GetComponent<Image>().color,
Color.clear,
m_flashspeed * Time.deltaTime
);
//设置鼠标灵敏度
datamanager.m_mosen = m_mouseslider.GetComponent<Slider>().value;
m_player.m_mouserate = datamanager.m_mosen * 5;
//状态转换
if (datamanager.M_gamelevel == datamanager.m_maxlevel || m_dead) m_state = PlayUiState.END;
if (Input.GetKeyUp(KeyCode.Y)) m_state = PlayUiState.SET;
}
#endregion
#region 结束界面
if (m_state == PlayUiState.END)
{
Cursor.visible = true;//显示鼠标
m_gun.enabled = false;
m_player.enabled = false;
m_endcanvas.SetActive(true);
string score = "";
if (datamanager.M_gamelevel == datamanager.m_maxlevel)//胜利
{
m_endtext.GetComponent<Text>().text = "Victory!";
//记录游戏时间
if (m_finaltime == 0)
m_finaltime = (int)datamanager.M_playtime;
score =
"杀敌数:" + datamanager.M_gamescore +
"\n当前关卡:" + "final" +
"\n用时:" + m_finaltime + "s";
}
else if (m_dead)//死亡
{
m_endtext.GetComponent<Text>().text = "Game Over";
m_playerhp.diedelegate -= OnDie;//释放委托事件
//记录游戏时间
if (m_finaltime == 0)
m_finaltime = (int)datamanager.M_playtime;
score =
"杀敌数:" + datamanager.M_gamescore +
"\n当前关卡:" + datamanager.M_gamelevel +
"\n用时:" + m_finaltime + "s";
}
m_scoretext.GetComponent<Text>().text = score.ToString();
}
#endregion
#region 设置界面
if (m_state == PlayUiState.SET)
{
m_gun.enabled = false;
//音乐暂停
m_musictime = m_bgm.GetComponent<AudioSource>().time;
m_bgm.GetComponent<AudioSource>().Pause();
Cursor.visible = true;//显示鼠标
Time.timeScale = 0;//时间暂停
m_setcanvas.SetActive(true);
//声音设置
datamanager.m_volume = m_volumeslider.GetComponent<Slider>().value;
}
#endregion
}
void FreshHpText()
{
m_hptext.GetComponent<Text>().text = "HP:" + m_playerhp.M_hp.ToString();
}
void FreshBulletText()
{
m_bulletText.GetComponent<Text>().text = m_gun.Curbulletnum.ToString() + "/"
+ m_gun.Storebulletnum.ToString();
}
void ShowAimImage()
{
if (sniperscope.m_isaiming)
{
m_snipertexture.SetActive(true);
m_aimtexture.SetActive(false);
}
else
{
m_snipertexture.SetActive(false);
m_aimtexture.SetActive(true);
}
}
void OnDie()
{
m_dead = true;
}
void ShowTheTime()
{
int time = (int)m_manager.M_WaitTime;
if (time == 0)
m_time.GetComponent<Text>().text = "The door is open!";
else
m_time.GetComponent<Text>().text = time.ToString();
}
public void HurtEffect()
{
m_hurtimage.GetComponent<Image>().color = m_flashcolor;
}
//下面两个方法是绑定在Button上的
public void OnSetClose()
{
Cursor.visible = false;
// 继续播放音乐
m_bgm.GetComponent<AudioSource>().Play();
m_bgm.GetComponent<AudioSource>().time = m_musictime;
Time.timeScale = 1;//时间恢复正常
m_setcanvas.SetActive(false);
m_gun.enabled = true;
m_state = PlayUiState.BATTLE;//转换状态
}
public void OnExit()
{
Application.Quit();
}
//显示警告,延迟消失
IEnumerator FirstWarning()
{
m_warningtext.GetComponent<Text>().text = "Live and get out";
m_warningtext.SetActive(true);
yield return new WaitForSeconds(5f);
m_warningtext.GetComponent<Text>().text = " ";
m_warningtext.SetActive(false);
}
}
因为每个关卡的ui都相同,可以设置为全局ui,在gamemanager中将名为ui的物体DontDestroyOnLoad了就行。
效果如下(结束界面):
ui写完后,这个小游戏就基本完成的差不多了,后面可能还会有些改进和补充,现在已经可以愉快的玩耍了,谢谢观看:)