Как передвинуть объект из точки А в точку B, и после того как он достиг точки подождать определенное время, и снова передвинуть
Как передвинуть объект из точки А в точку B, и после того как он достиг точки подождать определенное время, и снова передвинутся с точки B в новую точку.
Хочу что бы объект передвигался в точку после чего стоял на месте определенное время, и после снова перемещался в другую точку, не как не выходит понять, уже очень долго мучаюсь над этим. Помогите пожалуйста. Объект просто телепортируется по точкам. Нужно что - бы объект плавно дошел до точки назначения, ждал там некоторое время, и после снова перемещался
public class Coroutine : MonoBehaviour
{
// стартовая позиция
private Vector3 startPosition;
// новая позиция объекта
private Vector3 newPoint;
private void Start()
{
// даю начальную позицию
startPosition = transform.position;
}
private void Update()
{
// указываю новую точку рандомными координатами, от начальной точки
newPoint = new Vector3(
Random.Range(startPosition.x - 5, startPosition.x + 5),
startPosition.y,
Random.Range(startPosition.z + 5, startPosition.z - 5)
);
// запускаю корутину
StartCoroutine(MoveCoroutine(newPoint));
}
private IEnumerator MoveCoroutine(Vector3 moveTo)
{
// жду 2 сек
yield return new WaitForSeconds(2f);
// если позиция объекта не равна конечной точки
if (transform.position != newPoint)
{
// телепортирую объект по отрезку, создавая иллюзию перемещения
transform.position = Vector3.Lerp(transform.position, newPoint, Time.time / 0.5f);
}
}
}
Ответы (2 шт):
С корутиной движение не будет плавной, поэтому Update.
Выделить передвижение и задержку в отдельные компетенции.
TimeAction и MoveAction можно использовать везде и на основе TimeAction, как с MoveAction можно написать ещё много самых разнообразных действий.
public class Test : MonoBehaviour {
private void Start () {
MoveToRandomPosition();
}
private void MoveToRandomPosition () {
Vector3 NewPos = new Vector3(Random.Range(-5, 5), Random.Range(-5, 5), Random.Range(-5, 5));
//gameObject.AddComponent<MoveAction>().MoveWithTime(1, NewPos, DelayRandomTime);
gameObject.AddComponent<MoveAction>().MoveWithSpeed(3, NewPos, DelayRandomTime);
}
private void DelayRandomTime () {
float DelayTime = Random.Range(0, 5);
gameObject.AddComponent<TimeAction>().Delay(DelayTime, MoveToRandomPosition);
}
}
public delegate void TimeActionFinish();
public class TimeAction : MonoBehaviour {
protected float ActionTime, ActionTimer;
protected TimeActionFinish Finish;
public virtual void Delay (float time, TimeActionFinish finish) {
ActionTimer = 0;
ActionTime = time;
Finish = finish;
}
private void Update () {
ActionTimer += Time.deltaTime;
float Way = ActionTimer/ActionTime;
if (Way < 1)
UpdateWay(Way);
else {
UpdateWay(1);
if (Finish != null)
Finish();
Destroy(this);
}
}
protected virtual void UpdateWay (float way) { }
}
public class MoveAction : TimeAction {
private Vector3 _moveFrom, _moveTo;
public void MoveWithTime (float time, Vector3 target, TimeActionFinish finish) {
_moveFrom = gameObject.transform.localPosition;
_moveTo = target;
base.Delay(time, finish);
}
public void MoveWithSpeed (float speed, Vector3 target, TimeActionFinish finish) {
MoveWithTime(Vector3.Distance(gameObject.transform.localPosition, target)/speed, target, finish);
}
protected override void UpdateWay (float way) {
transform.localPosition = Vector3.Lerp(_moveFrom , _moveTo , way);
}
}
Движение не плавное потому, что Lerp обрабатывается один раз в конце корутина. Правильней такое перемещение делать в Update, т.к. операция будет выполняться один раз за кадр. Если перемещаемый объект будет взаимодействовать с другими (физика), то перемещать его нужно иначе - через Velocity или Force и обрабатывать в FixedUpdate. В корутине можно сделать плавное движение, но это неправильно с точки зрения оптимизации. Нужно разбить существующий корутин на два:
public class Coroutine : MonoBehaviour
{
// булин для таймера
private bool moved;
// булин для движения
private bool time_out;
// стартовая позиция
private Vector3 startPosition;
// новая позиция объекта
private Vector3 newPoint;
private void Start()
{
// даю начальную позицию
startPosition = transform.position;
time_out = false;
moved = true;
}
private void Update()
{
// указываю новую точку рандомными координатами, от начальной точки
newPoint = new Vector3(
Random.Range(startPosition.x - 5, startPosition.x + 5),
startPosition.y,
Random.Range(startPosition.z + 5, startPosition.z - 5)
);
if (moved)
StartCoroutine(Timer());
// запускаю корутину
if (time_out)
StartCoroutine(MoveCoroutine(newPoint));
}
private IEnumerator Timer()
{
moved = false;
// жду 2 сек
yield return new WaitForSeconds(2f);
time_out = true;
}
private IEnumerator MoveCoroutine(Vector3 moveTo)
{
time_out = false;
// если позиция объекта не равна конечной точки
if (Vector3.Distance(transform.position, moveTo) != float.Epsilon)
{
WaitForEndOfFrame wait = new WaitForEndOfFrame();
// Двигаем объект пока он не передвинется на новую позицию
do
{
// телепортирую объект по отрезку, создавая иллюзию перемещения
transform.position = Vector3.Lerp(transform.position, moveTo, Time.deltaTime);
// ждем до конца кадра
yield return wait;
} while (Vector3.Distance(transform.position, moveTo) < float.Epsilon);
}
moved = true;
}
}