Я пытаюсь получить прямоугольник для перемещения между двумя позициями, которые я называю _positionA
и _positionB
. Оба имеют тип Vector3
. Прямоугольник движется просто отлично. Однако, когда он достигает, _positionB
он не движется в противоположном направлении, как это должно быть.
Я вернулся в код, чтобы посмотреть. Я пришел к выводу, что когда объект перемещается, if
операторы в коде пропускают кадр, в котором позиция rects была равна _positionB
. Я решил изменить код в обратном направлении, если позиция rects больше или равна _positionB
. Мой код не слишком длинный, поэтому я покажу его ниже:
using UnityEngine;
using System.Collections;
public class Rectangle : MonoBehaviour
{
private Vector3 _positionA = new Vector3(-0.97f, -4.28f); //Start position
private Vector3 _positionB = new Vector3(11.87f, -4.28f); //End position
private Transform _rect_tfm;
private bool _atPosA = false, _atPosB = false;
public Vector2 speed = new Vector2(1f, 0f);
private void Start()
{
_rect_tfm = gameObject.GetComponent<Transform>();
_rect_tfm.position = _positionA;
_atPosA = true;
}
private void Update()
{
/*NOTE: Infinite loops can cause Unity to crash*/
Move();
}
private void Move()
{
if (_atPosA)
{
_rect_tfm.Translate(speed * Time.deltaTime);
if (_rect_tfm.position == _positionB)
{
_atPosA = false;
_atPosB = true;
}
}
if (_atPosB)
{
_rect_tfm.Translate(-speed * Time.deltaTime);
if (_rect_tfm.position == _positionA)
{
_atPosA = true;
_atPosB = false;
}
}
}
}
Однако, когда я изменил его, он предупредил меня о следующем сообщении об ошибке:
Оператор> = нельзя применять к операндам типа Vector3 и Vector3.
Это смущает меня по двум причинам; Во-первых, оба значения имеют одинаковый тип данных. Во-вторых, использование оператора сравнения ( ==
) для двух значений работает без ошибок. Почему я не могу использовать оператор >=
с Vector3
s?
источник
Bools
как_atPosA
и_atPosB
. Неизбежно, вы допустите ошибку, держа их обоих в синхронизации, и это приведет к ошибкам. Лучше сделать вложение,enum
содержащее все позиции (A, B, возможно, другие в будущем), и использовать это>=
означать дляVector3
? Сравнить по компонентам? Это не было бы полным заказом. Рассмотрите возможность использованияVector3.MoveTowards
var vec1 = new Vector3(1, 0, 0)
аvar vec2 = new Vector3(0, 1 ,0)
. Этоvec1 >= vec2
правда или ложь?Ответы:
Чтобы упростить ответ,
Vector3
это обычай,struct
предоставляемыйUnityEngine
пространством имен. Когда мы создаем customclass
илиstruct
типы, мы также должны определить его операторы . Таким образом, для>=
оператора нет логики по умолчанию . Как отметил Евгений Васильев ,_rect_tfm.position == _positionB
имеет смысл, так как мы можем непосредственно проверитьVector3.x
,Vector3.y
иVector3.z
значение._rect_tfm.position >= _positionB
не имеет особого смысла из-за того, что aVector3
представлено тремя отдельными значениями.Мы можем перегрузить
Vector3
класс, чтобы он содержал подходящие операторы в теории , но это кажется довольно сложным. Вместо этого, было бы проще просто расширить наVector3
класс с подходящим способом . При этом, похоже, что вы собираетесь использовать эту логику для движения. Таким образом, вам может оказаться гораздо проще использоватьVector3.Lerp
метод; если это так, читайте дальше ниже.Добавление методов расширения к
Vector3
Как упоминалось ранее, применение
<=
или>=
кVector3
часто нелогично. Что касается движения, вы, вероятно, хотите читать дальше дляVector3.Lerp
метода. Тем не менее, вы можете захотеть применить<=
=>
арифметику по другим причинам, поэтому я дам вам легкую альтернативу.Вместо применения логики
Vector3 <= Vector3
илиVector3 >= Vector3
, я предлагаю расширитьVector3
класс, чтобы включить методы дляisGreaterOrEqual(Vector3 other)
иisLesserOrEqual(Vector3)
. Мы можем добавить методы расширения кstruct
илиclass
, объявив их вstatic
классе, который не наследует. Мы также включаем цельclass
илиstruct
в качестве первого параметра, используяthis
ключевое слово. Обратите внимание, что в моем примере я предполагаю, что вы хотите убедиться, что все три основных значения (x
,y
иz
) все больше или равны или меньше или равны соответственно. Вы можете предоставить свою собственную логику здесь, как вам требуется.Когда мы попытаемся вызвать эти методы из
Vector3
класса,local
мы представимVector3
экземпляр, из которого мы вызываем метод. Вы заметите, что методы естьstatic
; методы расширения должны бытьstatic
, но вы все равно должны вызывать их из экземпляра. Учитывая вышеописанные методы расширения, теперь вы можете применять их непосредственно к вашимVector3
типам.Переезд
Vector3
сVector3.Lerp
Вызов на
Vector3.Lerp
метод позволяет определить точное положение между двумяVector3
значениями в данный момент времени. Дополнительным преимуществом этого метода является то, чтоVector3
он не будет превышать свою цель .Vector3.Lerp
принимает три параметра; начальная позиция, конечная позиция и текущая позиция, представленные в виде значений от 0 до 1. Он выводит результирующую позицию в виде aVector3
, которую мы можем непосредственно установить в качестве текущей позиции.Решая вашу проблему, я предлагаю использовать
Vector3.Lerp
для перехода кtargetPosition
. После вызоваMove
метода в каждомUpdate
мы можем проверить, достигли ли мы указанной цели;Lerp.Vector3
будет не перерегулирование, поэтомуtransform.position == targetPosition
становится надежным. Теперь мы можем проверить положение и изменить ,targetPosition
чтобыleftPosition
илиrightPosition
изменить направление движения, соответственно.Вы можете увидеть это в следующей анимации. Я перевожу синий куб с помощью
Vector3.LerpUnclamped
, который дает нам результат, аналогичный простому непроверенному переводу. Я перевожу красный куб, используяVector3.Lerp
. Оставленный непроверенным, синий куб уходит в забвение; в то время как красный куб останавливается именно там, где я собираюсь. Вы можете прочитать больше об этом типе движения в документации по переполнению стека .источник
Определение
>=
дляVector3
типа не имеет смысла. Что определяет, если один вектор больше другого? Их величина или их отдельные компоненты x, y, z?Вектор - это величина и направление. Так что определяет, какое направление больше?
Если вам нужно сравнить величины, которые вы можете использовать
sqrMagnitude
.В этом случае
Vector3
переопределяет,==
чтобы просто сравнить различные компоненты, чтобы увидеть, являются ли они одинаковыми. (в пределах порога)Это та же самая причина, по которой умножение двух векторов
*
невозможно. Там просто нет математического способа сделать это. Некоторые люди используют*
для точечного продукта, но это неясный дизайн API.источник
Vector3
являютсяstruct
, таким образом , пункт о эталонном сравнении не совсем верно.Это старый вопрос, но, если не сказать больше технических терминов, Vector3 - это «контейнер» для трех значений с плавающей запятой - x, y, z.
Вы можете сравнить отдельные значения, такие как сравнение значений x двух Vector3, потому что они являются просто числами.
Однако весь Vector3 нельзя сравнить с другим Vector3, потому что нет единого значения, которое можно использовать для сравнения двух.
источник
Просто добавлю к тому, что написал Gnemlock , относительно добавления методов расширения в класс Vector3. Там есть проблема в единстве (и я уверен , что другие двигатели игры) при использовании определенных операторов сравнения (
==
,<=
а>=
) между двумя значениями с плавающей точкой, из - за того , как обрабатывается расчет с плавающей точкой.Mathf.Approximately
следует использовать вместо этого, таким образом, следующие методы расширения могут быть добавлены для проверки, являются ли два вектора> = или <= друг другу:источник
Я хотел бы предложить другой способ интерпретации этого вопроса. Шаблон кода, подобный этому:
в основном пытается использовать
>=
/<=
операторы как "левая сторона достигла или прошла правую сторону?"тесты.С помощью
>=
/<=
для обозначения «достигнуто или пройдено» имеет смысл в одномерном смысле, если моя позиция просто поплавок:Но в трехмерном пространстве у нас нет ни одной линии для измерения, чтобы решить, какая сторона «высокая / дальняя», а какая «низкая / ближняя». Например, мы могли бы пытаться патрулировать между точками
Так что теперь мы ожидаем
patrolStart <= myPosition <= patrolEnd
на оси X, ноpatrolEnd <= myPosition <= patrolStart
по оси Z. Наш оператор «достигнут или пройден» отличается от одной оси к другой, поэтому больше нет четкого отображения между нашей концепцией прохождения порога и простой проверкой неравенства.Но есть способ, которым мы можем выделить только одну строку в трехмерном пространстве и заставить наш
>=
/<=
вести себя как один случай с плавающей точкой вдоль этой линии, которую мы выбрали:В качестве бонуса, если вы нормализуете вектор оси перед его использованием, тогда все точечные произведения представляют расстояния, так что вы можете точно измерить, как далеко вы находитесь от любого конца вдоль оси перемещения.
источник