Unity 多人連線遊戲製作

本教學使用 Unity 製作多人連線射擊遊戲,玩家使用各種武器將對手擊倒獲得勝利。

匯入 PUN 2 - FREE 資源包,匯入 Toon Soldiers 資源包,或自行製作遊戲需要的角色。

開啟 PUN Wizard 對話框,從 Input AppId 輸入網頁取得的 AppId 後按下 Setup Project 按鈕,再按 Close 關閉對話框。

PUN Demo Hub 提供了多人連線遊戲的範例,建議可發佈遊戲後多開視窗測試看看 Photon 連線功能。

製作遊戲角色活動的場景地板,建立 "Floor" 標籤並指定給地面,稍後用於判定遊戲角色在地面與是否可跳躍。

開啟 [ Toon_Soldiers > ToonSoldiers_2 > prefabs ] 資料夾將 ToonSoldiers_infantry 拖曳到場景,並移到原點的位置。

建立一個動畫控制器並重新命名為 "Player Animator Controller" ,開啟後新增 Speed (Float) 與 Rotate (Float) 參數。

開啟 [ Toon_Soldiers > ToonSoldiers_2 > animation > Infantry ] 資料夾,將待機、行走、跳躍等動作加入動畫控制器。

...

建立動作之間的過渡:

選取動畫過渡的箭頭,設定 Speed Grater 0.1

選取動畫過渡的箭頭,設定 Speed Less 0.1

 

選取玩家角色,將此角色重新命名為 “Player" ,附加 Rigidbody 剛體元件,勾選約束 Constraints Freeze Rotation XYZ 避免旋轉。

增加 Capsule Collider 膠囊碰撞器,調整中心位置與高度。

建立一個 C# 腳本命名為 "PlayerController" 並套用到 Player 玩家角色,程式碼如下:

目前只有基本的遊戲角色移動操作,按下 Play 測試遊戲確認目前沒問題。

選取 Player 玩家角色套用 Photon View 與 Photon Transform View 腳本元件。

建立 Resources 資料夾,將場景中的 Player 玩家角色拖曳到此資料夾,選擇 Original Prefab 製作預製物件。

建立 C# 腳本並命名為 "GameManager" 建立空物件並套用此腳本。

刪除場景中的 Player 玩家角色,儲存場景。

建立一個新場景,用於製作玩家登入畫面。

在此場景執行 [ GameObject > UI > Input Field] 建立文字欄位,並移到適當位置。

執行 [ GameObject > UI > Button ] 建立登入按鈕,移到適當位置,設定按鈕文字。

建立 C# 腳本並命名為 "NetworkManager" ,程式碼如下:

建立空物件命名為 "NetworkManager" 並將剛建立的腳本套用到此物件,透過 Inspector 指定 Input Field 與 Button 按鈕。

選取遊戲畫面的玩家名稱欄位, On Value Changed () + "NetworkManager" 再選取 "NetworkManager.OnNameFieldEdited".

注意!不是 NetworkManager.OnNameFieldEdited(String) 別選錯!

選取遊戲畫面的登入遊戲按鈕, On Click () + "NetworkManager" and select "NetworkManager.OnLoginButtonClicked".

儲存場景並將目前的遊戲場景加入 Scenes In Build 。

遊戲開發階段可增加自動登入功能,測試連線功能時,就不需要每次再切換回到登入場景。

儲存場景並發佈遊戲測試,玩家登入後會控制到場景上的所有的角色,必須判斷是否本地端的玩家以解決目前的問題。

開啟 PlayerController 腳本,修改程式碼:

透過以上修改即可解決 Photon 多人連線遊戲的遊戲角色控制問題。

 

增加玩家角色的跳躍動作

目前只有行走動作,而且連線時動畫不同步,玩家只會看到自已角色的動作,畫面上的其他玩家只會飄移。

加入跳躍動作,開啟 Player Animator Controller 動畫控制器,加入 Infantry_jump_1_start 動作並新增動畫過渡。

