Здесь много чего происходит.
Если у ваших transPointFirst
, transPointSecond
и т. Д. Есть какие-либо родительские игровые объекты, сравнение их localPosition
с position
из target
может привести к неожиданному поведению.Вероятно, лучше сравнить их position
поля напрямую.Кроме того, если их Z-компоненты их позиций уже 0
, вам не нужно создавать дубликаты Vector3
из них.
Translate
ожидает вектор направления, умноженный на расстояние, но выдают ему то, что кажется вектором позиции.Возможно, вы захотите использовать Vector3.MoveTowards
для вычисления позиции target
каждого кадра.Вам понадобится переменная, чтобы установить скорость, с которой вы хотите двигаться, в идеале это было бы открытое поле, поэтому вы можете установить его в инспекторе.
Кроме того, как сказал Эддж, вы делаете этосначала Translate
при любых обстоятельствах, которые идут против логики, которую вы хотите.
Однако в Unity операторы Vector3
==
и !=
уже проверяют приблизительное равенство, так что у вас все хорошо.
Вам также необходимо учитывать, что происходит с кадрами, когда объект находится между двумя позициями.Если вы вызываете ElevateCaptain
на каждом кадре, когда он должен двигаться, вы можете проверить, находится ли его текущая позиция между каждой последовательной парой точек, или иметь некоторые переменные, которые отслеживают, к каким точкам он «прикоснулся», такдалеко.
Более простым способом написать то, что вы хотите сделать здесь, может быть использование Coroutine
s , затем вызывать ElevateCaptain
только один раз, когда вы хотите, чтобы оно начало двигаться.Вот пример того, как ваш код может выглядеть с этими изменениями и использованием сопрограмм:
public float elevateSpeed;
private bool captainElevating;
Start()
{
// ...
captainElevating = false;
// ...
}
private void ElevateCaptain()
{
if (!captainElevating)
{
captainElevating = true;
StartCoroutine("ElevateCaptainCoroutine");
}
}
private IEnumerator ElevateCaptainCoroutine()
{
targetRigid.isKinematic = true
while (target.transform.position != transPointFirst.position)
{
target.transform.position = Vector3.MoveTowards(
target.transform.position,
transPointFirst.position,
elevateSpeed * Time.deltaTime);
yield return null;
}
while (target.transform.position != transPointSecond.position)
{
target.transform.position = Vector3.MoveTowards(
target.transform.position,
transPointSecond.position,
elevateSpeed * Time.deltaTime);
yield return null;
}
while (target.transform.position != transPointThird.position)
{
target.transform.position = Vector3.MoveTowards(
target.transform.position,
transPointThird.position,
elevateSpeed * Time.deltaTime);
yield return null;
}
while (target.transform.position != transPointFourth.position)
{
target.transform.position = Vector3.MoveTowards(
target.transform.position,
transPointFourth.position,
elevateSpeed * Time.deltaTime);
yield return null;
}
targetRigid.isKinematic = false;
captainElevating = false;
}
Если вы решите пойти по маршруту Coroutine
, вы должны попытаться вызвать ElevateCaptain
только один раз, когда захотитецель начинает движение, хотя включение переменной captainElevating
не должно вызывать ее, пока она уже происходит.
Сопрограмма или иное, улучшение в этом может заключаться в использовании List
из GameObject
и иметь цикл Coroutine над списком, перемещая target
к каждому по очереди.Таким образом, в инспекторе вы можете перетащить столько transPoint
GameObjects, сколько захотите, в список и очень легко изменить его.Повторяющаяся структура подхода сопрограммы очень хорошо подходит для такой петли.