Как получить координаты объекта в unity
Перейти к содержимому

Как получить координаты объекта в unity

  • автор:

Направление и расстояние от одного объекта до другого.

Если вычесть координаты одной точки в пространстве из координат другой, то получим вектор, который “выходит” из второй точки и “заканчивается” в первой:

// Gets a vector that points from the player's position to the target's. var heading = target.position - player.position; 

Помимо того, что этот вектор указывает в направлении объекта, модуль данного вектора равен расстоянию между двумя позициями. Часто нам требуется нормированный вектор, который показывает направление к цели, а также расстояние (скажем, для управления снарядом). Расстояние между двумя объектами равно модулю направляющего вектора, он может быть нормирован, достаточно разделить на его модуль:-

var distance = heading.magnitude; var direction = heading / distance; // This is now the normalized direction. 

Лучше выбрать именно такой подход, нежели использовать модуль и нормаль отдельно, из-за их склонности нагружать CPU (оба используют вычисления квадратных корней).

Если расстояние нужно лишь для сравнения (скажем, проверка на достаточную удаленность), тогда вообще можно не вычислять значение модуля. Свойство sqrMagnitude возвращает квадрат модуля, оно высчитывается подобно расстоянию, но без затратной по времени операции нахождения квадратного корня. Вместо того, что сравнивать модуль с известным расстоянием, можно сравнить квадрат модуля с квадратом расстояния:-

if (heading.sqrMagnitude < maxRange * maxRange) < // Target is within range. >

Это намного более эффективно, чем вычислять именно модуль при сравнении.

Иногда, требуется узнать направление к надземной цели. Например, представьте, что игроку, который стоит на земле нужно приблизиться к парящему в воздухе предмету. Если вычесть координаты позиции игрока из координат цели, тогда полученный вектор будет указывать вверх и по направлению к цели. Этот вариант не подходит, чтобы придать ориентацию компоненту transform игрока, так как он тоже будет указывать вверх. Что тут действительно нужно сделать — это вычислить вектор от игрока к позиции на земле прямо под предметом. Это легко сделать, если у вектора, являющегося результатом вычитания, установить координату Y в ноль:-

var heading = target.position - player.position; heading.y = 0; // This is the overground heading. 

Трансформации

Компонент Transform (трансформация) используется для хранения значений позиции, вращения, размеров и состояния наследования GameObject’а, потому он очень важен. К GameObject’у всегда добавлен компонент Transform — его невозможно удалить или создать GameObject без него.

Редактирование трансформаций

Компоненты Transform управляются в 3D пространстве по осям X, Y, и Z, или в 2D пространстве просто по X и Y. В Unity эти оси представлены красным, зелёным и синим цветами соответственно.

Tramsform c цветными осями

Transform может быть изменён в окне Scene или путём изменения параметров в инспекторе. В сцене вы можете изменять Transform используя инструменты Translate, Rotate и Scale (двигать, вращать и масштабировать). Эти инструменты расположены в верхнем левом углу редактора Unity.

Инструменты View, Translate, Rotate и Scale

Эти инструменты можно применить к любому объекту в сцене. Когда вы кликнете на объект, вы увидите, что у объекта появится гизмо инструмента. Вид гизмо зависит от выбранного инструмента.

Гизмо Transfromа

Когда вы нажмёте на одной из трёх осей гизмо и потянете, вы заметите, что её цвет изменится на жёлтый. По мере движения мыши, вы увидите как объект будет двигаться, вращаться или менять размер соответственно выбранной оси. Когда вы отпускаете кнопку мыши, ось остаётся выделенной. Если вы впоследствии будете двигать мышь с зажатым колёсиком, то будет использована последняя выбранная ось, независимо от позиции курсора мыши.

Transfrom с выделенной (жёлтой) осью X

Для режима перемещения есть дополнительная опция — перемещение объекта в отдельной плоскости (другими словами, позволяет перемещать объект в двух осях сразу, не затрагивая третью). Три маленьких цветных квадрата вокруг центра гизмо перемещения активируют фиксацию для каждой из плоскостей; цвета соответствуют оси, которая будет зафиксирована, если нажать на квадрате (например, синий квадрат фиксирует ось Z).

Наследование

Наследование — один из самых важных концептов, который следует понимать при использовании Unity. Когда GameObject является родительским для другого объекта, дочерний GameObject будет двигаться, вращаться и менять размер в той же степени, что и родительский объект. Вы можете представлять наследование как связь между вашими руками и вашим телом; когда ваше тело движется, то ваши руки также двигаются вместе с ним. Дочерние объекты могут иметь и свои дочерние объекты и так далее. Таким образом, ваши ладони могут считаться “детьми” ваших рук, а у каждой ладони есть несколько пальцев и т.д. Любой объект может иметь несколько “детей”, но только одного родителя. Эти многоуровневые связи родители-дети формируют иерархию трансформаций. Объект на самом верху иерархии (т.е. единственный объект, у которого нет родителя) известен как root (корень).

