Unity實(shí)戰(zhàn)之FlyPin(見(jiàn)縫插針)小游戲的實(shí)現(xiàn)
一、簡(jiǎn)單介紹
Unity 游戲?qū)嵗_(kāi)發(fā)集合,使用簡(jiǎn)單易懂的方式,講解常見(jiàn)游戲的開(kāi)發(fā)實(shí)現(xiàn)過(guò)程,方便后期類(lèi)似游戲開(kāi)發(fā)的借鑒和復(fù)用。
本節(jié)介紹,F(xiàn)lyPin (見(jiàn)縫插針) 休閑小游戲快速實(shí)現(xiàn)的方法,希望能幫到你,若有不對(duì),請(qǐng)留言。
二、FlyPin (見(jiàn)縫插針)游戲內(nèi)容與操作
1、游戲開(kāi)始,針 Pin 自動(dòng)準(zhǔn)備好,
2、鼠標(biāo)點(diǎn)擊左鍵發(fā)射 Pin,飛向目標(biāo),同時(shí)自動(dòng)準(zhǔn)備下一根針 Pin,并增加分?jǐn)?shù)
3、針 Pin 插入目標(biāo)后,會(huì)隨之一起轉(zhuǎn)動(dòng)
4、當(dāng)兩個(gè)針 Pin 發(fā)生碰撞,則游戲結(jié)束
5、游戲結(jié)束動(dòng)畫(huà)完成后,自動(dòng)重新開(kāi)始游戲
三、游戲代碼框架

四、知識(shí)點(diǎn)
1、MonoBehaviour 生命周期函數(shù):Awake,Start,Update,OnGUI
2、Input 按鍵的監(jiān)控
3、GameObject.Instantiate 物體的生成,GameObject.Destroy 物體的銷(xiāo)毀
4、Camera.orthographicSize 正交相機(jī)視口大小修改,Camera.backgroundColor 相機(jī) SolidColor 背景色的修改
5、Rigidbody2D 取消重力效果,添加 Collider ,進(jìn)行 Trigger 碰撞檢測(cè)
6、GUIStyle GUI樣式,GUI.Label 添加文字的功能使用
7、Vector3.Lerp 位移向量插值使用,Vector3.Distance 位置距離函數(shù)的使用
8、Mathf.Lerp ,Color.Lerp 數(shù)值和顏色插值計(jì)算的使用
9、Transform.Rotate 旋轉(zhuǎn)使用
10、IEnumerator 協(xié)程 , StartCoroutine 開(kāi)始協(xié)程 和 StopAllCoroutines 停止所有協(xié)程的使用
11、SimpleMessageCenter 簡(jiǎn)單的消息中心使用
12、Action<int> OnChangeValue 屬性變化中委托的使用
13、Resources.Load<GameObject>() 代碼加載預(yù)制體的使用
14、OnTriggerEnter2D 2D 碰撞檢測(cè)的使用
15、 SceneManager.LoadScene 加載,和 SceneManager.GetActiveScene() 當(dāng)前場(chǎng)景的獲取
16、等等
五、游戲效果預(yù)覽

六、實(shí)現(xiàn)步驟
這是一個(gè) 2D 游戲,主要用到 SpriteRenderer 、2D Collider,2D Rigidbody,以及 TextMesh 等資源組件,所有資源都是Unity自帶,沒(méi)有導(dǎo)入其他外部貼圖模型資源。
1、打開(kāi) Unity,創(chuàng)建工程

2、構(gòu)建場(chǎng)景,添加 Pin 初始生成,準(zhǔn)備和飛向的地方,以及旋轉(zhuǎn)的目標(biāo)圓,和顯示分?jǐn)?shù)的 3DText

3、ScoreText,創(chuàng)建是 3D Object - 3D Text,其中 根據(jù) TextMesh的字體大小,根據(jù) Character Size 和 Font Size 共同控制


4、如果 TextMesh 看起來(lái)很模糊,可以改小 Character Size ,放大 Font Size ,如圖


5、TargetCircle 是 SpriteRenderer ,根據(jù)需要設(shè)置顏色,Sprite 是 Unity 自帶的 Knob
說(shuō)明,同時(shí) TargetCircle 也是 Pin 飛向的目標(biāo)體