選取「從待機到跳躍」的箭頭,取消 Has Exit Time 設定 Conditions 在 Jump 觸發時過渡到下個動作狀態。

選取「從走路到跳躍」的箭頭,取消 Has Exit Time 設定 Conditions 在 Jump 觸發時過渡到下個動作狀態。

開啟 PlayerController.cs 腳本,修改程式碼來加入跳躍動作:

接著解決動畫的同步問題,選取遊戲角色的預製物件,附加 Photon Animator View 腳本元件。

將 Synchronize Parameters 同步參數下,設定 Layer 0 = Continuous 進行動作狀態的持續同步。

實際上 Jump 跳躍動作也需要同步,但如果 Jump 使用 Trigger 觸發方式,將會出現警告訊息!

When using triggers, make sure this component is last in the stack. If you still experience issues, implement triggers as a regular RPC or in custom IPunObservable component instead.

(上圖)所以這邊的 Jump 維持 Disabled

修改程式碼:

注意! 參數增加減少時,建議回到 Photon Animator View 確認設定是否被重置。

 

增加玩家角色的後退動作

將 Infantry_combat_idle 動作拖曳到 Player Animator Controller 動畫控制器。

新增從待機到後退動作的過渡箭頭(滑鼠右鍵 Make Transition)與後退到待機的回去箭頭。

選取「從待機到後退」的箭頭,取消 Has Exit Time 設定 Conditions 在 Speed Less -0.1 時過渡到後退的動作。

選取「從後退到待機」的箭頭,取消 Has Exit Time 設定 Conditions 在 Speed Greater -0.1 時過渡到待機的動作。

 

增加遊戲角色的跑步動作

動畫控制器新增 Run 參數

修改 PlayerController 腳本,增加遊戲角色跑步的程式碼

選取從走路到跑步的箭頭,取消 Has Exit Time 設定 Conditions 在 Run = true 時過渡到下個動作狀態。

選取從跑步到走路的箭頭,取消 Has Exit Time 設定 Conditions 在 Run = false 時過渡到下個動作狀態。

選取從倒退到向後跑的箭頭,取消 Has Exit Time 設定 Conditions 在 Run = true 時過渡到下個動作狀態。

選取從向後跑到倒退的箭頭,取消 Has Exit Time 設定 Conditions 在 Run = false 時過渡到下個動作狀態。

 

增加遊戲角色的射擊功能

開啟 Resources 資料夾,將 Player 玩家角色拖曳到場景再進行編輯。

選取玩家角色手上的武器,從 Hierarchy 視窗滑鼠右鍵執行 3D Object > Cutb 建立方塊物件。

此物件將是用於發射子彈的槍口,重新命名為 "Muzzle",稍後可關閉 Mesh Renderer 隱藏物件。

縮小方塊並移到槍口位置,刪除 Box Collider 方塊碰撞器。旋轉方向,讓 Z 軸藍色箭頭朝子彈前進的方塊。

 

製作子彈

建立一個空物件並命名為 ”Bullet" 移到原點位置。

Bullet 套用 Rigidbody 剛體元件與 Capsule Collider 膠囊碰撞器。

Bullet 套用 Photon View 元件與 Photon Transform View 元件。

Bulet 滑鼠右鍵執行 3D Object > Capsule 建立一個膠囊子物件。

膠囊 X 軸旋轉 90 度,縮小到 0.1。

刪除膠囊子物件的碰撞器,再為上層的 Bullet 建立膠囊碰撞器。

新增一個 Bullet 標籤並套用到 Bullet 子彈物件。(現已有 Floor 標籤)

Bullet 套用 Photon View, Photon Transform View腳本元件。★

 

建立一個 C# 腳本並命名為 "Bullet" ,使用 Rigidbody.AddRelativeForce 推動子彈,並於指定時間後刪除物件。

將 Bullet 腳本套用到 Bullet 子彈物件,設定推力 Thrust = 10

按下 Play 測試子彈功能,可套用 Trail Renderer 元件顯示飛行軌跡。

