加載場(chǎng)景的代碼
本地加載
有許多方法,舉幾個(gè)例子:
本地加載
//本地跳轉(zhuǎn)
using UnityEngine.SceneManagement;
//這個(gè)0是Build Settings面板中場(chǎng)景的順序。(Unity基礎(chǔ)知識(shí))
SceneManager.LoadScene(0);//也有其他方法
本地異步加載(場(chǎng)景內(nèi)容過多時(shí),防止卡頓異步加載)
//本地異步加載(場(chǎng)景內(nèi)容過多,防止卡頓異步加載)
StartCoroutine("LoadLevel1");
IEnumerator LoadLevel1()
{
loadPanel.SetActive(true);
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("SampleScene");
//AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("SampleScene", LoadSceneMode.Additive);
asyncOperation.allowSceneActivation = false;
while (!asyncOperation.isDone)
{
slider.value = asyncOperation.progress;
valueText.text = asyncOperation.progress * 100 + "%";
//asyncOperation.progress在0.9時(shí)就已經(jīng)加載完成
if (asyncOperation.progress >= 0.9f)
{
slider.value = 1;
valueText.text = "按任意鍵開始";
if (Input.anyKeyDown)
{
asyncOperation.allowSceneActivation = true;
}
}
yield return null;
}
}
多人游戲加載場(chǎng)景
pun2插件加載
//PUN2加載
//房主執(zhí)行:
PhotonNetwork.LoadLevel("SceneName");
//其他玩家在開啟自動(dòng)同步場(chǎng)景時(shí)會(huì)跟隨加載
PhotonNetwork.AutomaticallySyncScene = true;
這個(gè)異步加載起初是覺得場(chǎng)景內(nèi)容如果過多會(huì)引起卡頓。所以把這個(gè)應(yīng)用在了單機(jī)模式上。
至于多人游戲加載場(chǎng)景,可能用不到而且也沒法使用這個(gè)異步加載,可以通過pun插件的SetCustomProperties()
和OnPlayerPropertiesUpdate
回調(diào)確保所有人加載完成再開始。
場(chǎng)景內(nèi)容多端同步(真正的游戲多人化)
PUN文檔提到的幾點(diǎn)重要信息
想要做一個(gè)多人游戲,在使用PUN2插件時(shí),完全可以先做好一個(gè)單機(jī)游戲,再對(duì)其進(jìn)行修改。修改時(shí)對(duì)于預(yù)制體不要忘記放在pun規(guī)定的文件夾里。
官方文檔提到的兩個(gè)重要技巧以及其他幾點(diǎn):
在場(chǎng)景中修改實(shí)例后不要忘記apply預(yù)置體。
Time.deltatime保證平滑顯示及多客戶端一致性、不會(huì)因?yàn)槟骋慌_(tái)電腦好幀數(shù)高就會(huì)出現(xiàn)掉血多的情況。
PhotonView組件。是連接多個(gè)客戶端的組件,決定物體的哪些組件需要同步、以及如何同步。
開火狀態(tài)設(shè)置一個(gè)bool isFiring,可以配合gameobject.activeInHierarchy進(jìn)行開火顯示。
發(fā)生碰撞,若需要時(shí)一定判斷photonView.IsMine。判斷collider來源。
官方對(duì)于photonView.IsMine的解釋,通俗易懂。
擁有權(quán)的概念實(shí)現(xiàn)分端控制各自的物體如玩家對(duì)象。公共物體由主客戶端控制。
/// <summary>
/// True if the PhotonView is "mine" and can be controlled by this client.
/// </summary>
/// <remarks>
/// PUN has an ownership concept that defines who can control and destroy each PhotonView.
/// True in case the controller matches the local Player.
/// True if this is a scene photonview (null owner and ownerId == 0) on the Master client.
/// </remarks>
場(chǎng)景內(nèi)容多端同步
本篇接下來記錄實(shí)際開發(fā)。
把第一個(gè)游戲(2D向下跑)進(jìn)行多人化。
相信大家看到這個(gè)界面就知道是怎么個(gè)玩法了。(素材以及源碼參考b站)
保證同時(shí)開始游戲
首先通過Start
回調(diào)更改本地玩家的customProperties
,把“是否加載完場(chǎng)景”的鍵值對(duì)的值改為true。
public void Start()//“通知其他人”:我加載好了
{
Hashtable props = new Hashtable
{
{Const.PLAYER_LOADED_LEVEL, true}
};
PhotonNetwork.LocalPlayer.SetCustomProperties(props);//“通知其他人”我加載好了場(chǎng)景
}
其他玩家會(huì)自動(dòng)執(zhí)行回調(diào)OnPlayerPropertiesUpdate
來判斷是否加載完成。
public override void OnPlayerPropertiesUpdate(Photon.Realtime.Player targetPlayer, Hashtable changedProps)//判斷游戲結(jié)束(通過生命數(shù))||全員加載進(jìn)來(然后開始倒計(jì)時(shí))
{
if (changedProps.ContainsKey(Const.PLAYER_LIVES))
{
CheckEndOfGame();
return;
}
if (!PhotonNetwork.IsMasterClient)
{
return;
}
// if there was no countdown yet, the master client (this one) waits until everyone loaded the level and sets a timer start
int startTimestamp;
bool startTimeIsSet = CountdownTimer.TryGetStartTime(out startTimestamp);
if (!isGameStart && changedProps.ContainsKey(Const.PLAYER_LOADED_LEVEL))//有人加載進(jìn)來了
{
if (CheckAllPlayerLoadedLevel())//判斷是不是都加載進(jìn)來了
{
if (!startTimeIsSet)//如果沒有設(shè)置時(shí)間,設(shè)置開始計(jì)時(shí)時(shí)間為當(dāng)前時(shí)間
{
CountdownTimer.SetStartTime();
}
}
else
{
// not all players loaded yet. wait:
Debug.Log("setting text waiting for players! ", this.InfoText);
InfoText.text = "等待其他玩家...";
}
}
}
其中CountdownTimer.SetStartTime();
是pun官方的計(jì)時(shí)器代碼。
當(dāng)所有玩家全部加載完成后,會(huì)從此刻倒計(jì)時(shí)5s,有GUI提示哦。
5s倒計(jì)時(shí)后則會(huì)觸發(fā)事件,官方demo用的委托設(shè)計(jì)模式。OnCountdownTimerHasExpired
是倒計(jì)時(shí)結(jié)束事件。倒計(jì)時(shí)結(jié)束自然會(huì)執(zhí)行委托中的OnCountdownTimerIsExpired
方法。OnCountdownTimerIsExpired
方法中會(huì)啟動(dòng)游戲,生成玩家。
public override void OnEnable()//添加計(jì)時(shí)委托
{
base.OnEnable();
CountdownTimer.OnCountdownTimerHasExpired += OnCountdownTimerIsExpired;//給委托加一個(gè)方法,這個(gè)方法會(huì)執(zhí)行這里的“開始游戲”
}
第一個(gè)游戲要額外注意。這5s倒計(jì)時(shí)中,要保證場(chǎng)景中那個(gè)平臺(tái)不會(huì)上升。等到真正倒計(jì)時(shí)結(jié)束后才開始上升。所以需要改一下代碼,5s倒計(jì)時(shí)后isGameStarted = true,根據(jù)這個(gè)變量判斷是否可以上升。
除此以外有好多地方的代碼需要改。
比如確保玩家只控制自己的角色移動(dòng)(通過photonView.IsMine
判斷)、死亡后的觀戰(zhàn)而不是重玩一局等。
另外需要把預(yù)制體放在規(guī)定文件夾下。
另外就是這個(gè)預(yù)制體可以放在規(guī)定文件夾內(nèi)部的子文件中。
藍(lán)色框是規(guī)定路徑,黃色框是根據(jù)需要?jiǎng)?chuàng)建的子文件夾。
實(shí)例化時(shí),預(yù)制體名(string)
那個(gè)參數(shù),要寫上路徑就是了。如下:
//常量路徑字符串
public const string PLATFORM_PREFABS_BASEPATH = "PunPlatformGamePrefabs/PlatformPrefabs/";
//實(shí)例化時(shí):platforms[index]:string類型
PhotonNetwork.InstantiateRoomObject(Const.PLATFORM_PREFABS_BASEPATH + platforms[index], spawnPosition, Quaternion.identity);
除了改代碼,最重要的就是不要忘了在預(yù)制體上加入一個(gè)PhotonView組件。
新版pun2插件無需手動(dòng)選擇同步什么組件。選擇AutoFindAll
就可以了,還是挺方便的。文章來源:http://www.zghlxwxcb.cn/news/detail-427691.html
具體的這里不多說了,看官方文檔和demo足夠了。
有疑問歡迎留言。文章來源地址http://www.zghlxwxcb.cn/news/detail-427691.html
到了這里,關(guān)于項(xiàng)目實(shí)訓(xùn)--Unity多人游戲開發(fā)(十一、PUN框架--游戲場(chǎng)景篇(加載與同步))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!