6、PinSpawnPos 、PinReadyPos 是 針 Pin 生成的初始位置,和 準(zhǔn)備好位置,PinSpawnPos 、PinReadyPos 下的 Cube 是便于觀察位置設(shè)定的,確定好位置后,可以刪掉或者隱藏 Cube


7、注意 ScoreText 、TargetCircle、PinSpawnPos、PinReadyPos,Position.z 都是 0,為了保證實(shí)在同一個(gè)平面上,滿(mǎn)足2D 游戲要求

8、Main Camera,設(shè)置如圖,ClearFlags 為 Solid Color ,Background 顏色根據(jù)需要設(shè)定,Projection 為 Orthographic 正交(2D游戲設(shè)置相機(jī)),Size 為 5 ,你可以根據(jù)自己需要設(shè)置

9、最后,效果如圖

10、Pin 預(yù)制體,包含PinHead 和 PinBody

11、Pin 的 PinHead ,SpriteRenderer 的 Sprite 自帶的 Knob, 顏色根據(jù)自己需要設(shè)定,添加 CircleCollider2D 碰撞體,并且勾選 IsTrigger(避免發(fā)生碰撞,產(chǎn)生碰撞效果,不勾選則會(huì)有碰撞的物理效果),CircleCollider2D的大小可以根據(jù)實(shí)際情況調(diào)整(一般Unity會(huì)自動(dòng)根據(jù)Renderer 大小設(shè)置默認(rèn)大?。?;添加 Rigidbody2D (發(fā)生碰撞的必需條件之一),并且BodyType設(shè)置為 Kinematic 可以不受重力下墜(或者 BodyType 為 Dynamic ,把 Gravity Scale 設(shè)置 為 0 ,也可以不受重力影響)

12、Pin 中的 PinBody,SpriteRenderer 中 Sprite 自帶的 Background ,顏色自選,Order in Layer 默認(rèn)是 0 ,設(shè)置為 -1,是為針插入 TargetCircle 效果,Scale 設(shè)置為 (1,15,1),是為了細(xì)長(zhǎng)如針的效果


13、至于 Pin ,放置在 Resources 文件夾下的Prefabs 文件夾,是為了使用 Unity 中 Resources.Load 代碼加載預(yù)制體,不需要手動(dòng)掛載預(yù)制體,而 Resources.Load 加載就要求把預(yù)制體放在 Resources 文件夾下

14、PinHead 類(lèi) 監(jiān)聽(tīng)兩個(gè)針是否插在靠近位置相撞,相撞則發(fā)送游戲結(jié)束消息

15、PinHead中的 OnTriggerEnter2D(Collider2D collision) 見(jiàn)監(jiān)聽(tīng)碰撞進(jìn)入,碰撞則發(fā)送游戲借宿消息
/// <summary>
/// 監(jiān)聽(tīng)兩個(gè)針是否插在靠近位置相撞
/// 相撞則發(fā)送游戲結(jié)束消息
/// </summary>
/// <param name="collision"></param>
private void OnTriggerEnter2D(Collider2D collision)
{
// 兩個(gè) PinHead 是否碰撞
if (collision.name.Equals(ConstStr.PIN_HEAD_NAME))
{
// 相撞則發(fā)送游戲結(jié)束消息
SimpleMessageCenter.Instance.SendMsg(MsgType.GameOver);
}
}16、Pin 類(lèi),管理 針 Pin 的狀態(tài)和運(yùn)動(dòng)

17、Pin 類(lèi),Init 初始化函數(shù),得到相關(guān)位置和 PinHead 腳本的掛載到 Pin 的 PinHead 物體上
參數(shù)說(shuō)明:
// Pin 準(zhǔn)備好的位置
private Vector3 m_PinReadyPos;
// Pin 飛行的目標(biāo)位置
private Vector3 m_PinFlyTargetPos;
// Pin 插入目標(biāo)位置的距離間隔
private float m_PinFlyTargetPosDistance;
// Pin 的移動(dòng)速度
private float m_PinMoveSpeed;
// Pin 飛到目標(biāo)位置的 Transfrorm
private Transform m_PinTargetParentTrans;
// PinHead
private PinHead m_PinHead; /// <summary>
/// 初始化函數(shù),得到相關(guān)位置和 PinHead
/// </summary>
/// <param name="pinsManager"></param>
/// <param name="pinReadyPos"></param>
/// <param name="flyTargetPos"></param>
/// <param name="flyTargetPosDistance"></param>
/// <param name="pinMoveSpeed"></param>
/// <param name="pinTargetParentTrans"></param>
public void Init(PinsManager pinsManager, Vector3 pinReadyPos, Vector3 flyTargetPos,
float flyTargetPosDistance, float pinMoveSpeed, Transform pinTargetParentTrans) {
m_PinsManager = pinsManager;
m_PinReadyPos = pinReadyPos;
m_PinFlyTargetPos = flyTargetPos;
m_PinFlyTargetPosDistance = flyTargetPosDistance;
m_PinMoveSpeed = pinMoveSpeed;
m_PinTargetParentTrans = pinTargetParentTrans;
// PinHead 子物體添加PinHead腳本
m_PinHead = transform.Find(ConstStr.PIN_HEAD_NAME).gameObject.AddComponent<PinHead>() ;
// 設(shè)置狀態(tài)為準(zhǔn)備狀態(tài)
m_CurPinState = PinState.Readying;
}18、Pin 類(lèi),UpdatePinState(),Pin 的狀態(tài)監(jiān)聽(tīng)
/// <summary>
/// 狀態(tài)監(jiān)聽(tīng)
/// </summary>
void UpdatePinState() {
switch (CurPinState)
{
case PinState.Idle:
break;
case PinState.Readying:
Readying();
break;
case PinState.ReadyOK:
m_PinsManager.CurPin = this;
break;
case PinState.Fly:
Fly();
m_PinsManager.CurPin = null;
break;
default:
break;
}
}19、Pin 類(lèi),Readying() 正在準(zhǔn)備的狀態(tài)函數(shù),F(xiàn)ly() 飛行目標(biāo)位置狀態(tài),包含 Pin真正的運(yùn)動(dòng)(Vector3.Lerp),和滿(mǎn)足條件(Vector3.Distance)對(duì)應(yīng)的狀態(tài)切換(注意:把 Pin 實(shí)體至于 TargetCircle 即可以 使 Pin 隨 TargetCircle 一起轉(zhuǎn)動(dòng) (this.transform.SetParent(m_PinTargetParentTrans);))
/// <summary>
/// 正在準(zhǔn)備的狀態(tài)函數(shù)
/// </summary>
void Readying() {
// 移動(dòng)到準(zhǔn)備位置
transform.position = Vector3.Lerp(transform.position, m_PinReadyPos, Time.deltaTime * m_PinMoveSpeed);
// 判斷是否到達(dá)準(zhǔn)備位置
if (Vector3.Distance(transform.position, m_PinReadyPos)<=0.1f)
{
transform.position = m_PinReadyPos;
// 到達(dá)后切換狀態(tài)
CurPinState = PinState.ReadyOK;
}
}
/// <summary>
/// 飛行目標(biāo)位置狀態(tài)
/// </summary>
void Fly()
{
// 移動(dòng)到目標(biāo)位置
transform.position = Vector3.Lerp(transform.position, m_PinFlyTargetPos, Time.deltaTime * m_PinMoveSpeed);
if (Vector3.Distance(transform.position, m_PinFlyTargetPos) <= m_PinFlyTargetPosDistance)
{
// 到達(dá)后切換狀態(tài),并且置于 飛到的目標(biāo)下,使之隨目標(biāo)一起轉(zhuǎn)動(dòng)
CurPinState = PinState.Idle;
this.transform.SetParent(m_PinTargetParentTrans);
}
}20、PinsManager Pins 管理類(lèi),主要管理 Pin 的生成和 發(fā)射 Fly

21、PinsManager Pins 管理類(lèi),構(gòu)造函數(shù) PinsManager(),Resources.Load 獲取預(yù)制體 Pin 預(yù)制體,和參數(shù)賦值
參數(shù)說(shuō)明:
// Pin 預(yù)制體
private GameObject m_PinPrefab;
// Pin 生成位置
private Vector3 m_PinSpawnPos;
// Pin 準(zhǔn)備位置
private Vector3 m_PinReadyPos;
// Pin 飛向目標(biāo)位置
private Vector3 m_PinFlyTargetPos;
// Pin 飛向目標(biāo)插入間距
private float m_PinFlyTargetPosDistance;
// Pin 移動(dòng)速度
private float m_PinMoveSpeed;
// Pin 飛向目標(biāo)實(shí)體
private Transform m_PinTargetParentTrans; /// <summary>
/// 構(gòu)造函數(shù)
/// </summary>
/// <param name="pinSpawnPos"></param>
/// <param name="pinReadyPos"></param>
/// <param name="flyTargetPos"></param>
/// <param name="flyTargetPosDistance"></param>
/// <param name="pinMoveSpeed"></param>
/// <param name="pinTargetParentTrans"></param>
public PinsManager(Vector3 pinSpawnPos, Vector3 pinReadyPos,Vector3 flyTargetPos,
float flyTargetPosDistance, float pinMoveSpeed,Transform pinTargetParentTrans) {
// 獲取預(yù)制體
m_PinPrefab = Resources.Load<GameObject>(ConstStr.RESOURCES_PREFABS_PIN_PATH);
// 參數(shù)賦值
m_PinSpawnPos = pinSpawnPos;
m_PinReadyPos = pinReadyPos;
m_PinFlyTargetPos = flyTargetPos;
m_PinFlyTargetPosDistance = flyTargetPosDistance;
m_PinMoveSpeed = pinMoveSpeed;
m_PinTargetParentTrans = pinTargetParentTrans;
}22、PinsManager Pins 管理類(lèi),SpawnPin() 根據(jù)條件 生成準(zhǔn)備的 Pin
/// <summary>
/// 生成準(zhǔn)備的 Pin
/// </summary>
public void SpawnPin() {
// 生成準(zhǔn)備的 Pin
if (m_PinPrefab!=null && m_ReadyPin == null)
{
GameObject pinGo = GameObject.Instantiate(m_PinPrefab);
// 設(shè)置生成位置
pinGo.transform.position = m_PinSpawnPos;
// 添加 Pin 腳本
m_ReadyPin = pinGo.AddComponent<Pin>();
// Pin 腳本 初始化
m_ReadyPin.Init(this,m_PinReadyPos,m_PinFlyTargetPos,
m_PinFlyTargetPosDistance,m_PinMoveSpeed,m_PinTargetParentTrans);
// 添加到集合中
m_PinsList.Add(pinGo);
}
}23、PinsManager Pins 管理類(lèi),F(xiàn)lyPin() 根據(jù)條件 讓當(dāng)前 Pin 飛向目標(biāo)位置,返回是否有可飛行的 Pin,有則 true,DestroyAllPins() 銷(xiāo)毀清空 Pins 集合
/// <summary>
/// 讓當(dāng)前 Pin 飛向目標(biāo)位置
/// 返回是否有可飛行的 Pin
/// </summary>
/// <returns>true : 有可飛行 Pin </returns>
public bool FlyPin() {
if (CurPin!=null)
{
m_ReadyPin = null;
if (CurPin.CurPinState==PinState.ReadyOK)
{
CurPin.CurPinState = PinState.Fly;
}
return true;
}
return false;
}
/// <summary>
/// 銷(xiāo)毀清空 Pins 集合
/// </summary>
public void DestroyAllPins() {
for (int i=m_PinsList.Count-1; i >= 0 ; i--)
{
GameObject.Destroy(m_PinsList[i]);
}
m_PinsList.Clear();
}24、TargetCircleManager Pin 飛向目標(biāo)圓管理類(lèi)

25、TargetCircleManager Pin 飛向目標(biāo)圓管理,TargetCircleManager()構(gòu)造函數(shù) 獲取設(shè)置 旋轉(zhuǎn)的實(shí)體和旋轉(zhuǎn)速度
參數(shù)說(shuō)明:
// 實(shí)體Transform
Transform m_TargetCircleTrans;
// 轉(zhuǎn)動(dòng)速度
float m_Speed;
// 是否開(kāi)始轉(zhuǎn)動(dòng)
bool m_IsRotated = false; /// <summary>
/// 構(gòu)造函數(shù)
/// </summary>
/// <param name="target">目標(biāo)實(shí)體</param>
/// <param name="rotSpeed">旋轉(zhuǎn)速度</param>
public TargetCircleManager(Transform target, float rotSpeed) {
m_TargetCircleTrans = target;
m_Speed = rotSpeed;
m_IsRotated = false;
}26、TargetCircleManager Pin 飛向目標(biāo)圓管理, void UpdateRotateSelf() 更新自身旋轉(zhuǎn),StartRotateSelf() 開(kāi)始旋轉(zhuǎn),StopRotateSelf() 停止旋轉(zhuǎn)
/// <summary>
/// 更新自身旋轉(zhuǎn)
/// </summary>
public void UpdateRotateSelf() {
if (m_TargetCircleTrans != null && m_IsRotated==true)
{
m_TargetCircleTrans.Rotate(Vector3.forward,Time.deltaTime * m_Speed * -1); // -1 是讓其反向旋轉(zhuǎn)
}
}
/// <summary>
/// 開(kāi)始旋轉(zhuǎn)
/// </summary>
public void StartRotateSelf()
{
m_IsRotated = true;
}
/// <summary>
/// 停止旋轉(zhuǎn)
/// </summary>
public void StopRotateSelf() {
m_IsRotated = false;
}27、ScoreManager 分?jǐn)?shù)管理類(lèi),管理分?jǐn)?shù),和分?jǐn)?shù)變化更新的委托事件

