[英]Find localPlayer when all players have same name
Unity makes me confused when it comes to referencing players to another object's script. 在将玩家引用到另一个对象的脚本时,Unity让我很困惑。 I have used several ways to reference a localPlayer object:
我使用了几种方法来引用localPlayer对象:
gameObject.Name
(never used it but it is also not reliable) gameObject.Name
(从未使用过但它也不可靠) public GameObject Player;
public GameObject Player;
in the inspector Drag and Drop (face problems when the player is a prefab) public static [PlayerControllerClass] instance;
public static [PlayerControllerClass] instance;
and setting instance = this
in void Start()
function.In order to access playerSpeed
from another script I do PlayerControllerClass.instance.playerSpeed = 10;
instance = this
in void Start()
function。为了从另一个脚本访问playerSpeed
,我做了PlayerControllerClass.instance.playerSpeed = 10;
Is there other solutions for referencing players in a proper way. 是否有其他解决方案以适当的方式引用玩家。
Note: I know my question might not be relating to a specific problem but I can explain more if somebody will help. 注意:我知道我的问题可能与某个特定问题无关,但如果有人会提供帮助,我可以解释一下。
Edit1: for example I want to find
localPlayer
in a NetworkGame where all players have same name, same tag but only one player is a localPlayer.Edit1:例如我想在
localPlayer
中找到localPlayer
,其中所有玩家具有相同的名称,相同的标签,但只有一个玩家是localPlayer。 Can I access thelocalPlayer
from another script?我可以从其他脚本访问
localPlayer
吗?Edit2 : The answer I accepted is what I felt the best.I will use the answer provided in previewing
score text
of thelocalPlayer
by accessing it from a set of players [localPlayer
]编辑2:我接受的答案是我感觉最好的。我将使用在预览
localPlayer
的score text
时提供的答案,方法是从一组玩家[localPlayer
]访问它
Your question wasn't clear until your edit then I realized that this is a networking question. 你的问题直到编辑后才明确,然后我意识到这是一个网络问题。
I need to find localPlayer in a NetworkGame where all players have same name, same tag but only one player is a localPlayer can I access the localPlayer from another script?
我需要在NetworkGame中找到localPlayer,其中所有玩家具有相同的名称,相同的标签但只有一个玩家是localPlayer我可以从另一个脚本访问localPlayer吗?
You can find players with NetworkConnection.playerControllers
which retruens List of PlayerController
then loop over it and check if it is valid. 你可以找到使用
NetworkConnection.playerControllers
玩家,它重新获得PlayerController
List然后循环它并检查它是否有效。 After that, get NetworkBehaviour from it check the isLocalPlayer property. 之后,从中获取NetworkBehaviour,检查isLocalPlayer属性。 That's really it.
真的是这样的。
Something like this: 像这样的东西:
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;
}
If you have NetworkIdentity
attached to the player instead of NetworkBehaviour
, just get the NetworkIdentity
and check the isLocalPlayer
property. 如果您将
NetworkIdentity
附加到播放器而不是NetworkBehaviour
,只需获取NetworkIdentity
并检查isLocalPlayer
属性。 You can also find the GameObject then check the NetworkIdentity
and the isLocalPlayer
property. 您还可以找到
isLocalPlayer
然后检查NetworkIdentity
和isLocalPlayer
属性。
if (obj.GetComponent<NetworkIdentity>().isLocalPlayer){}
Other useful player operation you may need: 您可能需要的其他有用的玩家操作:
Find all players : 找到所有玩家 :
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;
}
Find player by name(Can also be changed to by tag or layer) : 按名称查找玩家(也可以按标签或图层更改) :
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;
}
OLD answer before your edit: 编辑前的旧答案:
Is there other solutions for referencing players in a proper way.
是否有其他解决方案以适当的方式引用玩家。
Yes, you Find the GameObject with GameObject.Find
, after this, you can use the GetComponent
function to get the script that is attached to it. 是的,你会发现与游戏对象
GameObject.Find
,在此之后,你可以使用GetComponent
函数来获得被连接到它的脚本。
I notice you mentioned you want to reference prefabs in the scene too. 我注意到你提到你想在场景中引用预制件。 There is a difference between prefabs and objects already the scene and they both have different ways to reference them.
预制件和已经存在的对象之间存在差异,它们都有不同的方式来引用它们。
Here is an example of Objects in the Scene already. 以下是场景中对象的示例。 You can see them in the Hierarchy tab:
您可以在“ 层次结构”选项卡中看到它们:
Let's reference the "Canvas" GameObject by name : 让我们按名称引用“Canvas”GameObject:
GameObject canvasObj = GameObject.Find("Canvas");
Let's reference the Canvas
script attache to the "Canvas" GameObject: 让我们将
Canvas
脚本附件引用到“Canvas”GameObject:
GameObject canvasObj = GameObject.Find("Canvas");
Canvas canvas = canvasObj.GetComponent<Canvas>();
Prefabs: 预制件:
Here is an example of prefabs in the Project tab: 以下是“项目”选项卡中预制件的示例:
Put the prefabs in a folder named "Resources". 将预制件放在名为“Resources”的文件夹中。 You must so that you can reference them with the
Resources
API. 您必须这样才能使用
Resources
API引用它们。
Let's reference the "Capsule" prefab GameObject: 让我们参考“Capsule”预制游戏对象:
GameObject prefab = Resources.Load<GameObject>("Capsule");
To use it, you have to instantiate it: 要使用它,您必须实例化它:
GameObject instance = Instantiate(prefab);
You can only get components on prefabs after when they are instantiated: 在实例化后,您只能在预制件上获取组件:
CapsuleCollider cc = instance.GetComponent<CapsuleCollider>();
I recommend the Singleton Pattern. 我推荐Singleton模式。 I implement it in almost all my Unity Projects for objects that only have 1 class, yet is a monobehaviour.
我在几乎所有的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();
}
You can then create a class like so: 然后,您可以创建一个类,如下所示:
public class MyClass : SingletonBehaviour<MyClass>
{
public void OnInitialize()
{
// You can use this instead of awake or start
}
public void DoStuff();
}
And call it like so: 并称之为:
MyClass.Instance.DoStuff()
I have always sought usage of GameObject.FindGameObjectsWithTag when I need multiple references or else GameObject.FindWithTag when I need just the one reference to a specific GameObject available in the system. 当我需要多个引用时,我总是寻求使用GameObject.FindGameObjectsWithTag;当我只需要对系统中可用的特定GameObject的一个引用时,我一直在寻找GameObject.FindWithTag 。
To reference a script on said GameObject (found using the API reference above), you simply use `` as described in GameObject.GetComponent API reference. 要在所述GameObject上引用脚本(使用上面的API参考找到),您只需使用GameObject.GetComponent API引用中所述的``。
A complete example would be: 一个完整的例子是:
PlayerA
. PlayerA
例如PlayerA
。 GameObject player = GameObject.FindWithTag("PlayerA");
PlayerScript playerScript = player.GetComponent<PlayerScript>();
I hope this helps and should you require further clarification, I'll be more than happy to help. 我希望这有帮助,如果您需要进一步澄清,我将非常乐意提供帮助。
EDIT: Another solution: 编辑:另一种解决方案:
Concern: 50 or x
amount of players would be too mundane to assign tags. 关注:50或
x
数量的玩家太平凡无法分配标签。
Solution: If you have a set of 50 players: 解决方案:如果您有一组50名玩家:
ParentPlayer
ParentPlayer
分配一个标签,例如ParentPlayer
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.