首页 > 解决方案 > 未找到跨脚本变量

问题描述

我知道这是你可以在 C# 中做的最简单的事情之一,但无论我做什么总是有错误。我正在制作一个 UI,您可以在其中单击并更改网格大小(我的建筑技工的)。它的默认值为 at 2.5,我想访问yourGridSize位于脚本上的变量GroundPlacementController。试图访问它的脚本称为GridChangerScript. 我得到的唯一错误是,GridChangerScript每当我调用变量时,它都会说它无法识别它。

继承人GroundPlacementController(缩短)

using UnityEngine;
using UnityEngine.AI;

public class GroundPlacementController : MonoBehaviour
{
    [SerializeField]   
    public float yourGridSize = 2.5f;

还有这里GridChangerScript

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GridChanger : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        GameObject gridChanger = GameObject.Find("GridChanger");
        GroundPlacementController groundPlacementController = gridChanger.GetComponent<GroundPlacementController>();
        float yourGridSize = 10f;
    }

    // Update is called once per frame
    void Update()
    {

    }
}

标签: unity3dglobal-variables

解决方案


而不是创建一个新的局部变量

float yourGridSize = 10f;

您必须访问该实例引用的值,例如

groundPlacementController.yourGridSize = 10.0f;

只是要确定

GameObject gridChanger = GameObject.Find("GridChanger");

在名为GridChanger... 的脚本中调用是否有可能两个组件都附加到同一个游戏对象?

在这种情况下,您可以这样做

var groundPlacementController = GetComponent<GroundPlacementController>();

我们刚刚发现问题还在于您在同一GameObject.

一般来说,Unity 并不是为了在同一个对象上多次使用相同的组件而设计的。正如您在评论中注意到的那样,GetComponent总是只会获得该类型的第一个组件。此外,如果您想在 UnityEvents(例如组件)中引用它们,onClickButton始终只能访问组件的第一次遇到。正确的设置是为该类型的每个实例设置一个子 GameObject。

但是,有一些解决方法。

例如,您可以使用GetComponentsInChildren在该游戏对象或其任何子对象上获取该类型的所有组件(递归)

GameObject gridChanger = GameObject.Find("GridChanger");

// Optionally you can pass in a true to also find inactive or disabled components
GroundPlacementController[] groundPlacementControllers = gridChanger.GetComponentsInChildren<GroundPlacementController>();

或者,如果这些是您可以使用的整个场景中唯一出现的该类型FindObjectsOfType(仅活动和可结束组件)

GroundPlacementController[] groundPlacementControllers = FindObjectsOfType<GroundPlacementController>();

而不是设置他们所有的yourGridSize迭代

foreach(var groundPlacementController in groundPlacementControllers)
{
    groundPlacementController.yourGridSize = 10.0f;
}

更新

因为您还想先读出某个文本

GroundPlacementController[] groundPlacementControllers = FindObjectsOfType<GroundPlacementController>();

foreach(var groundPlacementController in groundPlacementControllers)
{
    // get the childs text
    var childText = groundPlacementController.GetComponentInChildren<Text>(true);

    // Convert the text to float
    float textValue = float.TryParse(childText.text, out textValue ? textValue : 0.0f;
    groundPlacementController.yourGridSize = textValue;
}

笔记:

  • 对于 apublic您不需要添加[SerializeField],因为public字段会自动序列化。
  • 你应该删除空的 MonoBehaviour 事件,比如你的Update. 即使它们是空的,它们也会被 Unity 调用,从而导致不必要的开销。

推荐阅读