public int Score { get { return m_Scroe; }
set {
// 判斷分?jǐn)?shù)是否更新,更新則觸發(fā)更新事件
if (m_Scroe!=value)
{
m_Scroe = value;
if (OnChangeValue!=null)
{
OnChangeValue.Invoke(value);
}
}
}
}
// 分?jǐn)?shù)變化委托
public Action<int> OnChangeValue;28、SimpleMessageCenter 簡(jiǎn)單消息中心,管理消息的注冊(cè),觸發(fā),和清空,并且設(shè)置靜態(tài)單例(static SimpleMessageCenter Instance),方便被訪問(wèn)使用

29、SimpleMessageCenter 簡(jiǎn)單消息中心, RegisterMsg()注冊(cè)消息,SendMsg()發(fā)送消息,ClearAllMsg() 清空消息
/// <summary>
/// 注冊(cè)消息
/// </summary>
/// <param name="msgType"></param>
/// <param name="action"></param>
public void RegisterMsg(MsgType msgType, Action action) {
if (m_MsgDict.ContainsKey(msgType) == true)
{
m_MsgDict[msgType] += action;
}
else {
m_MsgDict.Add(msgType,action);
}
}
/// <summary>
/// 發(fā)送消息
/// </summary>
/// <param name="msgType"></param>
public void SendMsg(MsgType msgType)
{
if (m_MsgDict.ContainsKey(msgType) == true)
{
m_MsgDict[msgType].Invoke();
}
}
/// <summary>
/// 清空消息
/// </summary>
public void ClearAllMsg() {
m_MsgDict.Clear();
}30、ConstStr 統(tǒng)一管理一些不可變的常量字符串

