需要添加的插件內容
Netcode for GameObjects:是一個為 Unity 游戲開發提供高級網絡功能的 SDK。它的主要作用是允許開發者在其 GameObject 和 MonoBehaviour 工作流中集成網絡功能,并且可以與多種底層傳輸層協議兼容。
具體內容請看:https://zhuanlan.zhihu.com/p/669642159
ParrelSync:ParrelSync 是一個 Unity 編輯器擴展,旨在幫助開發者在沒有構建項目的情況下測試多人游戲玩法。通過使用 ParrelSync,開發者可以在多個 Unity 編輯器窗口中同時運行項目,從而快速測試多人游戲的功能和同步問題。
具體內容請看:ParrelSync 安裝和配置指南-CSDN博客
客戶端制作
Network manager?
? ? ? ? 添加了Net for work腳本后,可以給物體掛載Network manager腳本。我們需要創建一個空物體,并將該腳本掛載上。
編寫客戶端控制腳本
這段腳本代碼的作用是管理游戲的標題屏幕,提供兩個主要功能:
啟動網絡會話作為主機(
StartNetworkAsHost
),允許其他客戶端連接。開始一個新游戲(
StartNewGame
),加載游戲的初始狀態。
using SG;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;namespace SG
{public class TitleScreenManager : MonoBehaviour{// Start is called before the first frame updatepublic void StartNetworkAsHost(){NetworkManager.Singleton.StartHost();}public void StartNewGame(){StartCoroutine(WorldSaveManager.instance.LoadNewGame());}}}
命名空間:?
namespace SG
:定義了一個命名空間,用于組織代碼,避免命名沖突。
團隊開發中,不同開發者可能會使用相同的標識符名稱(如函數、類、變量等),導致命名沖突。命名空間通過為標識符添加一個前綴(即命名空間名稱),將標識符限定在一個特定的作用域內,從而避免了全局作用域中的命名沖突。
StartNetworkAsHost方法:
- 這個方法的作用是啟動一個網絡主機(Host)。在Unity Netcode中,主機既是服務器又是客戶端,可以允許其他客戶端連接到它
NetworkManager.Singleton.StartHost();
:
NetworkManager
是Unity Netcode(以前稱為UNet)中的一個單例類,用于管理網絡會話。
Singleton
是NetworkManager
的單例實例,確保在整個應用程序中只有一個NetworkManager
對象。
StartHost()
是NetworkManager
的一個方法,用于啟動主機模式。當用戶調用StartHost()
時,實際上是讓用戶的電腦設備承擔了主機的角色,同時運行服務器和客戶端的功能。
StartNewGame
方法:
- 這個方法用于開始一個新游戲。
WorldSaveManager.instance
:假設WorldSaveManager
是一個單例模式的管理器類,instance
是其唯一的實例。
LoadNewGame()
:這是一個協程方法,用于加載新游戲。協程在Unity中用于執行需要分多個幀完成的操作,通常用于避免主線程阻塞。
? ? ? ? 注意,這個掛載Network Manager腳本的空物體要加入預制體,在Unity中,將腳本掛載在空物體上作為單例管理器是一種常見的設計模式,這種模式能夠確保在整個游戲或應用中只有一個實例存在,并且提供了一個全局的訪問點,要添加至Asset—prefabs中。
掛載unity?import
????????將 Unity Transport 掛載在 NetworkManager 物體上,是為了讓 NetworkManager 使用它來處理網絡連接和數據傳輸。Unity Transport 作為 NetworkManager 的傳輸層,負責實際的網絡通信工作,使得 NetworkManager 能夠通過網絡與其他客戶端或服務器進行交互。
? ? ? ? 將腳本Unity Transport掛載到Network Transport
編寫切換大世界場景腳本?
????????用于Unity游戲引擎中的世界保存管理器(WorldSaveManager)。它的主要功能是管理游戲世界的加載。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;namespace SG
{public class WorldSaveManager : MonoBehaviour{// Start is called before the first frame updatepublic static WorldSaveManager instance;[SerializeField] int worldSceneIndex = 1;private void Awake(){if (instance == null){instance = this;}else{Destroy(gameObject);}}private void Start(){DontDestroyOnLoad(gameObject);}public IEnumerator LoadNewGame(){AsyncOperation loadOperation = SceneManager.LoadSceneAsync(worldSceneIndex);yield return null;}}
}
[SerializeField] int worldSceneIndex = 1;
這是一個Unity提供的特性(Attribute),用于指定一個私有字段(private field)應該在Unity編輯器的Inspector面板中顯示并可編輯。
通常情況下,私有字段不會在Inspector面板中顯示,但添加了
[SerializeField]
特性后,該字段就會在Inspector中可見,允許你在編輯器中直接修改它的值。?
private void Start() {DontDestroyOnLoad(gameObject); }
?這是Unity的另一個生命周期方法,在
Awake
之后調用。在這里,它調用了DontDestroyOnLoad
方法,確保WorldSaveManager
實例在場景切換時不會被銷毀。
public IEnumerator LoadNewGame() {AsyncOperation loadOperation = SceneManager.LoadSceneAsync(worldSceneIndex);yield return null; }?
????????這段代碼的作用是啟動一個異步操作,用于加載指定索引的場景。加載過程不會阻塞主線程,游戲可以繼續運行,同時場景在后臺加載。
SceneManager.LoadSceneAsync(worldSceneIndex)
:使用Unity的場景管理器異步加載指定索引的場景(這里是worldSceneIndex
)。
SceneManager.LoadSceneAsync
:這是Unity引擎中SceneManager
類的一個靜態方法,用于異步加載場景。
AsyncOperation
:這是一個返回值類型,表示異步操作的對象。通過這個對象,可以監聽頁面加載的進度和狀態。
yield return null
:這是一個協程的暫停點,表示在下一幀繼續執行。這里可能需要進一步的邏輯來處理場景加載的完成,比如等待加載完成后再繼續執行其他操作
????????Q1:什么是異步操作?? ? ? ? A1:異步操作是指一個操作在啟動后,不會立即阻塞當前線程的執行,而是允許當前線程繼續處理其他任務,直到該操作完成。
????????????????異步操作通常用于執行耗時的任務,例如文件讀寫、網絡請求、場景加載等,以避免主線程被阻塞,導致應用程序響應遲緩或卡頓。
? ? ? ? Q2:為什么這里要用異步操作?? ? ? ? A2:在Unity中,加載場景是一個耗時的操作,特別是當場景包含大量資源(如模型、紋理、動畫等)時。如果使用同步加載(即
SceneManager.LoadScene
),主線程會被阻塞,直到場景加載完成。這會導致游戲在加載期間出現卡頓,甚至完全凍結,嚴重影響用戶體驗。????????????????通過使用異步加載(即
SceneManager.LoadSceneAsync
),場景的加載過程會在后臺進行,而主線程可以繼續處理其他任務,例如更新UI、播放加載動畫、響應用戶輸入等。這樣可以確保游戲在加載場景時仍然保持流暢的運行。
????????注意,這個掛載world Save Manager腳本的空物體要加入預制體?
????????
如何設置場景序號
1、先將當前客戶端場景——save as——保存到Asset——Scene中(相當于另存一份),再刪去多余的一份。
2、為場景添加序號
? ? ? ? 進入當前場景后,進入Building Setting界面,點擊Add Open Scenes
為客戶端設置按鈕?
1、button的第一個設定:使網絡會話作為主機(
StartNetworkAsHost
),允許其他客戶端連接。2、button的第二個設定:隱藏Start Game游戲欄
3、button的第三個設定:顯示New Game游戲欄
4、button的第四個設定:
Select
方法會將按鈕設置為選中狀態,這通常會觸發按鈕的選中效果(如高亮設置等視覺效果)
? ? ? ? 將Screen Manager腳本掛載至Screen Canvas
? ? ? ? 將Screen Canvas物體掛載到New Game游戲欄的按鈕上,即點擊New Game欄時,進入游戲場景
設置游戲角色管理腳本?
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;namespace SG
{public class CharacterManger : MonoBehaviour{public static CharacterManger instance;[Header("NETWORK JOIN")][SerializeField] bool startGameAsClient;private void Awake(){if (instance == null){instance = this;}else{Destroy(gameObject);}}private void Start(){DontDestroyOnLoad(gameObject);}private void Update(){if (startGameAsClient){startGameAsClient = false;NetworkManager.Singleton.Shutdown();NetworkManager.Singleton.StartClient();}}}
}
[Header("NETWORK JOIN")] [SerializeField] bool startGameAsClient;
bool startGameAsClient;
:一個布爾變量,用于決定游戲啟動時是否作為客戶端加入游戲[Header("NETWORK JOIN")]
的作用是將下面的變量[SerializeField] bool startGameAsClient;
歸類到"NETWORK JOIN"這一部分
這樣在Unity編輯器中,這個變量會顯示在檢查器面板的"NETWORK JOIN"標題下。
if (startGameAsClient) {startGameAsClient = false;NetworkManager.Singleton.Shutdown();NetworkManager.Singleton.StartClient(); }
if (startGameAsClient)
:
檢查
startGameAsClient
是否為true
。如果是,表示需要以客戶端模式加入游戲。
startGameAsClient = false;
:
將
startGameAsClient
設置為false
,以確保這個邏輯只執行一次,避免重復觸發。
NetworkManager.Singleton.Shutdown();
:
調用
NetworkManager
的單例實例的Shutdown
方法。作用:關閉當前的網絡管理器,清理網絡狀態。
目的:確保在重新啟動客戶端連接之前,清除任何現有的網絡連接和狀態,避免沖突或資源泄漏。
NetworkManager.Singleton.StartClient();
:
調用
NetworkManager
的單例實例的StartClient
方法。作用:以客戶端模式啟動網絡連接,使游戲客戶端連接到服務器。?
?使動畫角色對應網絡連接
? ? ? ? 安裝了網絡插件后,為了讓場景角色也有網絡效應,我們要給物體加上該組件
? ? ? ? 將物體掛載到NetworkManager的Player Prefab上,但需要注意:不同場景下執行掛載操作產生的效果不同