如何:获取游戏对象的实例

How to: Get instance of gameObject

希望获取此游戏对象的实例,以便我可以成功使用 .enabled 将其隐藏在场景中。

PlayPortalLoginButton loginButton = gameObject.GetComponent<PlayPortalLoginButton>();

对 C# 相当陌生,我相信我已经接近通过上面的代码实现我的目标。需要改变什么?想了解如何正确执行此操作。

GameObject button;
void Start() {
    button = GameObject.Find ("yourButtom");
}
void SomeEvent() {
    button.SetActive(false);   
}

我觉得对你有帮助

有多种方法可以访问脚本中的游戏对象,具体取决于您尝试获取的游戏对象。

如果您尝试访问行为脚本中行为的游戏对象,那么只需使用 gameObject 就足够了,因为这是行为所附加的游戏对象。

访问附加到另一个游戏对象的脚本可能很棘手。对于MainMenu这样的场景,给它一个public引用作为例子没有错:

public PlayPortalLoginButton loginButton;

void setLoginState(bool activate) {
    loginButton.enabled = activate;
}

在此示例中,您只需将带有 PlayPortalLoginButton 脚本的游戏对象拖放到管理器脚本上,该脚本将控制它是否启用。

如果您需要更模块化的方法,例如在游戏场景中,您在 运行 时间填充对象,您可以采用的方法是:

PlayPortalLoginButton loginButton;

void setLoginState(bool activate) {
    if(loginButton == null)
    {
        loginButton = FindObjectOfType<PlayPortalLoginButton>();
    }
    // Requires the correct version of .net otherwise you can reuse the check above...
    loginButton?.enabled = activate;
}

在上面的脚本中如果你需要loginButton的gameObject,现在你可以通过loginButton.gameObject访问它。

还有一些您可以使用的示例和其他方法,但我觉得如果是菜单,以上内容应该足够了。

我还会提到我避免使用 GameObject.FindGameObject.FindGameObjectsWithTag 的示例,因为它们更容易出错。它们只有在您的名称或标签被正确标记时才会起作用,如果您出于任何原因重命名它们,那么您的脚本将无法找到该对象,这可能会导致故障排除问题。

使用 FindObjectOfType,您不太可能出现错误,如果您删除该脚本类型,这些脚本将填充一个错误,指示该脚本不再存在。重构时,如果您右键单击行为名称并使用重命名选项,它将自动更新整个代码中对脚本的引用。

这是您可以在场景中的 GameObject 上找到组件的一种方法,其中 "PortalLoginButton" 是编辑器中看到的 GameObject 的名称:

var loginButton = GameObject.Find("PortalLoginButton");
loginButton.enabled = false;

然而,GameObject.Find("...") 搜索场景中每个 GameObject 的名称,这通常不是引用 GameObject 的最佳方式,因为它不是很有效。 因此请确保不要在 Update() 函数中使用 GameObject.Find("...") 或类似的函数调用,因为它会执行每一帧并减慢您的游戏速度。如果在游戏 运行 时未实例化 GameObject,通常最好对脚本中使用的任何 GameObjectComponent 进行全局引用,然后drag-and-drop GameObjectComponent 你要找的字段在编辑器中。或者,您可以在 Start()Awake() 函数中使用 GameObject.Find("...") 来存储对您要查找的 GameObject 的引用,以便搜索仅在开始你的游戏。

这是一个如何在全局字段中存储引用的示例(它将显示在编辑器中,您可以将 drag-and-drop 和 GameObject 放入其中)。使用 public 字段与私有字段之间的区别在评论中进行了说明(您可以决定使用 public 或私有字段):

// By default, private fields are not viewable in the editor,
// but the [SerializeField] attribute, placed before
// the field declaration, allows them to be visible.
[SerializeField]
private GameObject loginButtonPrivateReference;
// If you need to access loginButton from another script, 
// you can make it a public field.
// Public fields are viewable in the editor by default.
public GameObject loginButtonPublicReference;

下面是如何在 Awake() 函数中使用 GameObject.Find("...") 的示例:

private GameObject loginButton;

private void Awake() {
    loginButton = GameObject.Find("PortalLoginButton");
}

如果您需要按类型或标签名称在场景中搜索 GameObjects,请参阅 GameObject 文档 here 了解更多信息。按类型搜索效率较低,而按标签搜索比按名称搜索更有效,因为类型搜索检查每个 GameObject 上的每个组件,而标签搜索仅搜索有组织的 GameObject 子集。