/// <summary>
/// 不可變字符串
/// </summary>
public class ConstStr
{
// Pin 飛行目標(biāo)圓 名字路徑
public const string WORLD_TARGETCIRCLE_NAME_PATH = "World/TargetCircle";
// Pin Resources 預(yù)制體路徑
public const string RESOURCES_PREFABS_PIN_PATH = "Prefabs/Pin";
// Pin Head 名字
public const string PIN_HEAD_NAME = "PinHead";
}31、Enum 統(tǒng)一管理枚舉類(lèi)型

/// <summary>
/// Pin 狀態(tài)
/// </summary>
public enum PinState
{
Idle = 0, // 閑置狀態(tài)
Readying, // 正在準(zhǔn)備狀態(tài)
ReadyOK, // 裝備好狀態(tài)
Fly, // 飛向目標(biāo)狀態(tài)
}
/// <summary>
/// 消息類(lèi)型
/// </summary>
public enum MsgType
{
GameOver = 0, // 游戲結(jié)束
}32、GameManager 游戲管理類(lèi) ,直接掛載到場(chǎng)景中,獲取一些場(chǎng)景游戲?qū)嶓w,并管理一些游戲邏輯的初始化等

33、GameManager 游戲管理類(lèi) ,Awake() 和Start() Unity自帶函數(shù),初始化變量和類(lèi),以及啟動(dòng)游戲,TargetCircle 開(kāi)始旋轉(zhuǎn),Pin 開(kāi)始準(zhǔn)備,在簡(jiǎn)單消息中心注冊(cè)監(jiān)聽(tīng)游戲結(jié)束事件,設(shè)置 分?jǐn)?shù)變化更新到 TextMesh 上,等等
private void Awake()
{
// 初始化參數(shù)值
m_MainCamera = Camera.main;
m_IsGameOver = false;
Transform targetCircleTrans = GameObject.Find(ConstStr.WORLD_TARGETCIRCLE_NAME_PATH).transform;
m_TargetCircleManager = new TargetCircleManager(targetCircleTrans, RotateSpeed);
m_PinsManager = new PinsManager(m_PinSpawnPos.position,m_PinReadyPos.position, targetCircleTrans.position,
m_PinFlyTargetPosDistance,m_PinMoveSpeed,targetCircleTrans);
m_ScoreManager = new ScoreManager();
}
private void Start()
{
// 開(kāi)始TargetCircle旋轉(zhuǎn)
m_TargetCircleManager.StartRotateSelf();
// 生成第一個(gè) Pin
m_PinsManager.SpawnPin();
// 注冊(cè)監(jiān)聽(tīng)游戲結(jié)束消息
SimpleMessageCenter.Instance.RegisterMsg(MsgType.GameOver,ToGameOver);
// 初始化分?jǐn)?shù) 0
m_ScoreManager.Score = 0;
// 分?jǐn)?shù)更新事件,更新 UI
m_ScoreManager.OnChangeValue += (score)=> { ScoreText.text = score.ToString(); };
}34、GameManager 游戲管理類(lèi) ,Update() Unity自帶函數(shù),游戲未結(jié)束,TargetCircle 每幀轉(zhuǎn)動(dòng),并監(jiān)聽(tīng)鼠標(biāo)左鍵按下,F(xiàn)ly Pin 和生成下一個(gè) Pin 準(zhǔn)備
private void Update()
{
// 游戲結(jié)束
if (m_IsGameOver == true)
{
return;
}
// TargetCircle 更新旋轉(zhuǎn)
m_TargetCircleManager.UpdateRotateSelf();
// 監(jiān)聽(tīng)鼠標(biāo)左鍵按下
if (Input.GetMouseButtonDown(0))
{
// Pin 飛向目標(biāo),則增加分?jǐn)?shù),并且生成下一個(gè) Pin
bool isFly = m_PinsManager.FlyPin();
if (isFly==true)
{
m_ScoreManager.Score++;
m_PinsManager.SpawnPin(); // 生成下一個(gè)
}
}
}35、GameManager 游戲管理類(lèi) ,OnDestroy() 在游戲重新加載銷(xiāo)毀時(shí),進(jìn)行一些數(shù)據(jù)清理置空,并停止可能的所有協(xié)程(不阻礙主程運(yùn)行的小程序),OnGUI() 做一些游戲操作說(shuō)明
private void OnDestroy()
{
// 銷(xiāo)毀所有 Pin
m_PinsManager.DestroyAllPins();
// 清空消息中心
SimpleMessageCenter.Instance.ClearAllMsg();
// 置空分?jǐn)?shù)更新事件
m_ScoreManager.OnChangeValue = null;
// 置空相關(guān)參數(shù)
m_PinsManager = null;
m_TargetCircleManager = null;
m_ScoreManager = null;
// 停止所有協(xié)程
StopAllCoroutines();
}
// Unity 周期函數(shù) 每幀調(diào)用
private void OnGUI()
{
// 游戲操作說(shuō)明
GUIStyle fontStyle = new GUIStyle();
fontStyle.normal.background = null; //設(shè)置背景填充
fontStyle.normal.textColor = new Color(1, 0, 0); //設(shè)置字體顏色
fontStyle.fontSize = 40; //字體大小
GUI.Label(new Rect(10, 10, 200, 200),
"操作說(shuō)明:\n1、點(diǎn)擊鼠標(biāo)左鍵發(fā)射球體;\n2、兩針 Pin 碰撞會(huì)自動(dòng)觸發(fā)重新開(kāi)始游戲;",
fontStyle);
}36、GameManager 游戲管理類(lèi) ,ToGameOver()游戲結(jié)束事件,停止旋轉(zhuǎn),開(kāi)啟協(xié)程,進(jìn)行游戲結(jié)束特效處理,然后自動(dòng)重新加載當(dāng)前場(chǎng)景,重新開(kāi)始游戲
/// <summary>
/// 游戲結(jié)束
/// </summary>
void ToGameOver() {
// 游戲結(jié)束
if (m_IsGameOver==true)
{
return;
}
// 游戲結(jié)束
m_IsGameOver = true;
// 停止目標(biāo)旋轉(zhuǎn)
m_TargetCircleManager.StopRotateSelf();
// 開(kāi)始結(jié)束協(xié)程
StartCoroutine(GameOver());
}
/// <summary>
/// 游戲結(jié)束協(xié)程
/// </summary>
/// <returns></returns>
IEnumerator GameOver() {
while (true)
{
// 等待幀最后
yield return new WaitForEndOfFrame();
// 更新主Camera 視口
m_MainCamera.orthographicSize = Mathf.Lerp(m_MainCamera.orthographicSize, m_OrthographicSize,Time.deltaTime * 10);
// 更新主Camera 背景色
m_MainCamera.backgroundColor = Color.Lerp(m_MainCamera.backgroundColor, Color.red,Time.deltaTime * 5);
// 更新主Camera 視口 到位,跳出循環(huán)
if ((m_MainCamera.orthographicSize - m_OrthographicSize)<0.01f)
{
break;
}
}
// 加載當(dāng)前場(chǎng)景
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}37、把 GameManager 掛載到場(chǎng)景中,根據(jù) GameManager 參數(shù)說(shuō)明賦值,一些速度等可以根據(jù)實(shí)際需要修改

