本節(jié)將指導(dǎo)您從頭開始創(chuàng)建將在本教程中使用的Player Prefab,以便我們涵蓋創(chuàng)建過程的每一步馁痴。
這里介紹一個好的方法谊娇,首先嘗試和創(chuàng)建一個Player Prefab,可以在沒有PUN連接的情況下工作罗晕,所以它很容易快速測試济欢,調(diào)試,并確保在沒有任何網(wǎng)絡(luò)的時候正常工作小渊。然后法褥,您可以慢慢地建立和修改每個功能到網(wǎng)絡(luò)兼容的角色:通常,用戶輸入只應(yīng)該在玩家擁有的實(shí)例上激活酬屉,而不是在其他的玩家計算機(jī)上半等。 我們將在下面詳細(xì)介紹。
主要內(nèi)容
- prefab基礎(chǔ)
- CharacterController
- 動畫設(shè)置
- 用戶輸入
- 相機(jī)設(shè)置
- 光束設(shè)置
- 健康設(shè)置
Prefab基礎(chǔ)
了解PUN的第一個重要約定是呐萨,對于一個要通過網(wǎng)絡(luò)實(shí)例化的Prefab杀饵,它需要保存在Resources文件夾中,否則不行谬擦。
在Resources中使用Prefabs的第二個重要的副作用切距,是你需要監(jiān)視他們的名字。在Assets Resources中不應(yīng)該有相同名字的Prefab惨远,因?yàn)閁nity會選擇它找到的第一個谜悟,因此請務(wù)必確保在您的項目資源中饵沧,Resources路徑中沒有兩個Prefab命名相同。
我們將使用Unity提供的Kyle Robot作為一個自由資產(chǎn)赌躺。它作為一個Fbx文件狼牺,它是由3d軟件生成的,例如3ds Max礼患,Maya是钥,cinema4d。使用這些軟件創(chuàng)建網(wǎng)格和動畫超出了本教程的范圍缅叠,但是對于創(chuàng)建自己的角色和動畫來說至關(guān)重要悄泥。這個機(jī)器人Kyle.fbx位于/Assets/Photon Unity Networking/Demos/Shared Assets/。
這里有一種方法開始使用Kyle Robot.fbx為你的玩家:
- 在項目瀏覽器中肤粱,創(chuàng)建一個名為“Resources”的文件夾
- 創(chuàng)建一個新的空場景弹囚,并保存為Kyle Test,放在這個文件夾/PunBasics_tutorial/Scenes/
- 將Robot Kyle拖放到場景Hierarchy上领曼。
- 將剛剛在Hierarchy中創(chuàng)建的GameObject重命名為My Robot Kyle
- 將我的機(jī)器人Kyle拖放到/PunBasics_tutorial/Resources/
我們現(xiàn)在創(chuàng)建了一個基于Kyle Robot Fbx資產(chǎn)的Prefab卫玖,我們在您的場景Kyle Test的Hierarchy中有一個實(shí)例”涂担現(xiàn)在我們可以開始使用它钓账。
CharacterController
- 讓我們在層次結(jié)構(gòu)中添加一個CharacterController組件到我的Kyle Robot實(shí)例灌诅。你可以直接在Prefab本身上這樣做,但我們需要調(diào)整它单刁,所以這是更快的這種方式灸异。
- 雙擊My Robot Kyle讓場景視圖放大。注意Capsule Collider在腳中間; 我們需要Capsule Collider來正確匹配角色羔飞。
- 在Capsule Collider組件中把Center.y屬性改成1肺樟。
- 點(diǎn)擊Apply使改變對prefab生效。這不很重要逻淌,因?yàn)槲覀兙庉嬃薓y Kyle Robot prefab么伯,我們想要所有的實(shí)例都生效,不只是這一個恍风,所以點(diǎn)擊Apply蹦狂。
動畫設(shè)置
分配動畫控制器
Kyle Robot Fbx資源需要Animator Graph控制。我們這篇教程不會介紹這個Graph的創(chuàng)建朋贬,所以我們提供了一個控制器,在項目Assets中Photon Unity Networking/Demos/PunBasics/Animator/ 下面窜骄,叫做Kyle Robot锦募。
要把這個Kyle Robot控制器分配給我們的Prefab,只需要把Animator組件的Controller屬性設(shè)置為Kyle Robot邻遏。
不要忘了糠亩,如果你修改的是My Kyle Robot實(shí)例虐骑,你需要點(diǎn)擊Prefab的Apply使改變生效。
嘗試控制器參數(shù)
理解Animator控制器的關(guān)鍵特性是動畫參數(shù)赎线,這些參數(shù)是我們?nèi)绾瓮ㄟ^腳本控制動畫廷没。在我們的例子中,有參數(shù)例如速度垂寥,方向颠黎,跳躍,Hi滞项。
Animator組件的一個重要功能是根據(jù)其動畫實(shí)際移動角色的能力狭归,這個功能稱為Root Motion,并且在Animator組件上有一個屬性Apply Root Motion文判,默認(rèn)情況下是true过椎。
所以,實(shí)際上戏仓,要讓人物走路疚宇,我們只需要將速度動畫參數(shù)設(shè)置為正值,它將開始行走和向前移動赏殃。 我們開工吧灰嫉!
Animator Manager Script
讓我們創(chuàng)建一個新的腳本,我們將基于用戶的輸入控制角色嗓奢。
創(chuàng)建新的腳本PlayerAnimatorManager
添加到My Robot Kyle這個Prefab 上
-
代碼如下
using UnityEngine; using System.Collections; namespace Com.MyCompany.MyGame { public class PlayerAnimatorManager : MonoBehaviour { #region MONOBEHAVIOUR MESSAGES // Use this for initialization void Start() { } // Update is called once per frame void Update() { } #endregion } }
保存腳本
Animator Manager : 速度控制
我們要做的第一件事實(shí)獲得Animator組件讼撒,以便于控制它
確保你正在編輯PlayerAnimatorManager
創(chuàng)建一個Animator類型的私有變量animator
-
在Start()函數(shù)中保存Animator組件
private Animator animator; // Use this for initialization void Start() { animator = GetComponent<Animator>(); if (!animator) { Debug.LogError("PlayerAnimatorManager is Missing Animator Component", this); } }
注意,由于我們需要一個Animator組件股耽,如果我們沒有得到一個根盒,我們記錄一個錯誤,以便它不被忽視物蝙,并由開發(fā)人員直接解決炎滞。你應(yīng)該總是寫出來,如果它將被其他人使用的話:)它盡管單調(diào)乏味诬乞,但長遠(yuǎn)來看是值得的册赛。
-
讓我們監(jiān)聽用戶輸出,控制動畫的Speed參數(shù)
// Update is called once per frame void Update() { if (!animator) { return; } float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); if (v < 0) { v = 0; } animator.SetFloat("Speed", h * h + v * v); }
保存腳本
讓我們看看這個腳本做了什么:
因?yàn)槲覀兊挠螒虿辉试S向后移動震嫉,所以我們確保v大于0.用戶按下向下鍵或's'鍵森瘪,我們不允許這樣做,并將值強(qiáng)制為0票堵。
你會注意到扼睬,我們已經(jīng)平方了兩個輸入,為什么悴势? 所以它總是一個正的絕對值窗宇,以及增加一些緩和措伐。 這里是個微妙的技巧。你也可以使用Mathf.Abs()军俊,這將工作正常侥加。
我們還增加了兩個輸入來控制Speed,所以當(dāng)我們只是按下左邊的輸入粪躬,我們轉(zhuǎn)彎時仍然獲得一些速度担败。
當(dāng)然,所有這些都是非常具體的我們的角色設(shè)計短蜕,根據(jù)你的游戲邏輯氢架,你可能希望角色原地轉(zhuǎn),或有能力后退朋魔,所以動畫參數(shù)的控制總是針對具體的游戲 岖研。
測試,測試 1 2 3...
讓我們驗(yàn)證我們迄今為止做了什么警检。確保您已打開Kyle Test場景孙援。目前,在這個場景中扇雕,我們只有一個相機(jī)和Kyle Robot實(shí)例拓售,場景缺少地面機(jī)器人站立的地面,如果你現(xiàn)在運(yùn)行場景凱爾機(jī)器人會下降镶奉。 此外础淤,我們不會在現(xiàn)場照明或任何奇怪,我們想測試和驗(yàn)證我們的角色和腳本是否正常工作哨苛。
- 將Cube添加到場景鸽凶。因?yàn)橐粋€Cube默認(rèn)情況下是Box碰撞器,我們很好地使用它作為地板建峭。
- 把它放到0玻侥,-0.5,0,因?yàn)榱⒎襟w的高度是1.我們希望立方體的頂面是地板亿蒸。
- 將Cube縮放到30,1,30凑兰,以便我們有空間進(jìn)行實(shí)驗(yàn)
- 選擇相機(jī)并將其移開,以獲得良好的觀察視野边锁。一個很好的技巧是在Scene視圖中調(diào)整到您喜歡的視圖姑食,選擇相機(jī)并轉(zhuǎn)到菜單 "GameObject/Align With View",攝像機(jī)將匹配場景視圖砚蓬。
- 最后一步矢门,往y軸上方移動My Robot Kyle 0.1單位,否則碰撞在開始時被錯過灰蛙,角色通過地板祟剔,所以在碰撞者之間留下一些物理空間。
- 運(yùn)行場景摩梧,按向上箭頭鍵或'a'物延,角色正在走!您可以使用所有鍵進(jìn)行測試以驗(yàn)證仅父。
很好叛薯,但仍然很多工作在前頭,我們的相機(jī)需要跟隨笙纤,我們不能轉(zhuǎn)動...
如果你現(xiàn)在想在相機(jī)上工作耗溜,請轉(zhuǎn)到相機(jī)部分,本頁的其余部分將完成Animator控件并實(shí)現(xiàn)旋轉(zhuǎn)省容。
Animator Manager 腳本:方向控制
控制旋轉(zhuǎn)將稍微更復(fù)雜抖拴,我們不希望我們的角色因?yàn)榘醋笥益I突然旋轉(zhuǎn),我們希望溫柔平滑的旋轉(zhuǎn)腥椒。幸運(yùn)的是阿宅,動畫參數(shù)可以使用一些阻尼來設(shè)置。
確保您正在編輯腳本 PlayerAnimatorManager
-
在“PRIVATE PROPERTIES”區(qū)域上方的腳本的新區(qū)域“PUBLIC PROPERTIES”中創(chuàng)建公共float變量DirectionDampTime
//#region PUBLIC PROPERTIES public float DirectionDampTime = .25f; //#endregion
-
在Update函數(shù)結(jié)尾處笼蛛,添加:
animator.SetFloat( "Direction", h, DirectionDampTime, Time.deltaTime );
所以我們馬上注意到animator.SetFloat()有不同的聲明洒放。我們用來控制速度是一個簡單的,但對于這一個需要兩個參數(shù)滨砍,一個是阻尼時間往湿,一個deltaTime。阻尼時間有意義:它達(dá)到所需的值需要多長時間惋戏,但deltaTime呢领追?它本質(zhì)上讓你編寫的幀速率獨(dú)立的代碼,因?yàn)閁pdate()取決于幀速率日川,我們需要通過使用deltaTime來考慮這種情況蔓腐。盡可能多的閱讀關(guān)于這個主題,當(dāng)你和在網(wǎng)上搜索的時候你會發(fā)現(xiàn)龄句。只有在你理解了這一概念之后回论,在動畫和隨時間變化對數(shù)值的一致性控制方面,你才能充分利用Unity的許多功能分歇。
- 保存腳本PlayerAnimatorManager
- 運(yùn)行你的場景傀蓉,并使用所有箭頭,看看你的角色是行走和轉(zhuǎn)身怎么樣
- 測試DirectionDampTime的效果:將其設(shè)為1职抡,例如葬燎,然后5,看到它需要達(dá)到最大轉(zhuǎn)向能力。你會看到轉(zhuǎn)彎半徑隨著DirectionDampTime增加谱净。
Animator Manager 腳本:跳躍
關(guān)于跳躍窑邦,我們需要多做一點(diǎn)工作,因?yàn)閮蓚€原因壕探。一是我們不想讓玩家在不跑動的情況下跳躍冈钦,二是我們不想跳躍循環(huán)。
確保正在編輯腳本PlayerAnimatorManager
-
在update方法中李请,捕捉用戶輸入之前瞧筛,插入下面代碼
// deal with Jumping AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0); // only allow jumping if we are running. if (stateInfo.IsName("Base Layer.Run")) { // When using trigger parameter if (Input.GetButtonDown("Fire2")) animator.SetTrigger("Jump"); }
保存腳本PlayerAnimatorManager
測試,開始跑動然后按下alt鍵导盅,Kyle會跳起來
要理解的第一件事情就是我們怎樣知道animator正在跑動较幌,通過使用stateInfo.IsName("Base Layer.Run"),我們詢問目前Animator的激活狀態(tài)是否是Run白翻。我們必須添加Base Layer因?yàn)镽un狀態(tài)是在Base Layer中的乍炉。
如果我們處于Run狀態(tài),然后我們監(jiān)聽Fire2輸入嘁字,然后調(diào)用Jump觸發(fā)器恩急。
到目前為止PlayerAnimatorManager腳本的完整版本:
using UnityEngine;
using System.Collections;
namespace Com.MyCompany.MyGame
{
public class PlayerAnimatorManager : MonoBehaviour
{
#region PUBLIC PROPERTIES
public float DirectionDampTime = .25f;
#endregion
#region MONOBEHAVIOUR MESSAGES
private Animator animator;
// Use this for initialization
void Start()
{
animator = GetComponent<Animator>();
if (!animator)
{
Debug.LogError("PlayerAnimatorManager is Missing Animator Component", this);
}
}
// Update is called once per frame
void Update()
{
if (!animator)
{
return;
}
// deal with Jumping
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
// only allow jumping if we are running.
if (stateInfo.IsName("Base Layer.Run"))
{
// When using trigger parameter
if (Input.GetButtonDown("Fire1"))
{
Debug.Log("jump");
animator.SetTrigger("Jump");
}
}
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
if (v < 0)
{
v = 0;
}
animator.SetFloat("Speed", h * h + v * v);
animator.SetFloat("Direction", h, DirectionDampTime, Time.deltaTime);
}
#endregion
}
}
當(dāng)你考慮它在場景中實(shí)現(xiàn)的功能,對于這幾行代碼來說還不錯〖脱眩現(xiàn)在讓我們處理相機(jī)的工作衷恭,因?yàn)槲覀兡軌蛟谖覀兊氖澜缁顒樱覀冃枰粋€合適的相機(jī)行為跟隨纯续。
相機(jī)設(shè)置
在本節(jié)中随珠,我們將使用CameraWork腳本,以保持專注于Player Prefab整體創(chuàng)建過程猬错。如果你想從頭開始寫CameraWork窗看,請去下一部分,完成后回到這里倦炒。
- 將組件CameraWork添加到My Kyle Robot Prefab
- 打開屬性Follow on Start显沈,可以有效地使照相機(jī)即時跟隨角色。當(dāng)我們開始網(wǎng)絡(luò)實(shí)現(xiàn)時逢唤,我們將關(guān)閉它
- 設(shè)置屬性Center Offset為0,4,0拉讯,這使得相機(jī)看起來更高,從而給出了一個更好的視角的環(huán)境比鳖藕,如果相機(jī)直視玩家魔慷,我們會看到太多的地面什么都沒有。
- 運(yùn)行場景Kyle Test著恩,并移動角色院尔,以驗(yàn)證相機(jī)正確跟隨角色蜻展。
光束設(shè)置
我們的機(jī)器人角色還沒有武器,讓我們創(chuàng)造一些可以從它的眼睛中發(fā)出來的激光束邀摆。
添加光束模型
為了簡單起見纵顾,我們將使用簡單的立方體并將它們縮放為非常瘦長。有一些技巧來快速做到這一點(diǎn):不要直接添加一個Cube作為頭部節(jié)點(diǎn)的子節(jié)點(diǎn)隧熙,而是創(chuàng)建它移動它片挂,并放大幻林,然后將其附加到頭贞盯,這將防止猜測正確旋轉(zhuǎn)值讓你的光束與眼睛對齊。
另一個重要的技巧是沪饺,對兩個光束只使用一個碰撞器躏敢。這是為了讓物理引擎更好地工作,瘦的碰撞器從來不是一個好主意整葡,它不可靠件余,所以我們將制作一個大盒子碰撞器,以確痹饩樱可靠地?fù)糁心繕?biāo)啼器。
- 打開Kyle test場景
- 添加一個Cube,命名為Beam Left
- 把它修改成一個長的光束俱萍,放到左眼的位置
- 在Hierarchy中選中My Kyle Robot
- 選中Head子節(jié)點(diǎn)
- 給Head對象添加一個空白對象端壳,命名為Beams
- 把Beam Left拖拽到Beams下面
- 復(fù)制Beams Left,命名為Beams Right
- 把它放到右眼的位置上
- 去掉Beams Right的碰撞體
- 調(diào)整Beams Right的碰撞體枪蘑,讓它包括兩個Beam對象
- 把Beams Left碰撞體的IsTrigger屬性設(shè)置為True损谦,我們只想知道光束接觸到的玩家,而不是碰撞體
- 撞見一個新的材質(zhì)岳颇,命名為Red Beam照捡,保存
- 把Red Beam賦值給兩個Beams
- 對prefab執(zhí)行Apply
你應(yīng)該像下面這樣的:
通過用戶輸入控制Beams
好了,既然我們有了激光束话侧,讓我們使用Fire鍵來觸發(fā)他們栗精。
創(chuàng)建一個C#腳本,命名為PlayerManager瞻鹏。下面是該腳本第一個版本的完整內(nèi)容:
using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;
namespace Com.MyCompany.MyGame
{
/// <summary>
/// Player manager.
/// Handles fire Input and Beams.
/// </summary>
public class PlayerManager : MonoBehaviour
{
#region Public Variables
[Tooltip("The Beams GameObject to control")]
public GameObject Beams;
#endregion
#region Private Variables
//True, when the user is firing
bool IsFiring;
#endregion
#region MonoBehaviour CallBacks
/// <summary>
/// MonoBehaviour method called on GameObject by Unity during early initialization phase.
/// </summary>
void Awake()
{
if (Beams == null)
{
Debug.LogError("<Color=Red><a>Missing</a></Color> Beams Reference.", this);
}
else
{
Beams.SetActive(false);
}
}
/// <summary>
/// MonoBehaviour method called on GameObject by Unity on every frame.
/// </summary>
void Update()
{
ProcessInputs();
// trigger Beams active state
if (Beams != null && IsFiring != Beams.GetActive())
{
Beams.SetActive(IsFiring);
}
}
#endregion
#region Custom
/// <summary>
/// Processes the inputs. Maintain a flag representing when the user is pressing Fire.
/// </summary>
void ProcessInputs()
{
if (Input.GetButtonDown("Fire1"))
{
if (!IsFiring)
{
IsFiring = true;
}
}
if (Input.GetButtonUp("Fire1"))
{
if (IsFiring)
{
IsFiring = false;
}
}
}
#endregion
}
}
這個腳本在這個階段的要點(diǎn)是激活或停用激光束悲立。當(dāng)激活時,激光束將有效地觸發(fā)與其他模型發(fā)生碰撞乙漓,因此我們將在后面利用這些觸發(fā)器來影響每個角色的健康值级历。
我們還暴露了一個公共屬性Beams,它將讓我們在My Kyle Robot Prefab的層次結(jié)構(gòu)中引用確切的對象叭披。讓我們看看我們?nèi)绾喂ぷ鱽磉B接Beams寥殖,因?yàn)樵贏ssets瀏覽器中玩讳,Prefabs只暴露第一個子節(jié)點(diǎn),而不是所有子節(jié)點(diǎn)嚼贡,而且我們的Beams確實(shí)埋在Prefab層次結(jié)構(gòu)中熏纯,因此,我們需要從場景中的一個實(shí)例執(zhí)行此操作粤策,然后將其應(yīng)用回Prefab本身樟澜。
- 打開Kyle Test場景
- 在場景Hierachy中選擇我的Kyle Robot
- 將PlayerManager組件添加到My Kyle Robot
- 將My Kyle Robot/Root/Ribs/Neck/Head/Beams拖放到Inspector中的PlayerManager Beams屬性中
- 將實(shí)例中的更改應(yīng)用到Prefab
如果你點(diǎn)擊play,并按Fire1輸入(默認(rèn)情況下是左鼠標(biāo)或左ctrl鍵)叮盘,Beams將顯示秩贰,并立即隱藏時釋放時。
健康設(shè)置
讓我們實(shí)現(xiàn)一個非常簡單的健康系統(tǒng)柔吼,當(dāng)光束擊中玩家時會減少生命毒费。由于它不是子彈,而是一個恒定的能量流愈魏,我們需要以兩種方式考慮健康損害觅玻,當(dāng)我們受到光束撞擊時,以及在整個時間射束撞擊我們培漏。
打開PlayerManager腳本
-
為了暴露PhotonView組件溪厘,把PlayerManager改變成Photon.PunBehaviour的子對象,
public class PlayerManager : Photon.PunBehaviour {
-
在Public Variables區(qū)塊添加一個公共的Health屬性
[Tooltip("The current Health of our player")] public float Health = 1f;
-
在MonoBehaviour CallBacks區(qū)塊中添加下面兩個方法
/// <summary> /// MonoBehaviour method called when the Collider 'other' enters the trigger. /// Affect Health of the Player if the collider is a beam /// Note: when jumping and firing at the same, you'll find that the player's own beam intersects with itself /// One could move the collider further away to prevent this or check if the beam belongs to the player. /// </summary> void OnTriggerEnter(Collider other) { if (!photonView.isMine) { return; } // We are only interested in Beamers // we should be using tags but for the sake of distribution, let's simply check by name. if (!other.name.Contains("Beam")) { return; } Health -= 0.1f; } /// <summary> /// MonoBehaviour method called once per frame for every Collider 'other' that is touching the trigger. /// We're going to affect health while the beams are touching the player /// </summary> /// <param name="other">Other.</param> void OnTriggerStay(Collider other) { // we dont' do anything if we are not the local player. if (!photonView.isMine) { return; } // We are only interested in Beamers // we should be using tags but for the sake of distribution, let's simply check by name. if (!other.name.Contains("Beam")) { return; } // we slowly affect health when beam is constantly hitting us, so player has to move to prevent death. Health -= 0.1f * Time.deltaTime; }
保存PlayerManager腳本
首先牌柄,這兩種方法幾乎是相同的畸悬,唯一的區(qū)別是,我們在TriggerStay期間使用Deltatime減少健康友鼻,減量的速度不取決于幀速率傻昙。這是一個重要的概念,通常適用于動畫彩扔,但在這里妆档,我們也需要這樣,我們希望Health在所有設(shè)備上以可預(yù)測的方式減少虫碉,在更快的計算機(jī)上這是不公平的贾惦,你的健康下降更快:) Deltatime在這里是為了保證一致性。如果您有問題敦捧,并通過搜索Unity社區(qū)了解DeltaTime须板,直到您完全吸收這個概念,然后回來兢卵,這是至關(guān)重要的习瑰。
第二個重要的方面,現(xiàn)在應(yīng)該明白秽荤,我們只影響本地玩家的健康甜奄,這就是為什么我們前面退出方法的條件PhotonView不是Mine柠横。
最后,如果擊中我們的對象是一個Beam课兄,我們只想影響健康牍氛,所以我們使用標(biāo)簽“Beam”檢查這點(diǎn),這是我們?yōu)楹螛?biāo)記我們的Beam對象烟阐。
為了便于調(diào)試搬俊,我們使Health float作為一個公共浮動,以便在等待UI構(gòu)建時輕松檢查其值蜒茄。
好吧唉擂,這看起來一切正確嗎?健康系統(tǒng)是不完整的扩淀,當(dāng)健康是0時楔敌,沒有考慮到玩家的游戲結(jié)束狀態(tài),讓我們現(xiàn)在做到這一點(diǎn)驻谆。
游戲結(jié)束健康檢查
為了保持簡單,當(dāng)玩家的健康達(dá)到0時庆聘,我們就離開房間胜臊。如果你還記得,我們已經(jīng)在GameManager Script中創(chuàng)建了一個離開房間的方法伙判。如果我們可以重用這個方法而不是重寫一遍象对,這是不錯的主意。 相同結(jié)果的重復(fù)代碼是你應(yīng)該盡一切代價避免的宴抚。這也將是一個好時機(jī)勒魔,介紹一個非常方便的編程概念,“Singleton”菇曲。 雖然這個主題本身可以寫滿幾個教程冠绢,我們將只實(shí)現(xiàn)極小的“單例”。了解Singleton常潮,它們在Unity上下文中的變體以及它們?nèi)绾螏椭鷦?chuàng)建強(qiáng)大的功能是非常重要的弟胀,并將為您節(jié)省很多麻煩。所以喊式,不要猶豫孵户,把時間放在這個教程來了解更多。
打開GameManager腳本
-
在Public Properties區(qū)塊添加這個變量
static public GameManager Instance;
-
在Start函數(shù)中添加這行代碼
Instance = this;
保存GameManager腳本
注意岔留,我們使用[static]關(guān)鍵字修飾了Instance變量夏哭,這意味著,不必持有一個指向GameManager實(shí)例的指針献联,就可以使用這個變量竖配,所以你可以在代碼中的任何地方做一個簡單的GameManager.instance.xxx()厕吉。這是非常實(shí)用的!讓我們看看如何用于我們的游戲結(jié)束邏輯管理械念。
打開PlayerManager腳本
-
在Update函數(shù)中头朱,ProcessInput之后,加入這些代碼
if ( Health <= 0f) { GameManager.Instance.LeaveRoom(); }
保存PlayerManager腳本
- 注意龄减,我們考慮到健康可能是負(fù)面的项钮,因?yàn)榧す馐斐傻膿p害在強(qiáng)度上是不同的。
- 注意希停,我們調(diào)用了GameManager實(shí)例的LeaveRoom()公共方法烁巫,而實(shí)際上不需要獲取組件或任何東西,我們僅僅依賴于我們假設(shè)GameManager組件在當(dāng)前場景中某個GameObject上的事實(shí)宠能。
好了亚隙,下面我們要處理網(wǎng)絡(luò)部分。
原文
http://doc.photonengine.com/en-us/pun/current/tutorials/pun-basics-tutorial/player-prefab#cam_setup