Adventure Creator Wikia

NOTE: This script has been incorporated into the "UI template: Mobile joystick" package on AC's Downloads page.

This script improves the Direct and First Person on mobile devices by separating player and camera movement on different sides of the screen - with drags on the left moving the Player, and drags on the right moving the Camera.

To use it for Direct movement:

  • In the Settings Manager, set Movement method to Direct, Input method to Touch Screen, and Direct movement to Custom Input.
  • Assign a GameCamera Third-person Camera type, uncheck Is drag-controlled?, and set the Spin and Pitch input axes to CameraSpin and CameraPitch respectively (these need not be added to Unity's Input Manager)
  • Copy/paste the script below into a C# file named DragCameraAndPlayer.cs, add to the scene, and assign your camera in its GameCamera Third Person Inspector field.
  • To tweak the drag distance that causes the Player to run, adjust the Player Run Threshold field in the Drag Camera And Player component's Inspector.
  • To tweak the camera speed, adjust the Input influence fields in the GameCamera Third-person component's Inspector.

To use it for First Person movement:

  • In the Settings Manager, set Movement method to First Person, Input method to Touch Screen, and First-person movement to Custom Script.
  • Add a First-person Camera to your Player as normal, following the steps in this tutorial.
  • Copy/paste the script below into a C# file named DragCameraAndPlayer.cs, and add to the scene.
  • To tweak the drag distance that causes the Player to run, adjust the Player Run Threshold field in the Drag Camera And Player component's Inspector.
  • To tweak the camera speed, adjust the Freelook sensitivity values in the First Person Camera component's Inspector.


DragCameraAndPlayer.cs:

using UnityEngine;
using AC;

public class DragCameraAndPlayer : MonoBehaviour
{

	private readonly TouchData cameraTouch = new TouchData (true, false, 1f);
	private readonly TouchData playerTouch = new TouchData (false, true, 1f);

	[SerializeField] private float playerRunThreshold = 0.2f;
	private const string playerHorizontalAxis = "Horizontal";
	private const string playerVerticalAxis = "Vertical";
	private const string runAxis = "Run";

	[SerializeField] private GameCameraThirdPerson gameCameraThirdPerson = null;

	private int cursorFingerID = -1;
	private Vector2 lastCursorPosition;


	private void Start ()
	{
		KickStarter.playerInput.InputGetAxisDelegate = InputGetAxis;
		KickStarter.playerInput.InputGetButtonDelegate = InputGetButton;
		KickStarter.playerInput.InputMousePositionDelegate = InputMousePosition;
		KickStarter.playerInput.InputGetFreeAimDelegate = InputGetFreeAimDelegate;
	}


	private void Update ()
	{
		cameraTouch.Update ();
		playerTouch.Update ();

		UpdateCursor ();
	}


	private void UpdateCursor ()
	{
		if (cursorFingerID < 0)
		{
			for (int i = 0; i < Input.touchCount; i++)
			{
				Touch touch = Input.GetTouch (i);
				if (touch.phase == TouchPhase.Began)
				{
					lastCursorPosition = touch.position;
					cursorFingerID = touch.fingerId;
					return;
				}
			}
			return;
		}

		for (int i = 0; i < Input.touchCount; i++)
		{
			if (Input.GetTouch (i).fingerId == cursorFingerID && Input.GetTouch (i).phase != TouchPhase.Ended)
			{
				return;
			}
		}
		cursorFingerID = -1;
	}


	private Vector2 InputMousePosition (bool isLocked)
	{
		if (isLocked)
		{
			return KickStarter.playerInput.LockedCursorPosition;
		}

		if (cursorFingerID >= 0)
		{
			for (int i = 0; i < Input.touchCount; i++)
			{
				if (Input.GetTouch (i).fingerId == cursorFingerID)
				{
					lastCursorPosition = Input.GetTouch (i).position;
				}
			}
			return lastCursorPosition;
		}
		return Input.mousePosition;
	}


	private bool InputGetButton (string axis)
	{
		if (!InvInstance.IsValid (KickStarter.runtimeInventory.SelectedInstance) && axis == runAxis)
		{
			return (playerTouch.GetDragVector ().magnitude / ACScreen.LongestDimension) > playerRunThreshold;
		}

		try { return Input.GetButton (axis); }
		catch { return false; }
	}


	private float InputGetAxis (string axis)
	{
		if (!InvInstance.IsValid (KickStarter.runtimeInventory.SelectedInstance))
		{
			if (gameCameraThirdPerson && axis == gameCameraThirdPerson.spinAxis)
			{
				return cameraTouch.GetDragVector ().x;
			}
			else if (gameCameraThirdPerson && axis == gameCameraThirdPerson.pitchAxis)
			{
				return cameraTouch.GetDragVector ().y;
			}
			else if (axis == playerHorizontalAxis)
			{
				return playerTouch.GetDragVector ().x;
			}
			else if (axis == playerVerticalAxis)
			{
				return playerTouch.GetDragVector ().y;
			}
		}

		try { return Input.GetAxis (axis); }
		catch { return 0f; }
	}


	private Vector2 InputGetFreeAimDelegate (bool cursorIsLocked)
	{
		return cameraTouch.GetDragVector () * 0.0005f;
	}



	private class TouchData
	{

		public int fingerID = -1;
		public Vector2 startPosition;
		private readonly bool OnRightSide;
		private readonly bool DragIsRelative;
		private readonly float DragScaler;


		public TouchData (bool onRightSide, bool dragIsRelative, float dragScaler)
		{
			OnRightSide = onRightSide;
			DragIsRelative = dragIsRelative;
			DragScaler = dragScaler;
		}


		public void Update ()
		{
			if (fingerID == -1)
			{
				fingerID = GetBeginningTouchIndex ();
				if (fingerID >= 0)
				{
					startPosition = GetTouchPosition ();
				}
			}
			else
			{
				if (!IsStillTouching ())
				{
					fingerID = -1;
				}
			}
		}


		public Vector2 GetDragVector ()
		{
			if (DragIsRelative)
			{
				return fingerID >= 0 ? (GetTouchPosition () - startPosition) * DragScaler : Vector2.zero;
			}
			return fingerID >= 0 ? GetTouchDrag () * DragScaler : Vector2.zero;
		}


		private int GetBeginningTouchIndex ()
		{
#if !UNITY_EDITOR
			for (int i = 0; i < Mathf.Min (2, Input.touchCount); i++)
			{
				Touch touch = Input.GetTouch (i);
				if (touch.phase == TouchPhase.Began && (OnRightSide == touch.position.x > ACScreen.width / 2f))
				{
					return touch.fingerId;
				}
			}
#else
			if (Input.GetMouseButtonDown (0) && (OnRightSide == Input.mousePosition.x > ACScreen.width / 2f))
			{
				return 0;
			}
#endif
			return -1;
		}


		private bool IsStillTouching ()
		{
#if !UNITY_EDITOR
			for (int i = 0; i < Input.touchCount; i++)
			{
				Touch touch = Input.GetTouch (i);
				if (touch.fingerId == fingerID && touch.phase != TouchPhase.Ended)
				{
					return true;
				}
			}
			return false;
#else
			return Input.GetMouseButton (0);
#endif
		}


		private Vector2 GetTouchPosition ()
		{
#if !UNITY_EDITOR
			for (int i = 0; i < Input.touchCount; i++)
			{
				Touch touch = Input.GetTouch (i);
				if (touch.fingerId == fingerID)
				{
					return touch.position;
				}
			}
			return startPosition;
#else
			return (Vector2) Input.mousePosition;
#endif
		}


		private Vector2 GetTouchDrag ()
		{
#if !UNITY_EDITOR
			for (int i = 0; i < Input.touchCount; i++)
			{
				Touch touch = Input.GetTouch (i);
				if (touch.fingerId == fingerID)
				{
					return touch.deltaPosition;
				}
			}
			return Vector2.zero;
#else
			return GetTouchPosition () - startPosition;
#endif
		}

	}

}