Движение объекта по свайпу.(Unity 2d)
Есть код с помощью которого объект по свайпу двигается вправо, влево, вверх, вниз без остановки. Но почему то объект нормально двигается только вверх и вниз. А вправо и влево не всегда. Как это можно исправить. Спасибо заранее.
Код:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmoothMove : MonoBehaviour
{
private Vector2 startTouchPosition, endTouchPosition;
private Vector3 startRocketPosition, endRocketPosition;
private float flyTime;
private float flightDuration = 100f;
// Update is called once per frame
private void Update()
{
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
startTouchPosition = Input.GetTouch(0).position;
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
{
endTouchPosition = Input.GetTouch(0).position;
if ((endTouchPosition.x < startTouchPosition.x) && transform.position.x > -100f)
StartCoroutine(Fly("left"));
if ((endTouchPosition.x > startTouchPosition.x) && transform.position.x < 100f)
StartCoroutine(Fly("right"));
if ((endTouchPosition.y > startTouchPosition.y) && transform.position.y < 100f)
StartCoroutine(Fly("up"));
if ((endTouchPosition.y < startTouchPosition.y) && transform.position.y > -100f)
StartCoroutine(Fly("down"));
}
}
private IEnumerator Fly(string whereToFly)
{
switch (whereToFly)
{
case "left":
flyTime = 0f;
startRocketPosition = transform.position;
endRocketPosition = new Vector3
(startRocketPosition.x - 100f, transform.position.y, transform.position.z);
while (flyTime < flightDuration)
{
flyTime += Time.deltaTime;
transform.position = Vector2.Lerp
(startRocketPosition, endRocketPosition, flyTime / flightDuration);
yield return null;
}
break;
case "right":
flyTime = 0f;
startRocketPosition = transform.position;
endRocketPosition = new Vector3
(startRocketPosition.x + 100f, transform.position.y, transform.position.z);
while (flyTime < flightDuration)
{
flyTime += Time.deltaTime;
transform.position = Vector2.Lerp
(startRocketPosition, endRocketPosition, flyTime / flightDuration);
yield return null;
}
break;
case "up":
flyTime = 0f;
startRocketPosition = transform.position;
endRocketPosition = new Vector3
(startRocketPosition.x, transform.position.y + 100f, transform.position.z);
while (flyTime < flightDuration)
{
flyTime += Time.deltaTime;
transform.position = Vector2.Lerp
(startRocketPosition, endRocketPosition, flyTime / flightDuration);
yield return null;
}
break;
case "down":
flyTime = 0f;
startRocketPosition = transform.position;
endRocketPosition = new Vector3
(startRocketPosition.x, transform.position.y - 100f, transform.position.z);
while (flyTime < flightDuration)
{
flyTime += Time.deltaTime;
transform.position = Vector2.Lerp
(startRocketPosition, endRocketPosition, flyTime / flightDuration);
yield return null;
}
break;
}
}
}
Ответы (2 шт):
Автор решения: r1kki
→ Ссылка
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
{
endTouchPosition = Input.GetTouch(0).position;
string flyType = "";
if ((endTouchPosition.x < startTouchPosition.x) && transform.position.x > -100f)
flyType = "left";
if ((endTouchPosition.x > startTouchPosition.x) && transform.position.x < 100f)
flyType = "right";
if ((endTouchPosition.y > startTouchPosition.y) && transform.position.y < 100f)
flyType = "up";
if ((endTouchPosition.y < startTouchPosition.y) && transform.position.y > -100f)
flyType = "down";
StartCoroutine(Fly(flyType));
}
Автор решения: Yaroslav
→ Ссылка
Свайп и движение это две абсолютно разные и независимые друг от друга ответственности. Они не должны знать о существовании друг друга. Мухи отдельно, котлеты отдельно.
public interface ISwipeTarget
{
void OnSwipe (Vector2 side);
}
public class Swipe : MonoBehaviour
{
[SerializeField] private float _swipeDistance = 10f;
[SerializeField] private GameObject _inputTarget; // кому посылаем импуты
private ISwipeTarget _target;
private Vector2 _touchDownPosition;
private bool _swipe;
private void Start ()
{
if (_inputTarget != null)
_target = _inputTarget.GetComponent<ISwipeTarget>();
}
private void Update ()
{
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
Touch Touch0 = Input.GetTouch(0);
switch (Touch0.phase)
{
case TouchPhase.Began:
_touchDownPosition = Touch0.position;
_swipe = true;
break;
case TouchPhase.Ended:
_swipe = false;
break;
case TouchPhase.Moved:
if (Vector2.Distance(_touchDownPosition, Touch0.position) > _swipeDistance) {
Vector2 Vector = Touch0.position-_touchDownPosition;
// надо опредилить куда сместилось больше, по X или Y
if (Math.Abs(Vector.x) > Math.Abs(Vector.y))
OnSwipe(Vector.x > 0 ? Vector2.right : Vector2.left);
else
OnSwipe(Vector.y > 0 ? Vector2.up : Vector2.down);
_swipe = false;
}
break;
}
}
}
private void OnSwipe (Vector2 side)
{
if (_target != null)
_target.OnSwipe(side);
}
}
public class Move : MonoBehaviour, ISwipeTarget
{
[SerializeField] private float _time = 1f;
[SerializeField] private float _distance = 100f;
// с кривой как-то красивше
[SerializeField] private AnimationCurve _curve = new AnimationCurve(new[] { new Keyframe(0, 0, 2, 2), new Keyframe(1, 1, 0, 0) });
private Transform _transform;
private IEnumerator _courutine;
private void Awake ()
{
_transform = transform;
}
public void OnSwipe (Vector2 side)
{
// запуск новой корутины не останавливает предыдущюю
if (_moveCourutine != null)
StopCoroutine(_courutine);
_courutine = Coroutine(side);
StartCoroutine(_courutine);
}
private IEnumerator Coroutine (Vector2 side)
{
Vector3 Start = _transform.position;
Vector3 Finish = Start+(Vector3)side*_distance;
float Timer = 0;
while (Timer < _time)
{
float Way = Timer/_time;
float WayCurve = _curve.Evaluate(Way);
_transform.position = Vector2.Lerp(Start, Finish, WayCurve);
Timer += Time.deltaTime;
yield return null;
}
_transform.position = Finish;
}
}