#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. У него есть родительский объект, также не смущайтесь, если я не отвечу до завтра, это для школьного проекта, и мне нужно идти.