Вы можете создать родительский объект перетягиванием любого GameObject’а в окне Hierarchy на другой объект. Это создаст связь родительский-дочерний между двумя игровыми объектами.

Пример родительской иерархии. Объекты с раскрывающимися стрелками слева от их имён являются родительскими.

Учтите, что значения Transform в инспекторе для любого дочернего объекта показаны относительно значений Transform родительского объекта. Эти значения известны как локальные координаты . Возвращаясь к аналогии тела и рук, положение вашего тела может изменяться по мере ходьбы, но ваши руки будут присоединены в одном и том же месте относительно тела. Для построения сцены обычно достаточно работать с локальными координатами для дочерних объектов, но во время игрового процесса зачастую полезно найти их точное положение в мировом пространстве или их мировые координаты . API скриптинга для компонента Transform имеет отдельные настройки для локальных и мировых координат.

Проблемы производительности и ограничения неравномерного (Non-Uniform) масштабирования

Неравномерное масштабирование (Non-uniform Scaling) — это когда параметр Scale в Transform имеет разные значения для x, y, и z; например (2, 4, 2). И наоборот, при равномерном масштабировании, x, y и z имеют одинаковые значения; например (3, 3, 3). Неравномерное масштабирование может быть полезно в некоторых особых случаях, но вам лучше стараться этого избегать, поскольку это замедляет рендеринг графики. Также могут появиться некоторые странности, которых не бывает при равномерном масштабировании:-

  • Некоторые компоненты не имеют полной поддержки неравномерного масштабирования. Например у некоторых компонентов есть круглый или сферический элемент с заданным параметром radius . Среди таких компонентов есть Sphere Collider , Capsule Collider , Light и Audio Source . В подобных случаях круглая форма не станет эллиптической под влиянием неравномерного масштабирования, а просто останется круглой.
  • Если у дочернего объекта есть неравномерно отмасштабированный родитель, и он (дочерний объект) повёрнут относительно родителя, он может стать перекошенным или “сдвинутым”. Есть компоненты, которые поддерживают простое неравномерное масштабирование, но некорректно работают такими перекосами. Например, перекошенный Box Collider не будет точно совпадать с формой меша.
  • По причинам производительности, масштаб дочернего объекта неравномерно отмасштабированного родителя не будет автоматически обновлён при вращении. В результате, форма дочернего объекта может резко измениться, после того как масштаб уже обновился, например, после отделения дочернего объекта от родителя.

Важность масштаба

Масштаб Transform’а определяет разницу между размером меша в приложении для моделирования и размером этого же меша в Unity. Размер меша в Unity (он же — масштаб Transform’a) очень важен, особенно во время физических симуляций. По умолчанию, физический движок предполагает, что одна единица меры в мировом пространстве соответствует одному метру. Если объект очень большой, может получиться, что он будет падать “в замедленном времени”; симуляция на самом деле правильная, т.к. по сути, вы смотрите с большого расстояния на то, как падает очень большой объект.

Есть 3 фактора которые могут повлиять на масштаб вашего объекта:

  • Размер вашего меша в вашем приложении для 3D моделирования.
  • Коэффициент Mesh Scale Factor устанавливаемый в настройках импорта объекта ( Import Settings ).
  • Значение параметра Scale компонента Transfrom.

В идеале, вам не надо настраивать параметр Scale вашего объекта в компоненте Transform. Лучшим вариантом является создание моделей реалистичного размера, таким образом, чтобы вам не пришлось менять масштаб. Следующим лучшим вариантом является настройка масштаба в настройках Import Settings импортированного меша, для конкретного меша. Некоторые оптимизации производятся на основе размера при импорте, и создание экземпляра объекта с изменённым значением масштаба может снизить производительность. Для дополнительной информации, прочитайте раздел об оптимизации масштаба на странице справки по компоненту Rigidbody.

Подсказки по работе с компонентами Transform

  • При родительстве Transform’а, будет полезным установить координаты родителя на , прежде чем добавлять дочерний объект. Это значит, что местные координаты для дочернего объекта будут равны мировым координатам и таким образом будет проще убедиться, что дочерний объект находится в нужной позиции.
  • Particle Systems (системы частиц) не подвержены влиянию параметра Scale у компонента Transfrom. Чтобы масштабировать систему частиц, вам надо изменить параметры в разделах системы частиц Emitter, Animator и Renderer.
  • Если вы используете Rigidbodies для симуляции физики, то убедитесь, что прочитали раздел про параметр Scale на странице Rigidbody.
  • Вы можете поменять цвета осей Transform’а (и других элементов интерфейса) в настройках ( Menu: Unity > Preferences и затем выбрать панель Colors & keys ).
  • Changing the Scale affects the position of child transforms. For example scaling the parent to (0,0,0) will position all children at (0,0,0) relative to the parent.

