简体   繁体   English

当所有玩家具有相同名称时,找到localPlayer

[英]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对象:

  1. Comparing Tags(not so good in some situations) 比较标签(在某些情况下不太好)
  2. gameObject.Name (never used it but it is also not reliable) gameObject.Name (从未使用过但它也不可靠)
  3. Assigning public GameObject Player; 分配public GameObject Player; in the inspector Drag and Drop (face problems when the player is a prefab) 在检查器中拖放 (当播放器是预制件时面临问题)
  4. Making 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 the localPlayer 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 the localPlayer by accessing it from a set of players [ localPlayer ] 编辑2:我接受的答案是我感觉最好的。我将使用在预览localPlayerscore 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然后检查NetworkIdentityisLocalPlayer属性。

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: 一个完整的例子是:

  1. Assign a tag to your Player GameObject eg PlayerA . 将标记分配给您的Player PlayerA例如PlayerA
  2. GameObject player = GameObject.FindWithTag("PlayerA");
  3. 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名玩家:

  1. I would group them under a parent GameObject. 我会将它们分组在父GameObject下。
  2. Assign the parent GameObject a tag eg ParentPlayer 为父ParentPlayer分配一个标签,例如ParentPlayer
  3. Use the GetComponentsInChildren reference. 使用GetComponentsInChildren引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当所有节点都具有相同的名称时,如何获取特定的节点值? - How to get particular node values when all nodes have same name? 当我使用 AutoMapper 时,如果这些属性具有相同的名称,我是否需要明确地编写所有属性? - Do I need to write all the properties explicitly when I am using AutoMapper, if these properties have the same name? LocalPlayer的子对象不是localplayer吗? - Child Objects of LocalPlayer is not localplayer? 获取球员姓名和得分 - Get the players name and score 当项目具有相同的名称时,筛选出最旧的项目 - Filter out oldest item when items have the same name 两个类同名时如何设置默认类 - How to set the default class when two classes have the same name 当多个块具有相同名称时搜索特定块 - Searching for a specific block when multiple blocks have the same name 当类和命名空间同名时区分类和命名空间 - Differentiating class and namespace when class and namespace have the same name NHibernate DuplicateMappingException 当两个类具有相同的名称但不同的命名空间时 - NHibernate DuplicateMappingException when two classes have the same name but different namespaces 当所有记录具有相同的值时,如何在linq中发生OrderBy? - How OrderBy happens in linq when all the records have the same value?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM