### GameObject (экземпляр)
[Doc Unity](https://docs.unity3d.com/ScriptReference/GameObject.html)
<br>
```csharp
var gm = new GameObject ();
```
При инициализации экземпляра GameObject, он автоматически добавляется на сцену.
В качестве аргумента можно передать название экземпляра, которое отобразится в иерархии сцены.
<br><br>
```csharp
gameObject.transform.SetParent(anyGameObject.transform);
```
Метод устанавливает anyGameObject в качестве родителя для gameObject.
Только через transform. Других способов нет.
Это означает, что gameObject теперь становится дочерним объектом anyGameObject. Он будет следовать за своим родительским объектом по позиции, вращению и масштабу, если эти параметры будут меняться у родительского объекта.
Например, если вы переместите, вращаете или масштабируете anyGameObject, то gameObject также будет перемещён, повёрнут или масштабирован вместе с ним, сохраняя свои относительные позицию, вращение и масштаб.
Стоит отметить, что у SetParent есть опциональный второй аргумент worldPositionStays. Если он установлен в true (по умолчанию), gameObject сохранит свои глобальные координаты, вне зависимости от того, какие координаты у нового родителя. Если установить его в false, то gameObject сохранит свои локальные (относительные) координаты относительно родителя.
<br><br>
```csharp
gameObject.SetActive(false);
```
Метод отключает GameObject на сцене.
Равнозначно, если в редакторе Unity снять галку

Если установить значение false через AetActive, то оно сразу подтягивается в activeSelf

Если вы вызываете SetActive(false) внутри метода Update(), FixedUpdate() или любого другого метода, связанного с обновлением, то изменение состояния активности GameObject не будет отображаться до следующего кадра. Это происходит потому что Unity обновляет экран только в конце каждого кадра.
<br>
```csharp
var result = gameObject.activeSelf;
```
Свойство проверяет активен ли gameObject (стоит ли галка, смотреть скрин у SetActive)
<br>
```csharp
gameObject.GetComponent<Transform>();
```
Метод ищет компонент указанного типа, присоединенный к текущему GameObject.
Как именно метод ищет компонент среди других компонентов:
Unity хранит информацию обо всех компонентах, прикрепленных к GameObject, во внутренней структуре данных, которая похожа на список или массив. Когда вы вызываете GetComponent\<T>(), Unity просматривает эту структуру данных по порядку, сравнивая тип каждого компонента с типом, который вы ищете.
Стоит отметить, что порядок, в котором компоненты добавлены к GameObject, определяет порядок, в котором они будут просмотрены при вызове GetComponent\<T>().
Если вы часто вызываете GetComponent\<T>() (например, в каждом кадре в Update()), это может замедлить вашу игру, поэтому рекомендуется кэшировать ссылки на компоненты в переменные при инициализации объекта.
<br>
Если нужно получить несколько компонентов одного типа
```csharp
var list = new List<Transform>();
gameObject.GetComponents(list);
```
<br>
```csharp
if (gameObject.TryGetComponent(out Transform component))
{
component.position = Vector3.zero;
}
```
Если у GameObject’а может отсутствовать компонент, то можно проверить его наличие перед тем как его вызывать.
Определяем переменную и там же передаем. Если компонент существует, то работаем с ним.
<br>
```csharp
public T GetComponentInChildren<T>()
```
```csharp
public T GetComponentInChildren<T>(bool includeInactive)
```
Метод ищет компонент указанного типа в самом gameobject и в его дочерних GameObject’ах (дети, внуки, правнуки и далее).
Метод возвращает только первый найденный компонент. Если в иерархии объекта есть несколько компонентов указанного типа, то метод вернет только один из них.
По умолчанию метод ищет компоненты только среди активных GameObject. Если нужно найти включая неактивные, вы можете использовать версию метода с аргументом includeInactive со значением true.
<br>
```csharp
public T[] GetComponentsInChildren<T>()
public T[] GetComponentsInChildren<T>(bool includeInactive)
```
Метод получает список всех активных компонентов GameObject’ов (дети, внуки, правнуки и далее) для конкретного GameObject.
Помните, что в этом списке также будет включен сам родительский объект. Если вы хотите исключить родительский объект из списка, вы можете просто пропустить первый элемент в массиве (предполагая, что компонент типа T есть на родительском объекте).
По умолчанию метод ищет компоненты только среди активных GameObject. Если нужно найти включая неактивные, вы можете использовать версию метода с аргументом includeInactive со значением true.
Метод работает следующим образом:
1. Unity начинает с текущего GameObject, на котором вызван метод. Он проверяет наличие компонента типа T на текущем объекте и добавляет его в список, если таковой имеется.
2. Затем Unity обходит иерархию дочерних объектов текущего GameObject. Он делает это рекурсивно, то есть, начинает с непосредственных дочерних объектов, затем переходит к дочерним объектам этих дочерних объектов и так далее, пока не обойдет всех.
3. На каждом дочернем объекте Unity проверяет наличие компонента типа T и добавляет его в список, если таковой имеется. Принцип поиска компонента такой же, как у GetComponent\<T>().
4. В конце Unity возвращает список в виде массива. Массив включает все найденные компоненты типа T, включая компонент на самом объекте, на котором был вызван метод, если таковой имеется.
Это достаточно эффективный процесс, но может быть затратным с точки зрения производительности, если у вас большая иерархия объектов и/или большое количество компонентов типа T. Поэтому следует использовать этот метод с осторожностью и стараться минимизировать его использование там, где это возможно.
### AddComponent
Добавляем к GameObject’у компонент с указанным типом
```csharp
gameObject.AddComponent<GameView>();
```
### Destroy component
Мы можем удалить компонент
```csharp
Destroy(unit.GetComponent<BoxCollider>());
```
## GameObject (Статичный класс)
<br>
Метод находит GameObject по названию
```csharp
var gameObject = GameObject.Find(stringNameOfGameObject)
```
<br>
Метод создает GameObject с заданной примитивной фигурой (например, куб)
```csharp
var gameObject = GameObject.CreatePrimitive(PrimitiveType.Cube)
```
<br>
Все три метода находят GameObject по названию тега
```csharp
var gameObject = GameObject.FindWithTag(stringNameOfTag)
var gameObjectArray = GameObject.FindGameObjectsWithTag(stringNameOfTag)
var gameObject = GameObject.FindGameObjectWithTag(stringNameOfTag)
```
```csharp
static GameObject[] FindGameObjectsWithTag(string tag)
```
Метод ищет все активные gameobject’ы на сцене, у которых тег совпадает с указанным тегом.
Метод работает следующим образом:
1. Вначале метод проверяет, был ли задан тег. Если тег не задан, он возвращает пустой массив.
2. Затем метод обращается к внутреннему списку всех активных игровых объектов на сцене.
3. Метод проходит по всем активным игровым объектам на сцене и сравнивает их тег с заданным тегом.
4. Если тег игрового объекта соответствует заданному тегу, объект добавляется во временный список.
5. После прохода по всем активным объектам на сцене, временный список преобразуется в массив и возвращается в качестве результата.
Однако, этот метод не является оптимальным, если вызывается часто или обрабатывает большое количество объектов, поскольку в этом случае он может вызвать проблемы с производительностью. Вместо него стоит рассмотреть использование кэширования ссылок, событий, делегатов или методов GetComponent/GetComponentInChildren,.
<br>
### Transform (экземпляр класса)
[Doc Unity](https://docs.unity3d.com/ScriptReference/Transform.html)
Когда вы обращаетесь к transform.position у GameObject, который находится внутри другого GameObject, вы получаете глобальную позицию (в мировых координатах). Если вы хотите получить локальную позицию относительно родительского объекта, вы должны использовать transform.localPosition.
ChatGPT-4
##### При изменении родительства, gameobject сохраняет свое мировое положение, но обновляет свое локальное положение относительно нового родителя.
Когда вы создаете gameobject на сцене через метод Instantiate без указания родителя, его мировое положение будет равно значению, которое было задано в префабе.
Если затем вы устанавливаете родителя для этого gameobject, то gameobject сохранит свое текущее мировое положение, но его локальное положение (относительно родителя) изменится. Например, если у родителя позиция (50, 50, 50), то после установки родителя у gameobject, локальное положение объекта станет (49, 49, 49), так как его мировое положение (1, 1, 1) сохраняется.
GPT4
Если при добавлении префаба (в конечном итоге добавится gm) на сцену через метод instantiate не указать сразу родителя, и тем самым сначала добавить префаб просто на сцену, а потом уже добавить этому gm родителя, то произойдет следующее:
- Допустим, у префаба был заполнен position (1, 1, 1).
- Когда его добавили на сцену без родителя, то он расположился на сцене в позицию (1, 1, 1) относительно мира.
- Потом когда мы добавляем для gm родителя, то происходит следующее:
- Допустим родитель находится в позиции (50, 50, 50).
- После добавления для gm родителя, gm останется на своем месте.
- Позиция в инспекторе у нее будет отображаться локальная
- Значение в инспеторе будет (49, 49, 49)
Подробно описанный мой кейс.
<br>
```csharp
public int childCount { get; }
```
Свойство возвращает количество дочерних gameobject’ов у текущего gameobject’а
Свойство возвращает количество только прямых дочерних объектов. Если у вас есть объекты, которые являются "внуками" (т.е. они являются дочерними объектами для ваших дочерних объектов), они не будут включены в childCount. Если вам нужно узнать общее количество всех дочерних объектов на всех уровнях иерархии, вам придется самостоятельно написать код для этого.
<br>
```csharp
public Transform GetChild(int index);
```
Метод ищет по индексу дочерний gameobject у текущего gameobject’а и возвращает его Transform
Метод ищет только среди прямых дочерних gameobject’ов (т.е. не включая «внуков» и т.д.).
GetChild возвращает дочерние объекты в порядке, в котором они отображаются в окне иерархии в редакторе Unity. Этот порядок может быть изменен пользователем путем перетаскивания объектов в окне иерархии.
Если вы попытаетесь вызвать GetChild с индексом, который выходит за пределы количества дочерних объектов, Unity выдаст ошибку ArgumentOutOfRangeException.
##### transform.gameObject;
У экземпляра Transform хранится ссылка на экземпляр своего GameObject
##### transform.root
Возвращает самого верхнего gameobject-родителя.
В данном примере TankItem был внутри Content. Однако, когда была выполнена команда transform.SetParent(transform.root), то он оказался внутри самого верхнего родителя.

<br>
##### transform.parent
Свойство возвращает родительский gameobject текущего gameobject.
<br>
##### transform.childCount
<br>
##### transform.SetAsLastSibling()
Метод перемещает текущий gameobject в **конец** списка дочерних объектов своего родителя.
Это означает, что объект будет отображаться "поверх" всех своих сиблингов (братьев/сестер) в иерархии, если они находятся в одной плоскости отображения.
##### transform.SetAsFirstSibling()
В **начало** списка дочерних объектов своего родителя.
##### transform.SetParent(anotherGameObject)
Метод устанавливает для текущего gameobject’а родительский gameobject
### Опиши самые часто используемые members у класса Transform
Класс Transform в Unity представляет преобразование объекта в 3D-пространстве и является одним из основных компонентов, применяемых к каждому объекту в сцене.
Вот некоторые наиболее часто используемые свойства и методы класса Transform:
1. **position**: Векторное свойство, представляющее позицию объекта в мировых координатах. Может использоваться для получения или установки позиции объекта.
2. **localPosition**: Векторное свойство, представляющее позицию объекта относительно его родительского объекта. Если объект не имеет родителя, localPosition будет совпадать с position.
3. **rotation**: Кватернион, представляющий вращение объекта в мировых координатах. Может использоваться для получения или установки вращения объекта.
4. **localRotation**: Кватернион, представляющий вращение объекта относительно его родительского объекта. Если объект не имеет родителя, localRotation будет совпадать с rotation.
5. **eulerAngles**: Векторное свойство, представляющее вращение объекта в мировых координатах в виде углов Эйлера (по осям X, Y и Z).
6. **localEulerAngles**: Векторное свойство, представляющее вращение объекта относительно его родительского объекта в виде углов Эйлера (по осям X, Y и Z).
7. **scale**: Векторное свойство, представляющее масштаб объекта относительно его родительского объекта. Может использоваться для изменения размера объекта.
8. **parent**: Свойство, представляющее родительский объект текущего объекта. Может использоваться для создания иерархии объектов или перемещения объекта между родительскими объектами.
9. **forward**, **right**, **up**: Векторные свойства, представляющие оси Z, X и Y объекта соответственно в мировых координатах. Можно использовать для определения направления движения или работы с векторами в контексте объекта.
10. **Translate**: Метод, используемый для перемещения объекта на указанное расстояние по определенному вектору.
11. **Rotate**: Метод, используемый для вращения объекта вокруг заданных осей на указанные углы.
12. **LookAt**: Метод, который поворачивает объект так, чтобы его ось Z указывала на указанный объект или позицию.
13. **InverseTransformPoint**, **TransformPoint**, **InverseTransformDirection**, **TransformDirection**: Методы для преобразования координат и направлений между мировыми и локальными системами координат.
14. **InverseTransformPoint**: Метод, который преобразует позицию из мировых координат в локальные координаты объекта.
15. **TransformPoint**: Метод, который преобразует позицию из локальных координат объекта в мировые координаты.
16. **InverseTransformDirection**: Метод, который преобразует направление из мировых координат в локальные координаты объекта.
17. **TransformDirection**: Метод, который преобразует направление из локальных координат объекта в мировые координаты.
18. **SetParent**: Метод, который устанавливает родительский объект для текущего объекта. Можно использовать для создания иерархии объектов или перемещения объекта между родительскими объектами.
19. **GetSiblingIndex** и **SetSiblingIndex**: Методы для получения и установки индекса сиблинга (брата/сестры) текущего объекта в иерархии. Индекс сиблинга определяет порядок отображения объектов с одним и тем же родителем.
GPT-4
<br>
### Вопросы
##### Как получить список всех дочерних gameobjects (дети, внуки, правнуки и далее)?
```csharp
GameObject parent = ...; // Это ваш родительский GameObject
Transform[] children = parent.GetComponentsInChildren<Transform>();
foreach (Transform child in children)
{
Debug.Log(child.gameObject.name);
}
```
Помните, что в этом списке также будет включен сам родительский объект. Если вы хотите исключить родительский объект из списка, вы можете просто пропустить первый элемент в массиве.
Примечание: В этом примере мы используем Transform, потому что каждый GameObject обязательно содержит Transform, и нам нужен доступ к GameObject каждого дочернего элемента.
##### Как получить список только всех прямых детей gameobjects (т.е. не включая "внуки" и т.д.)?
```csharp
for (int i = 0; i < parent.transform.childCount; i++)
{
Transform child = parent.transform.GetChild(i);
Debug.Log(child.gameObject.name);
}
```
<br>
Этот код будет работать только для прямых детей родительского объекта.