Как получить координаты ближайшего объекта из множества других в Unity?

Нужно сделать так, чтобы каждый куб на сцене при движении рассчитывал расстояние до еды и если это расстояние меньше 10 единиц, то начинал двигаться к нему. Уже неделю пытаюсь реализовать эту затею, но сложность составляет то, что еда появляется на сцене каждые n секунд. причем произвольное перемещение работает нормально. Пробовал и присваивать в скрипте Food Script координаты объекта, и создавать отдельный GameObject, получая его координаты. Один раз получилось реализовать, но была ошибка с уничтожением объекта, т.к удалял префаб, а не сам объект. После исправления что-то изменил и теперь никак не могу вернуть. Я так понимаю, проблема в том, что мой скрипт перемещения куба не может выбрать определенные координаты, ведь еды на сцене много, но путает то, что как-то до этого работало. Помогите пожалуйста.

 public class PlayerControl : MonoBehaviour < public GameObject prefabCube; public Rigidbody cube; public Vector3 moveDirection; public Vector3 cubePosition; public float smoothing; private FoodScript food; private LevelManager levelManager; public int collectedFood; void Start() < food = FindObjectOfType(); moveDirection = transform.position; > void Update() < if (food != null && Vector3.Distance(transform.position, food.transform.position) < 10.0f) < Debug.Log("This is foodDirection"); transform.position = Vector3.MoveTowards(transform.position, food.transform.position, smoothing * Time.deltaTime); >else < Movement(); >> private void Movement() < if (Vector3.Distance(moveDirection, transform.position) < 0.5f) < //Random.Range(-10.0f, 10.0f) moveDirection = new Vector3(Random.Range(-40.0f, 40.0f), transform.position.y, Random.Range(-40.0f, 40.0f)); >else < transform.position = Vector3.MoveTowards(transform.position, moveDirection, smoothing * Time.deltaTime); >> private void OnTriggerEnter(Collider other) < if (other.tag == "FallDetector") < Destroy(prefabCube); >> 
 public class LevelManager : MonoBehaviour < public float timer; public float startTimer; public GameObject prefabFood; private PlayerControl player; private FoodScript food; // Start is called before the first frame update void Start() < food = FindObjectOfType(); timer = startTimer; > // Update is called once per frame void Update() < timer -= Time.deltaTime; if (timer > public void SpawnFood() < Debug.Log("This is SpawnFood"); for (int i = 0; i < 5; i++) < Instantiate(prefabFood, new Vector3(Random.Range(-40.0f, 40.0f), transform.position.y, Random.Range(-40.0f, 40.0f)), transform.rotation); >> > 
 public class FoodScript : MonoBehaviour < public Vector3 position; private LevelManager levelManager; private PlayerControl player; private void Start() < position = transform.position; player = FindObjectOfType(); levelManager = FindObjectOfType(); > private void Update() < >private void OnTriggerEnter(Collider other) < if (other.gameObject.tag == "Cube") < Destroy(gameObject); >> > 

Отслеживать
Никита Юрин
задан 20 ноя 2020 в 15:05
Никита Юрин Никита Юрин
1 1 1 бронзовый знак

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Научитесь работать с событиями ( event ) (обязательно)

Научитесь работать с корутинами. Альтернатива Update , для не постоянных вещей. (желательно)

// запрет на несколько компоненов этого типа на одном GameObject [DisallowMultipleComponent] public class CubeManager : MonoBehaviour < // статическая переменная к которой можно будет обращаться глобально типа как Camera.main public static CubeManager Main; // список всех кубов public ListCollection; private void Awake () < Main = this; // Задаём данный обьект как Main Collection = new List(); > > 
using System; [DisallowMultipleComponent] public class FoodManager : MonoBehaviour < public static FoodManager Main; public ListCollection; // событие спавна еда // Action - делегат некой void функции с аргуметом Food типа void Function (Food food) public event Action FoodSpawned; // событие удаления еды public event Action FoodRemoved; // префаб еды // SerializeField - поле ведёт себя в инспекторе, как public, хотя и private, // в public нет смысла, другим глассам незачем иметь к этому полю доступ [SerializeField] private GameObject _foodTemplate; [SerializeField] private float _spawnStep; private float _spawnTimer; private void Awake () < Main = this; Collection = new List(); > private void Update () < _spawnTimer += Time.deltaTime; if (_spawnTimer >= _spawnStep) < _spawnTimer -= _spawnStep; SpawnFood(); >> private void SpawnFood () < GameObject NewFoodObject = Instantiate(_foodTemplate); Food NewFood = NewFoodObject.GetComponent(); Collection.Add(NewFood); // передаём делегат с методом RemoveFood() для того, // чтобы еда смогла удалить себя из листа и оповестить о событии удаления NewFood.SetRemove(RemoveFood); float PositionX = UnityEngine.Random.Range(-100, 100); float PositionZ = UnityEngine.Random.Range(-100, 100); NewFood.Transform.position = new Vector3(PositionX, 0, PositionZ); // оповещает всех подписчиков о событии спавна с передачей ссылки на заспавниную еду if (FoodSpawned != null) FoodSpawned.Invoke(NewFood); > private void RemoveFood (Food food) < Collection.Remove(food); if (FoodRemoved!= null) FoodRemoved.Invoke(food); >> 
[DisallowMultipleComponent] // делает Rigidbody обязательным // автоматически добавит на GameObject, если его нет и не позволит удалить, пока есть Cube компонент [RequireComponent(typeof(Rigidbody))] public class Cube : MonoBehaviour < [SerializeField] private float _followDistance = 10; [SerializeField] private float _followSpeed = 1; private Rigidbody _body; private Transform _transform; private Food _followTarget; private IEnumerator _followCoroutine; private void Start () < _transform = transform; // кешируем, что-бы не запрашивать повторно (хотя в паследних версия "вроде" не надо) // берём компонент без проверки не боясь ошибки "null reference exception", поскольку есть RequireComponent _body = GetComponent(); // добавляется в общий список кубов CubeManager.Main.Collection.Add(this); // подписывается на события появления и удаления еды FoodManager.Main.FoodSpawned += SpawnFood; FoodManager.Main.FoodRemoved += SpawnFood; > private void OnDestroy () < // при удалении куба, удаляет себя из списка и отписывается от событий CubeManager.Main.Collection.Remove(this); FoodManager.Main.FoodSpawned -= SpawnFood; FoodManager.Main.FoodRemoved -= SpawnFood; >private void SpawnFood (Food food) < Vector3 Vector = food.Transform.position-_transform.position; Vector = new Vector3(Vector.x, 0, Vector.z); // magnitude это длина Vector2/Vector3 if (Vector.magnitude < _followDistance) StartFollow(food); >private void RemoveFood (Food food) < if (food == _followTarget) StopFollow(); >private void CatchFood () < Destroy(_followTarget); >private void StartFollow (Food food) < _followTarget = food; // запускаем корутину движения, если она не запущена if (_followCoroutine == null) < _followCoroutine = FollowCoroutine(); StartCoroutine(_followCoroutine); >> private void StopFollow () < _followTarget = null; // корутина остановилась бы и после _followTarget = null, // выйдя из цикла while, поскольку _followTarget в её условии, // но вообще она останавливается так StopCoroutine(_followCoroutine); _followCoroutine = null; >private IEnumerator FollowCoroutine () < // безконечно выполняется, пока есть цель while (_followTarget != null) < Vector3 FollowVector = _followTarget.Transform.position-_transform.position; FollowVector = new Vector3(FollowVector.x, 0, FollowVector.z); // normalized выдаёт вектор, длинной 1 Vector3 MoveVector = FollowVector.normalized*_followSpeed; _body.velocity = MoveVector; // ждёт до следубщего обновления физики как FixedUpdate yield return new WaitForFixedUpdate(); >> private void OnTriggerEnter (Collider other) < // столкновение с едой if (other.GetComponent() != null) Destroy(other.gameObject); > > 
using System; [DisallowMultipleComponent] public class Food : MonoBehaviour < public Transform Transform; private Action_onDestroy; public void SetRemove (Action remove) < _onDestroy = remove; >private void Awake () < Transform = transform; >private void OnDestroy () < // при удалении вызывает ранее переданный метод удаляющий еду из списка и вызывающий событие if (_onDestroy != null) _onDestroy(this); >> 

Как узнать координату X объекта в unity?

MrMureno

а как правильно получить ссылку. на объект. сделать скрипт. куда вешать — туториалы на саите юнити..

GavriKos

GavriKos @GavriKos Куратор тега Unity

Я бы еще дополнил всякими ScreenToWorldPoint и обратными операциями. А то фиг его координату в какой системе отчета надо получить

HapBox @HapBox Автор вопроса
Denis Gaydak, Спасибо большое.
RuslanVoronin @RuslanVoronin

Вот советы про то, что человеку бросать, а что нет, могли бы оставить при себе. Если не хотите помогать, зачем отвечать? Русскоязычное сообщество в действии, что тут сказать.

RuslanVoronin, замечание в точку
Ответы на вопрос 0
Ваш ответ на вопрос

Войдите, чтобы написать ответ

c#

  • C#
  • +1 ещё

Почему в Unity очень низкое качество?

  • 1 подписчик
  • 4 часа назад
  • 73 просмотра

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *