[英]Find localPlayer when all players have same name
在將玩家引用到另一個對象的腳本時,Unity讓我很困惑。 我使用了幾種方法來引用localPlayer對象:
gameObject.Name
(從未使用過但它也不可靠) public GameObject Player;
在檢查器中拖放 (當播放器是預制件時面臨問題) public static [PlayerControllerClass] instance;
並設置instance = this
in void Start()
function。為了從另一個腳本訪問playerSpeed
,我做了PlayerControllerClass.instance.playerSpeed = 10;
是否有其他解決方案以適當的方式引用玩家。
注意:我知道我的問題可能與某個特定問題無關,但如果有人會提供幫助,我可以解釋一下。
Edit1:例如我想在
localPlayer
中找到localPlayer
,其中所有玩家具有相同的名稱,相同的標簽,但只有一個玩家是localPlayer。 我可以從其他腳本訪問localPlayer
嗎?編輯2:我接受的答案是我感覺最好的。我將使用在預覽
localPlayer
的score text
時提供的答案,方法是從一組玩家[localPlayer
]訪問它
你的問題直到編輯后才明確,然后我意識到這是一個網絡問題。
我需要在NetworkGame中找到localPlayer,其中所有玩家具有相同的名稱,相同的標簽但只有一個玩家是localPlayer我可以從另一個腳本訪問localPlayer嗎?
你可以找到使用NetworkConnection.playerControllers
玩家,它重新獲得PlayerController
List然后循環它並檢查它是否有效。 之后,從中獲取NetworkBehaviour,檢查isLocalPlayer屬性。 真的是這樣的。
像這樣的東西:
GameObject FindLocalNetworkPlayer()
{
NetworkManager networkManager = NetworkManager.singleton;
List<PlayerController> pc = networkManager.client.connection.playerControllers;
for (int i = 0; i < pc.Count; i++)
{
GameObject obj = pc[i].gameObject;
NetworkBehaviour netBev = obj.GetComponent<NetworkBehaviour>();
if (pc[i].IsValid && netBev != null && netBev.isLocalPlayer)
{
return pc[i].gameObject;
}
}
return null;
}
如果您將NetworkIdentity
附加到播放器而不是NetworkBehaviour
,只需獲取NetworkIdentity
並檢查isLocalPlayer
屬性。 您還可以找到isLocalPlayer
然后檢查NetworkIdentity
和isLocalPlayer
屬性。
if (obj.GetComponent<NetworkIdentity>().isLocalPlayer){}
您可能需要的其他有用的玩家操作:
找到所有玩家 :
List<GameObject> ListPlayers()
{
NetworkManager networkManager = NetworkManager.singleton;
List<PlayerController> pc = networkManager.client.connection.playerControllers;
List<GameObject> players = new List<GameObject>();
for (int i = 0; i < pc.Count; i++)
{
if (pc[i].IsValid)
players.Add(pc[i].gameObject);
}
return players;
}
按名稱查找玩家(也可以按標簽或圖層更改) :
GameObject FindNetworkPlayer(string name)
{
NetworkManager networkManager = NetworkManager.singleton;
List<PlayerController> pc = networkManager.client.connection.playerControllers;
for (int i = 0; i < pc.Count; i++)
{
if ((pc[i].IsValid) && (name == pc[i].gameObject.name))
return pc[i].gameObject;
}
return null;
}
編輯前的舊答案:
是否有其他解決方案以適當的方式引用玩家。
是的,你會發現與游戲對象GameObject.Find
,在此之后,你可以使用GetComponent
函數來獲得被連接到它的腳本。
我注意到你提到你想在場景中引用預制件。 預制件和已經存在的對象之間存在差異,它們都有不同的方式來引用它們。
以下是場景中對象的示例。 您可以在“ 層次結構”選項卡中看到它們:
讓我們按名稱引用“Canvas”GameObject:
GameObject canvasObj = GameObject.Find("Canvas");
讓我們將Canvas
腳本附件引用到“Canvas”GameObject:
GameObject canvasObj = GameObject.Find("Canvas");
Canvas canvas = canvasObj.GetComponent<Canvas>();
預制件:
以下是“項目”選項卡中預制件的示例:
將預制件放在名為“Resources”的文件夾中。 您必須這樣才能使用Resources
API引用它們。
讓我們參考“Capsule”預制游戲對象:
GameObject prefab = Resources.Load<GameObject>("Capsule");
要使用它,您必須實例化它:
GameObject instance = Instantiate(prefab);
在實例化后,您只能在預制件上獲取組件:
CapsuleCollider cc = instance.GetComponent<CapsuleCollider>();
我推薦Singleton模式。 我在幾乎所有的Unity項目中都實現了它,只用於只有1個類的對象,但它是一個單獨的行為。
using UnityEngine;
public abstract class SingletonBehaviour<T> : MonoBehaviour where T : MonoBehaviour
{
public bool dontDestroyOnLoad = true;
private bool isInitialized = false;
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<T>();
if (instance == null)
{
var obj = new GameObject
{
name = typeof(T).Name
};
instance = obj.AddComponent<T>();
}
}
return instance;
}
}
protected virtual void Awake()
{
if (instance == null)
{
instance = this as T;
if (dontDestroyOnLoad)
{
DontDestroyOnLoad(this.transform.root.gameObject);
}
}
else if (instance != this)
{
Destroy(gameObject);
}
}
private void OnEnable()
{
if (!isInitialized)
{
OnInitialize();
isInitialized = true;
}
}
public abstract void OnInitialize();
}
然后,您可以創建一個類,如下所示:
public class MyClass : SingletonBehaviour<MyClass>
{
public void OnInitialize()
{
// You can use this instead of awake or start
}
public void DoStuff();
}
並稱之為:
MyClass.Instance.DoStuff()
當我需要多個引用時,我總是尋求使用GameObject.FindGameObjectsWithTag;當我只需要對系統中可用的特定GameObject的一個引用時,我一直在尋找GameObject.FindWithTag 。
要在所述GameObject上引用腳本(使用上面的API參考找到),您只需使用GameObject.GetComponent API引用中所述的``。
一個完整的例子是:
PlayerA
例如PlayerA
。 GameObject player = GameObject.FindWithTag("PlayerA");
PlayerScript playerScript = player.GetComponent<PlayerScript>();
我希望這有幫助,如果您需要進一步澄清,我將非常樂意提供幫助。
編輯:另一種解決方案:
關注:50或x
數量的玩家太平凡無法分配標簽。
解決方案:如果您有一組50名玩家:
ParentPlayer
分配一個標簽,例如ParentPlayer
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.