目標:
- 本地多人畫面遊玩
- 設定 4 組外接搖桿做控制 (以 Xbox Controller 為主,但因手邊沒有,無法詳盡介紹)
- 四個角色都能被控制
- 畫面切割線
實際畫面:
分割四個畫面的設定
要分割四個畫面,等於是只要 4 個不同的攝影機進行控制,我們先看看一個攝影機的情況,如何調整為 1/4 的畫面,且保持在平面座標第二象限。
在攝影機的 Component 設定中,有個 Viewport Rect,這是一個 Component 參數,而且型別是 Rect,其中可以直接在 Inspector 中調整 x,y, 寬度比, 高度比,然後就會置中在如下畫面 (若是在遊戲起動時拖曳,會有殘影):
程式碼部分:
GameObject camera_1 = new GameObject(); camera_1.AddComponent<Camera>(); camera_1.GetComponent<Camera>().rect = new Rect(0,0.5f,0.5f,0.5f); camera_1.name = "Camera Player 1";
於是,這個攝影機就會在開始遊戲時,自己生產一個攝影機遊戲物件,然後預設調整其 Rect。
*此腳本(init.cs)請在 start 中寫入該程式,並且將腳本套用到一個空物件上。
加入至遊玩角色物件底下
我們期望在 Hierarchy 中可以把 Camera 變成跟 Player 之間的父子關係,因此套用 4 個攝影機分別到四個玩家座標上,然後把攝影機位置往後往上拉,目的是可以在 Player 移動的時候,原座標也會相同。
其中使用綁定的程式碼是將子物件的 transform 其中一參數 (transform.parent) 指定為父物件的 Transform 型別,因為一個子物件只會有一個父物件。
然後在子物件中欲想設定座標,請注意在繼承關係下的物件,座標會轉換本地座標 (local position),所以在 Inspector 上顯示的 transform position x,y,z 座標也會是 local position (本地座標),在設定遊戲物件座標時,要使用 transform.localPosition 而不是 transform.position。
程式碼部分(init.cs):
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Init : MonoBehaviour { public GameObject player1; public GameObject player2; public GameObject player3; public GameObject player4; // Use this for initialization void Start () { GameObject camera_1 = new GameObject(); camera_1.AddComponent<Camera>(); camera_1.GetComponent<Camera>().rect = new Rect(0,0.5f,0.5f,0.5f); camera_1.name = "Camera Player 1"; camera_1.transform.parent = player1.transform; //指定父物件是誰 camera_1.transform.Rotate(new Vector3(30,0,0)); //攝影機旋轉位置 camera_1.transform.localPosition = new Vector3(0,1.5f,-2); //攝影機位置向後看 GameObject camera_2 = new GameObject(); camera_2.AddComponent<Camera>(); camera_2.GetComponent<Camera>().rect = new Rect(0.5f,0.5f,0.5f,0.5f); camera_2.name = "Camera Player 2"; camera_2.transform.parent = player2.transform; camera_2.transform.Rotate(new Vector3(30,0,0)); camera_2.transform.localPosition = new Vector3(0,1.5f,-2); GameObject camera_3 = new GameObject(); camera_3.AddComponent<Camera>(); camera_3.GetComponent<Camera>().rect = new Rect(0.5f,0,0.5f,0.5f); camera_3.name = "Camera Player 3"; camera_3.transform.parent = player3.transform; camera_3.transform.Rotate(new Vector3(30,0,0)); camera_3.transform.localPosition = new Vector3(0,1.5f,-2); GameObject camera_4 = new GameObject(); camera_4.AddComponent<Camera>(); camera_4.GetComponent<Camera>().rect = new Rect(0,0,0.5f,0.5f); camera_4.name = "Camera Player 4"; camera_4.transform.parent = player4.transform; camera_4.transform.Rotate(new Vector3(30,0,0)); camera_4.transform.localPosition = new Vector3(0,1.5f,-2); } }
*此程式腳本尚未完整,請自行加入螢幕分割的程式。
玩家角色物件控制
在控制角色移動時,會碰到兩個問題:
- 多個控制器如何控制各自的不同物件
- 同一個腳本如何區分不同的物件進行控制
我們得解決第一個問題,事實上我們一般使角色在 x,y 座標下移動,使用 WASD 或上下左右的程式會像這樣:
void Update () { float x = Input.GetAxis("Horizontal"),y = Input.GetAxis("Vertical"); transform.Translate(x,y,0); }
而在 Input.GetAxis 中的字串,其實是 Unity 中 Input Setting 的參數設定,有 Horizontal, Vertical 兩個設定涵蓋了鍵盤中 WASD, 上下左右的定義。
功能選項位於 Edit -> Project Settings -> Input。
在功能中,你可以看到有 Horizontal, Vertical 這兩個設定,而下面的 Joy Num (如下圖)其實就是指 Joystick(可以想成是不同的搖桿控制器),只要指定到 N 個控制器,就可以區分玩家了。
如果要設定 4 個玩家,那就對預設的 Horizontal, Vertical 兩個參數,右鍵複製(如下圖):
複製後更改名稱,則就是在 Input.GetAxis 中需要的參數,這裡就複製 4 個 horizontal, 4 個 vertical 改為 player1x, player1y, player2x, player2y,.....
最好是能夠在 Component 中做選擇,會比較方便。
程式碼(PlayerControl.cs):
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerControl : MonoBehaviour { public enum playerType { player1, player2, player3, player4 }; public playerType playerNumber; // Use this for initialization void Start () { } // Update is called once per frame void Update () { float x = 0,y = 0; //for player 1 if(playerNumber.Equals(playerType.player1)){ x = Input.GetAxis("Player1x"); y = Input.GetAxis("Player1y"); } //for player 2 if(playerNumber.Equals(playerType.player2)){ x = Input.GetAxis("Player2x"); y = Input.GetAxis("Plater2y"); } transform.Translate(x,y,0); } }
*此腳本(PlayerControl.cs)請套用至各角色的 GameObject 中,然後請設定 Component 參數。
在螢幕畫分割線
在螢幕中做分割線有很多做法,在此只用最粗糙的方式完成:
程式碼(init.cs),請自行加入在 update(){} 結束之後。
void OnGUI(){ GUI.Box(new Rect(Screen.width / 2, 0, 1, Screen.height),""); GUI.Box(new Rect(0, Screen.height / 2, Screen.width, 1),""); }
Reference:
https://docs.unity3d.com/ScriptReference/Transform-localPosition.html
https://docs.unity3d.com/ScriptReference/GUI.Box.html
沒有留言:
張貼留言