測試完成若無問題,將 Bullet 拖曳到 Resources 資料夾轉成預製物件,刪除場景中的 Bullet 子彈物件。

 

開啟 PlayerController 腳本元件,修改程式碼加入開槍射擊功能:

 

開啟 Player Animator Controller 動畫控制器,加入對應的射擊動作。

本例使用 [ Toon_Soldiers > ToonSoldiers_2 > animation > Infantry ] 資料夾的 infantry_combat_shoot 動作。

使用動畫層可以製作較複雜的動畫,無論是待機、前進、後退、跑步時,上半身都可做射擊動作。

按 + 新增動畫層並且命名為 Upper body

接著在 Project 視窗滑鼠右鍵執行 Create Avatar Mask ,命名為 Player Avatar Mask 。★

選取後透過 Inspector 進行設定。展開 Humanoid 將下半身變成紅色,表示動畫在下半身將被遮蔽不受影響。

回到動畫編輯器切換到 Parameters 分頁按 + 新增 Shoot (Trigger) 參數。新增 Burst (Trigger) 參數。

...

動畫編輯器切換到 Layers 分頁選擇 Upper body

設定權重 Weight = 1 完全控制,將 Mask 遮罩選擇剛建立的 Player Avatar Mask 遮罩。★

設定 Bliding = Additive 混合動作。★

在此動畫層執行 Create State > Empty 建立空狀態,再將攻擊動作拖曳進來。

建立狀態之間的過渡★,並透過 Inspector 設定過渡的條件。★★

 

修改攝影機

製作 Unity 多人連線遊戲的攝影機與單機遊戲的差異,場景上可能同時有多個玩家角色,攝影機需要設定跟隨的目標。

使用 Standard Assets 的 MultipurposeCameraRig 攝影機,匯入 Standard Assets 資源包的 Cameras、CrossPlatformInput 資源。

開啟多人連線的主要遊戲場景,選取 預設的Main Camera 攝影機,停用或刪除此攝影機。

開啟 [ Standard Assets > Cameras > Prefabs ] 資料夾,將 MultipurposeCameraRig 拖曳到場景。

此攝影機可以自動追隨玩家移動,但需要修改為多人連線遊戲使用,開啟 GameManager.cs 腳本,修改程式碼:

按下 Play 測試遊戲,本地端的玩家角色動態生成後,攝影機將會跟隨本地端玩家,而不是其他玩家。

若出現 UnassignedReferenceException: The variable target of CameraController has not been assigned. 錯誤訊息,無需理會。

 

製作血條

目前完成的進度是 Unity 多人連線的射擊遊戲,接著製作玩家的血條。

從 Hierarchy 視窗選取玩家角色,滑鼠右鍵執行 Create > UI > Canvas 。

建立一個 Text 文字用於顯示玩家名稱,調整到適當大小與位置,設定 Horizontal Overflow = Overflow 讓字數較多時也不換行。

建立一個 Slider 滑桿,將滑桿 Slider > Handle Slide Area 子物件停用或刪除。原本的 Slide 滑桿將會變成接近血條的外觀。

將滑桿 Slider > Fill Area 子物件的 Left 與 Right 設定為 0 。

將滑桿 Slider > Fill Area > Fill 子物件的 Width 設定為 0 。

建立 C# 腳本並命名為 "PlayerStats" 用於儲存連線玩家的狀態,此腳本的程式較多,請點擊圖片開啟連結。

將 PlayerStats 套用到玩家角色的預製物件。注意!不是場景中的遊戲角色。

將此預製物件下的玩家名稱、血條、最大 HP 數值、布偶預製物件設定到對應欄位。

 

修改 PlayerController 腳本,增加 PhotonView 與 playerStats 避免玩家角色倒地後仍被控制的問題。

 

修改 Bullet.cs 腳本,讓子彈擊中遊戲角色時執行扣血的功能。

 

修改 GameManager 腳本,讓玩家進入房間時進行資料同步更新。

修改 PlayerStats 腳本,增加被擊倒時的動作。廣播通知房間內的其他玩家進行資料同步更新。