[英]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.