Переменная перекрестного скрипта не найдена

#unity3d #global-variables

#unity3d #глобальные переменные

Вопрос:

Я знаю, что это одна из самых простых вещей, которые вы можете сделать в C #, но что бы я ни делал, всегда возникает ошибка. Я создаю пользовательский интерфейс, в котором вы можете щелкнуть и изменить размер сетки (моего строительного механика). Его значение по умолчанию равно at 2.5 , и я хочу получить доступ к переменной yourGridSize , которая находится в скрипте GroundPlacementController . Вызывается скрипт , который пытается получить к нему доступ GridChangerScript . Единственная ошибка, которую я получаю, — это in GridChangerScript , и всякий раз, когда я вызываю переменную, она говорит, что не распознает ее.

Heres 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()
    {

    }
}
 

Комментарии:

1. Куда вы звонили?

2. @MaifeeUlAsad Я попытался изменить yourGridSize в функции обновления, но это выдало мне ту же ошибку

3. Отредактируйте и опубликуйте эту часть кода, пожалуйста

Ответ №1:

Вместо создания новой локальной переменной

 float yourGridSize = 10f;
 

вы должны получить доступ к значению этой ссылки на экземпляр, например

 groundPlacementController.yourGridSize = 10.0f;
 

Просто чтобы быть уверенным

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

вызывается в вызываемом скрипте GridChanger … возможно ли, что оба компонента в любом случае подключены к одному и тому же GameObject?

Из этого случая вы могли бы просто сделать

 var groundPlacementController = GetComponent<GroundPlacementController>();
 

Мы только что выяснили, что проблема также заключается в том, что у вас есть этот компонент несколько раз на одном и том же GameObject .

В общем, Unity на самом деле не предназначен для использования одного и того же компонента несколько раз на одном и том же объекте. Как вы заметили, например, в комментариях GetComponent всегда будет только первый компонент этого типа. Кроме того, если вы хотите ссылаться на них в UnityEvents (например onClick Button , компонента), вы всегда можете получить доступ только к первой встрече компонента. Правильная настройка состояла бы в том, чтобы иметь один дочерний GameObject для каждого экземпляра этого типа.

Однако для этого есть обходные пути.

Вы можете, например, использовать GetComponentsInChildren для получения всех компонентов этого типа в этом GameObject или любом из его дочерних элементов (рекурсивно)

 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;
}
 

Примечания:

  • Для a public вам не нужно добавлять [SerializeField] , так public как поля сериализуются автоматически.
  • вы должны удалить пустые события MonoBehaviour, подобные вашему Update . Даже если они пусты, они вызываются Unity, вызывая ненужные накладные расходы.

Комментарии:

1. это работает, но похоже, что переменная вызывается только в GridChangerScript, когда ее необходимо изменить в GroundPlacementController. Я имею в виду, что yourGridSize изменяется в скрипте GridChangerScript, а не в groundPlacementController, поэтому это вообще не влияет на размещение.

2. Нет, вы называете это так, как будто groundPlacementController.yourGridSize = 10.0f; это определенно меняет то GroundPlacementController GridChanger , у которого даже нет поля yourGridSize . Убедитесь, что вы ссылаетесь и проверяете правильный GameObject.

3. Будет ли иметь значение, если сценарий GroundPlacementConroller будет прикреплен несколько раз к одному и тому же игровому объекту? Я также только что протестировал, и поскольку у меня есть groundPlacementController, подключенный несколько раз к одному и тому же объекту, он изменяет размер сетки только для первого, а не для всех.

4. GetComponent всегда находит только первый! Unity на самом деле не создан для того, чтобы иметь один и тот же компонент несколько раз в одном и том же игровом объекте! Есть ли у этого объекта родительский объект или все эти компоненты являются единственными во всей сцене? Тогда есть обходной путь

5. У него есть родительский объект, также не смущайтесь, если я не отвечу до завтра, это для школьного проекта, и мне нужно идти.