В Unity пытаюсь получить координаты Vector3 из массива и присвоить им новую переменную. Каков правильный синтаксис?

#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 of roadCoordinates , потому что массивы имеют фиксированный размер. Вы можете изменить размер только путем перераспределения. Вы не можете добавлять или удалять элементы без перераспределения. Рассмотрим сценарий, в котором вы сохранили 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. Порожденные объекты — это список. Эта функция выполняет поиск по списку, чтобы увидеть, какие объекты являются дорогами, а затем находит их преобразование. Я полагаю, мне следует изменить его на словарь и сохранить как их имя, так и их преобразование. Как вы думаете, какая из мобильных видеоигр менее ресурсоемка?