38、運(yùn)行場(chǎng)景, Pin 自動(dòng)準(zhǔn)備好,游戲就開(kāi)始了

39、點(diǎn)擊鼠標(biāo)左鍵,即可發(fā)射Fly,如圖

七、工程源碼地址
github 地址:GitHub - XANkui/UnityMiniGameParadise: Unity 游戲開(kāi)發(fā)集合代碼集
八、延伸擴(kuò)展
游戲的好不好玩,趣味性,視覺(jué)化等諸多因素影響,下面簡(jiǎn)單介紹幾個(gè)方面拓展游戲的方向,僅做參考
1、可以根據(jù)自己需要修改游戲資源,換膚什么的等
2、可以根據(jù)需要添加撞擊特效,音效等
3、添加 UI 面板等,美化游戲
4、等等
以上就是Unity實(shí)戰(zhàn)之FlyPin(見(jiàn)縫插針)小游戲的實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Unity見(jiàn)縫插針游戲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#實(shí)現(xiàn)在Excel中添加篩選器并執(zhí)行篩選的操作
自動(dòng)篩選器是 Excel 中的一個(gè)基本但極其有用的功能,它可以讓你根據(jù)特定的條件來(lái)自動(dòng)隱藏和顯示你的數(shù)據(jù),當(dāng)有大量的數(shù)據(jù)需要處理時(shí),這個(gè)功能可以幫你快速找到你需要的信息,下面將介紹如何使用免費(fèi).NET Excel庫(kù)在Excel中添加、應(yīng)用和刪除自動(dòng)篩選器,需要的朋友可以參考下2024-05-05
C#實(shí)現(xiàn)程序開(kāi)機(jī)啟動(dòng)的方法
這篇文章主要介紹了C#實(shí)現(xiàn)程序開(kāi)機(jī)啟動(dòng)的方法,涉及C#針對(duì)應(yīng)用程序及注冊(cè)表的相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
DevExpress實(shí)現(xiàn)GridControl同步列頭checkbox與列中checkbox狀態(tài)
這篇文章主要介紹了DevExpress實(shí)現(xiàn)GridControl同步列頭checkbox與列中checkbox狀態(tài),需要的朋友可以參考下2014-08-08
C#實(shí)現(xiàn)XOR密碼(異或密碼)的示例代碼
XOR密碼(異或密碼)是一種簡(jiǎn)單的加密算法,它使用異或(XOR)操作來(lái)對(duì)明文和密鑰進(jìn)行加密和解密,本文為大家介紹了C#實(shí)現(xiàn)XOR密碼的相關(guān)知識(shí),希望對(duì)大家有所幫助2024-01-01
c#中Empty()和DefalutIfEmpty()用法分析
這篇文章主要介紹了c#中Empty()和DefalutIfEmpty()用法,以實(shí)例形式分析了針對(duì)不同情況下Empty()和DefalutIfEmpty()用法區(qū)別,需要的朋友可以參考下2014-11-11

