Moving a 3D object with 2D swipes

I’m trying to move a 3D object in 6 possible directions using 2D swipes. I’ve actually accomplished that but I can only move the object one step. I want the movement to be grid based so whenever there is a swipe i increase the corresponding axis value by 1.

Depending on the length of the swipe, I want to be able to move the object further. I can imagine how to implement that, but there is no point in doing so if the movement in not updated in real time. So my real problem is that the movement only starts after the swipe is over. Also, if there is a change of direction during a swipe, the object should move in that direction too.

I have the feeling that this shouldn’t be so complicated. Maybe there is another way to approach this? Am I reinventing the wheel?

45372-swipes.jpg

Here is my code so far:

using UnityEngine;
using System.Collections;

public enum Swipe {
	None,
	Up,
	Down,
	UpLeft,
	UpRight,
	DownLeft,
	DownRight
};

public class DetectSwipes : MonoBehaviour {
	
	public float MinSwipeLength = 5f;
	public static Swipe SwipeDirection;
	public float ReturnForce = 10f;
	
	private Vector2 _firstPressPos;
	private Vector2 _secondPressPos;
	private Vector2 _currentSwipe;
	
	private Vector2 _firstClickPos;
	private Vector2 _secondClickPos;

	private bool objectSelected = false;
	private GameObject objecte;


	private void Update() {
		//Raycast to find "movable" object
		if (Input.GetMouseButtonDown(0)) {			
			RaycastHit hit;
			Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
			
			if (Physics.Raycast (ray, out hit, 100.0f)) {  
				if(hit.collider.tag == "Movable"){
					objecte = hit.collider.gameObject;
					objectSelected = true;
				}
			}
		}
		if (objectSelected == true) {
			DetectSwipe(objecte);
		}
	}
	
	public void DetectSwipe(GameObject objecte) {

		if ( Input.touches.Length > 0 ) {
			Touch t = Input.GetTouch( 0 );
			
			if ( t.phase == TouchPhase.Began ) {
				_firstPressPos = new Vector2( t.position.x, t.position.y );
			}
			
			if ( t.phase == TouchPhase.Ended ) {
				_secondPressPos = new Vector2( t.position.x, t.position.y );
				_currentSwipe = new Vector3( _secondPressPos.x - _firstPressPos.x, _secondPressPos.y - _firstPressPos.y );
				
				// Make sure it was a legit swipe, not a tap
				if ( _currentSwipe.magnitude < MinSwipeLength ) {
					SwipeDirection = Swipe.None;
					return;
				}
				
				_currentSwipe.Normalize();
				
				// Swipe up
				if ( _currentSwipe.y > 0 && _currentSwipe.x > -0.5f && _currentSwipe.x < 0.5f ) {
					SwipeDirection = Swipe.Up;
					setDirection (SwipeDirection, objecte);
				}
				// Swipe down
				else if ( _currentSwipe.y < 0 && _currentSwipe.x > -0.5f && _currentSwipe.x < 0.5f ) {
					SwipeDirection = Swipe.Down;
					setDirection (SwipeDirection, objecte);
				}
				// Swipe up left
				else if ( _currentSwipe.y > 0 && _currentSwipe.x < 0 ) {
					SwipeDirection = Swipe.UpLeft;
					setDirection (SwipeDirection, objecte);
				}
				// Swipe up right
				else if ( _currentSwipe.y > 0 && _currentSwipe.x > 0 ) {
					SwipeDirection = Swipe.UpRight;
					setDirection (SwipeDirection, objecte);
				}
				// Swipe down left
				else if ( _currentSwipe.y < 0 && _currentSwipe.x < 0 ) {
					SwipeDirection = Swipe.DownLeft;
					setDirection (SwipeDirection, objecte);
					
					// Swipe down right
				} else if ( _currentSwipe.y < 0 && _currentSwipe.x > 0 ) {
					SwipeDirection = Swipe.DownRight;
					setDirection (SwipeDirection, objecte);
				}
			}
		} 
	}
	
	public void setDirection(Swipe swipeDir, GameObject objecte){

		Vector3 objPosition = objecte.transform.position;


		if(swipeDir == Swipe.Up){
			Vector3 newPosition = new Vector3(objPosition.x, objPosition.y + 1, objPosition.z);
			StartCoroutine (moveObject(objecte, newPosition));
		}
		else if(swipeDir == Swipe.Down){
			Vector3 newPosition = new Vector3(objPosition.x, objPosition.y - 1, objPosition.z);
			StartCoroutine (moveObject(objecte, newPosition));
		}
		else if(swipeDir == Swipe.UpLeft){
			Vector3 newPosition = new Vector3(objPosition.x - 1, objPosition.y, objPosition.z);
			StartCoroutine (moveObject(objecte, newPosition));
		}
		else if(swipeDir == Swipe.UpRight){
			Vector3 newPosition = new Vector3(objPosition.x, objPosition.y, objPosition.z + 1);
			StartCoroutine (moveObject(objecte, newPosition));
		}
		else if(swipeDir == Swipe.DownLeft){
			Vector3 newPosition = new Vector3(objPosition.x + 1, objPosition.y, objPosition.z);
			StartCoroutine (moveObject(objecte, newPosition));
		}
		else if (swipeDir == Swipe.DownRight){
			Vector3 newPosition = new Vector3(objPosition.x, objPosition.y, objPosition.z + 1);
			StartCoroutine (moveObject(objecte, newPosition));
		}
	}


	public IEnumerator moveObject(GameObject objecte, Vector3 newPosition) {

		float elapsedTime = 0f;
		Vector3 startPosition = objecte.transform.position;
		float time = 0.1f;

		while (elapsedTime <= time){
			objecte.transform.position = Vector3.Lerp(startPosition, newPosition, elapsedTime/time);
			elapsedTime += Time.fixedDeltaTime;
			yield return null;
		}

		objectSelected = false;
	}
}

“Depending on the length of the swipe, I want to be able to move the object further…my real problem is that the movement only starts after the swipe is over…if there is a change of direction during a swipe, the object should move in that direction too.”

There is a single answer to all these requirements. Or rather, a single change would make satisfying these three requirements a great deal easier. Your “swipe” algorithm needs to stop considering a single gesture, and instead “poll” for the distance / direction of the dragged object until the input state exits.

Entering this state (press finger?) begins the polling process, and exiting the state (lift finger?) ends it, so it’s quite similar. The key difference is how you’ll measure and respond to the input. When the input is one tile-width from the dragged entity’s current tile, it begins moving in the direction suggested by the difference, and will respond to additional movement requests in the most rapid manner possible given your animation requirements.

Depending on if-and-how your camera can move, this may present a new set of challenges, lest you wind up with a ‘flip flop’ situation where the same input position creates a back 'n forth motion. Other challenges will emerge as you try to implement this in your particular scenario. But yeah, this is how I’d recommend approaching these requirements.

Try the following code

      void Update()
	   {
		TakeMouseInput();

	   }

   void TakeMouseInput()
	{
		if(Input.GetMouseButtonDown(0))
		{
			startMousePos = Input.mousePosition;
		}
		if(Input.GetMouseButtonUp(0))
		{
			Vector3 endMousePos = Input.mousePosition;
			SwipeOrTouch(endMousePos);
		}
	}

  void SwipeOrTouch(Vector3 pos)
	{
		Vector3 dir = pos - startMousePos;
		dir.Normalize();
    }

with direction “dir” calculated in hand you can translate your object in that direction. If in case you want drag like situation just replace Input.GetMouseButtonUp with Input.GetMouseButton. Workable on every platform. for 3d the value you get for y place those value as z