#c# #arrays #unity3d #transform
#c# #массивы #unity3d #преобразовать
Вопрос:
У меня есть список всех созданных объектов в игре. Я пытаюсь выполнить поиск по этому списку, чтобы найти только объекты с тегом «Road Tag», получить их позицию преобразования и преобразовать ее в новую переменную.
Если я использую
Отладка.Log(порожденные объекты [i].transform.position;
На самом деле он отлично выводит координаты x, y, z. Но я не знаю, как присвоить их новой переменной Vector3. Синтаксис для массивов, похоже, отличается.
Я пытался:
roadCoordinates[i] = new Vector3(spawnedObjects[i].transform.position.x, spawnedObjects[i].transform.position.y, spawnedObjects[i].transform.position.z);
и
roadCoordinates[i] = spawnedObjects[i].transform.position;
public static Vector3[] roadCoordinates;
public static void FindSpawnedRoads()
{
loopCount = spawnedObjects.Count;
for (int i = 0; i < loopCount; i )
{
if (spawnedObjects[i].tag == "Road Tag")
{
//This prints perfectly
Debug.Log(spawnedObjects[i].transform.position);
//This gives me NullReferenceException
roadCoordinates[i] = new Vector3(spawnedObjects[i].transform.position.x, spawnedObjects[i].transform.position.y, spawnedObjects[i].transform.position.z);
Debug.Log(roadCoordinates[i]);
}
}
}
Я хочу, чтобы переменной были присвоены координаты Vector3 roadCoordinates[i]
.
Вместо этого я получаю NullReferenceException
. Если я не напечатаю SpawnedObjects
, в котором он печатает координаты, как я хочу.
Комментарии:
1. Как вы инициализировали
roadCoordinates
массив или вы его инициализировали?2. Извините, новичок в C #. Я не знаю, что означает initialize, но я могу сказать вам, что все три раза, когда используется переменная, показаны выше.
3. Из приведенных ниже ответов на ваши вопросы и вашего комментария о том, что вы новичок в C #, кажется, вам не хватает некоторых основ программирования, таких как типы и память. Возможно, вам следует ознакомиться с этим и задать конкретные вопросы в отдельном вопросе здесь, на SO?
4. Да, я определенно многого не понимаю, но прошло всего 2 недели. Я узнаю больше с каждым днем 🙂
Ответ №1:
Вы должны инициализировать roadCoordinates
массив, иначе вы получите NullReferenceException
ошибку. В остальном с вашей логикой все в порядке. Вы можете решить эту проблему, добавив эту строку после loopCount
присваивания:
roadCoordinates = new Vector3[loopCount];
Что происходит, когда вы не инициализируете свой массив, вы создаете переменную с именем roadCoordinates
, но для этой переменной не выделяется память или на нее нет ссылок. Следовательно, он не указывает ни на что в памяти, и когда вы пытаетесь его использовать, он говорит, что я не могу ссылаться ни на один блок памяти.
Как вы упомянули в своем вопросе, что у вас есть список всех созданных объектов, вы также можете сохранить эти точки в списке, тогда вам не нужно выделять какую-либо память, вы можете просто добавить элементы в список.
List<Vector3> roadCoordinates = new List<Vector3>()
Затем вы можете добавлять элементы, используя roadCoordinates.Add(spawnedObjects[i].transform.position)
Если вам нужно сохранить индексы созданного объекта, у которого есть Road Tag
, вы можете использовать Dictionary
Dictionary<int, Vector3> roadCoordinates = new Dictionary<int, Vector3>()
Затем вы можете добавить элементы типа roadCoordinates.Add(i,spawnedObject[i].transform.position)
Комментарии:
1. Это сработало! Спасибо. Я бы никогда не догадался задать его, чтобы присвоить ему значение loopCount. Почему это? Будет ли использование этого делать то же самое?
roadCoordinates = new Vector3(0, 0, 0);
2. Нет, вы не можете присвоить вектор массиву векторов. loopCount — это размер вашего массива, и на самом деле это не очень хорошая практика, потому что вы на самом деле не знаете размер (сколько элементов имеют тег) вашего массива. Следовательно, список — лучшее решение для этого.
3. spawnedObjects — это фактически список всех созданных игровых объектов. Есть ли лучший способ сделать это? Почему это плохая практика?
4. Решение заключается в использовании a
List
вместоArray
ofroadCoordinates
, потому что массивы имеют фиксированный размер. Вы можете изменить размер только путем перераспределения. Вы не можете добавлять или удалять элементы без перераспределения. Рассмотрим сценарий, в котором вы сохранили 20 мест для вечеринки, но не знаете, сколько из них придет. Тогда, допустим, пришли 5 человек, 15 мест потрачены впустую или пришло 30 человек, тогда у вас не хватает места или еды / напитков для всех.5. Да, это имеет смысл. Хм. Что ж, spawnedObjects на самом деле представляет собой список, как я уже сказал. Как бы я их вызвал, если бы не использовал массив?
Ответ №2:
Вероятно, вам следует использовать array.push() (см.:https://docs.unity3d.com/ScriptReference/Array.Push.html ) вместо того, чтобы писать ‘roadCoordinates[i]’, поскольку этот массив все еще пуст. Используя ‘push’, вы добавляете новую позицию / 3D вектор в конец массива, что также работает, если массив все еще пуст. Я надеюсь, это поможет вам!
PS: если вы сначала инициализируете массив определенной длины, как предложено в другом ответе, у вас будет много пустых элементов массива, поскольку не каждый элемент в вашем цикле является «дорожным тегом».
Комментарии:
1. «Примечание: Это только javascript. C # не использует эту функцию «. Цитируется по ссылке
2. Конечно, вы правы в этом… Совершенно забыл об этом. Тогда решение заключается в использовании списка, где вы можете запустить .Add() .
3. Только что увидел вашу правку. Есть ли что-нибудь лучшее для его присвоения?
4. Что именно вы имеете в виду? Кроме того, вам действительно не нужно добавлять словарь. Просто посмотрите мой новый ответ в корне этого Q amp; A.
Ответ №3:
Да, как предлагает Александр, использование списков — это правильный путь. Вам не нужно использовать словарь, поскольку вы уже знаете, что список roadCoordinates будет содержать только элементы тега ‘Road Tag’.
public static List<Vector3> roadCoordinates = new List<Vector3>();
public static void FindSpawnedRoads()
{
loopCount = spawnedObjects.Count;
for (int i = 0; i < loopCount; i )
{
if (spawnedObjects[i].tag == "Road Tag")
{
roadCoordinates.Add(new Vector3(spawnedObjects[i].transform.position.x, spawnedObjects[i].transform.position.y, spawnedObjects[i].transform.position.z));
}
}
}
Комментарии:
1. Редактировать: Позвольте мне сделать это более читабельным. Подождите, эй! Я пытаюсь выяснить, как бы я это сделал с помощью цикла foreach, но синтаксис, похоже, неправильный. Вы знаете, что у меня здесь не так? Там говорится, что мне нужен идентификатор, но у меня есть один (GameObject, верно?)
public static void FindSpawnedRoadsForEach() { foreach(spawnedObjects.tag = "Road Tag" in spawnedObjects) { Debug.Log(spawnedObjects); } }
Ответ №4:
В этом случае лучше использовать списки, потому что мы с самого начала не знаем, сколько объектов у нас будет.
List<Vector3> roadCoordinates = new List<Vector3>();
...
roadCoordinates.Add(new Vector3(...));
Вот руководство по спискам.
Комментарии:
1. Порожденные объекты — это список. Эта функция выполняет поиск по списку, чтобы увидеть, какие объекты являются дорогами, а затем находит их преобразование. Я полагаю, мне следует изменить его на словарь и сохранить как их имя, так и их преобразование. Как вы думаете, какая из мобильных видеоигр менее ресурсоемка?