Ребята, подскажите, как плавно переместить куб свайпом по оси X на 1 шаг?
Куб имеет Scale 1. Нужно его передвинуть на расстояние равно этому кубу, или на один поинт.
Вот такой код написал, но не работает как надо.
void Update()
{
if (Input.touchCount == 1)
{
Touch screenTouch = Input.GetTouch(0);
if (screenTouch.phase == TouchPhase.Moved)
transform.position = Vector3.Lerp(transform.position, new Vector3 (screenTouch.deltaPosition.normalized.x, transform.position.y, transform.position.z) speed * Time.deltaTime);
}
}
В моем случае куб движется за пальцем, ровно на столько, на сколько я переместил палец, а нужно что бы при любом свайпе он переместился ровно на 1 условный шаг, даже если свайп был коротким.
Так если тебе надо конкретное перемещение, то зачем ты берешь вообще deltaPosition в расчет?
Перемещай сразу на нужное расстояние, как только TouchPhase.Moved обнаружил.
Increaser
Ну на самом деле мне нужно двигать куб или в лево, или в право, в зависимости от свайпа, по-этому использовал нормализованную дельту. Но как оказалась, она мне Не возвращает почему-то единицу.
Но и это не главное. Проблема что перемещение выполнялось постоянно пока есть свайп, а нужно разовое выполнение кода. Переписал код, но все равно не получается строго на единицу двигаться:
void Update()
{
if (Input.touchCount == 1)
{
Touch screenTouch = Input.GetTouch(0);
if (screenTouch.phase == TouchPhase.Moved)
if (Mathf.Abs(screenTouch.deltaPosition.magnitude) > 1)
targetPosition = transform.position;
targetPosition.x += 1f * screenTouch.deltaPosition.normalized.x ;
}
transform.position = Vector3.MoveTowards(transform.position, targetPosition, Time.deltaTime * 2);
}Короче точное перемещение не получается. А в итоге нужно еще что бы движение было и влево и вправо. По идеи это решилось бы так:
targetPosition.x += 1f * screenTouch.deltaPosition.normalized.x;
где screenTouch.deltaPosition.normalized.x давал бы мне единицу с плюсом или с минусом, но что-то работает не так, и перемещение не точное
Попробовал сделать так
targetPosition.x += Mathf.Sign(screenTouch.deltaPosition.x);
Mathf.Sign - возвращает положительную или отрицательную единицу.
Но во время одного свайпа в апдейте эта строчка успеваете выполнится много раз, а нужно один раз за свайп
Ну так добавь флаг какой-нибудь. Как movePhase началась, ставишь флаг в false и до тех пор, пока пользователь не отпустит руку, не сбрасываешь его.
Так у тебя код только один раз выполнится, сколько бы не длился свайп.
Increaser
Дружище, можешь написать пример кода? Я сам не соображу
Что-то такое. Это, конечно, уродство, но для иллюстрации идеи пойдет.
public sealed class MoveSample : MonoBehaviour { private bool _isMoving; private Vector3 _targetPosition; private void Update() { if ( _isMoving) { return; } if ( Input.touchCount > 0 && Input.GetTouch( 0).phase == TouchPhase.Moved) { _isMoving = true; if ( Input.GetTouch( 0).deltaPosition.x > 0) { _targetPosition = new Vector3( transform.position.x + 1, transform.position.y, transform.position.z); StartCoroutine( MoveRight( )); } else { _targetPosition = new Vector3( transform.position.x - 1, transform.position.y, transform.position.z); StartCoroutine( MoveLeft( )); } } } private IEnumerator MoveRight( ) { while ( transform.position != _targetPosition) { var targetX = transform.position.x + Time.deltaTime; if ( targetX > _targetPosition.x) { targetX = _targetPosition.x; } transform.position = new Vector3( targetX, transform.position.y, transform.position.z); yield return null; } _isMoving = false; } private IEnumerator MoveLeft( ) { //аналогично } }
Вообще рекомендую для всяких движений использовать твинер, например вот этот, чтобы не городить кастомные велосипеды там где это не надо
https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676
Тогда весь стриптиз выше превратится в что-то более удобоваримое
public sealed class MoveSample : MonoBehaviour { private bool _isMoving; private void Update() { if ( _isMoving) { return; } if ( Input.touchCount > 0 && Input.GetTouch( 0).phase == TouchPhase.Moved) { _isMoving = true; var delta = Mathf.Sign( Input.GetTouch( 0).deltaPosition.x); var targetPosition = new Vector3( transform.position.x + delta, transform.position.y, transform.position.z); transform.DOMove( targetPosition, 1f) .OnComplete( ( ) => _isMoving = false); } } }
Increaser
Дружище, спасибо огромное! Жму руку!
Increaser
Собрал сцену, все работает. Осталось только сделать так, что бы одни кубы могли двигаться только по X, другие по Z, и что бы не наезжали на друг друга. Еще раз спасибо!
Подскажи, а можно сделать движение от слабого свайпа на 1 шаг, а от сильного на 2 шага?
Vadimicus
Слабого по скорости или по расстоянию?
Increaser
> Слабого по скорости или по расстоянию?
По расстоянию
Ну в таком случае можно считать расстояние deltaPosition и при достижении конца первого движения добавить еще одно передвижение. Если ты использовал второй вариант, то по достижении OnComplete можешь передать туда функцию проверки, которая в случае превышения порога повторит тот же самый код со сдвигом.
Если первый вариант, то там можно targetPosition сделать переменной уровня класса, и в апдейте смотреть дельту. Если она превысила порог, то добавить еще единицу к targetPosition.x