The Room-style camera transitions

These two scripts allow for touch-screen pinching and double-tapping to move forward and backward between different cameras that are focused on different Hotspots - behaviour popularised by The Room series of mobile games.
 * 1) Set the "Movement method" to "None"
 * 2) Create a new Tag named CameraHotspot
 * 3) For any Hotspot you want to be able to focus on with its own camera, create either a SimpleCamera or Advanced Third Person Camera (available from AC's Downloads page), and attach the Camera Zoom component to it.
 * 4) In this Camera Zoom component, assign the Hotspot it is intended for, as well as (optionally) a camera to switch to if when pinching out in the "Exit Camera" field.
 * 5) Create an ActionList asset named "SwitchCamera", and define a GameObject parameter named "New camera".
 * 6) In the ActionList, create a "Camera: Switch" Action with a 2s transition, and override the "New camera" field with the parameter.
 * 7) Add the GestureHotspot component to either a scene object, or a spawned prefab e.g. a custom EventSystem assigned in the Menu Manager
 * 8) In this component, assign "SwitchCamera" as the "Switch Camera Action List", and tweak the other fields to suit

You should now be able to double-click / double-tap Hotspots to transition to their associated camera, as well as screen-pinch / scroll the middle-mouse button to transition back and forth.

CameraZoom.cs: using UnityEngine; namespace AC { public class CameraZoom : MonoBehaviour { 		#region Variables [SerializeField] private Hotspot associatedHotspot = null; [SerializeField] private _Camera exitCamera = null; private Camera _camera; private float originalFOV; private float targetZoom; private LerpUtils.FloatLerp zoomLerp = new LerpUtils.FloatLerp ; private const float zoomSpeed = 5f; #endregion #region UnityStandards private void Start { 			if (associatedHotspot != null) { 				associatedHotspot.gameObject.tag = GestureHotspot.cameraHotspotTag; } 			_camera = GetComponentInChildren  ; originalFOV = _camera.fieldOfView; targetZoom = 0f; } 		private void OnEnable { 			EventManager.OnSwitchCamera += OnSwitchCamera; } 		private void OnDisable { 			EventManager.OnSwitchCamera -= OnSwitchCamera; } 		private void Update { 			if (KickStarter.mainCamera.attachedCamera.Camera == _camera) { 				_camera.fieldOfView = zoomLerp.Update (_camera.fieldOfView, originalFOV + targetZoom, zoomSpeed); } 		}  		#endregion #region PublicFunctions public void SetZoomAmount (float amount) { 			targetZoom = amount; } 		#endregion #region PrivateFunctions private void OnSwitchCamera (_Camera fromCamera, _Camera toCamera, float transitionTime) { 			if (toCamera == _camera) { 				targetZoom = 0f; zoomLerp.Reset ; _camera.fieldOfView = originalFOV; } 		}  		#endregion #region GetSet public _Camera ExitCamera { 			get { 				return exitCamera; } 		}  		#endregion } }

GestureHotspot.cs: using UnityEngine; using System.Collections.Generic; namespace AC { public class GestureHotspot : MonoBehaviour { 		#region Variables [Header("Pinching")] [SerializeField] private float pinchThreshold = 0.2f; [SerializeField] private float doubleTapWindow = 0.3f; [SerializeField] private float sphereCastRadius = 0.2f; [Header("Zooming")] [SerializeField] private AnimationCurve zoomCurve = new AnimationCurve (new Keyframe(-1, -1), new Keyframe(1, 1)); [SerializeField] private float zoomFactor = 3f; [Header ("Interactions")] [SerializeField] private ActionListAsset switchCameraActionList = null; private float doubleTimeActive; private LayerMask hotspotLayerMask; private Vector2 lastTapPosition; public const string cameraHotspotTag = "CameraHotspot"; private bool isPinching = false; private float startPinchDistance; private CameraZoom activeCameraZoom; #endregion #region UnityStandards private void Start { 			hotspotLayerMask = 1 << LayerMask.NameToLayer (KickStarter.settingsManager.hotspotLayer); } 		private void OnEnable { 			EventManager.OnSwitchCamera += OnSwitchCamera; } 		private void OnDisable { 			EventManager.OnSwitchCamera -= OnSwitchCamera; } 		private void Update { 			if (doubleTimeActive > 0f) { 				doubleTimeActive -= Time.deltaTime; } 			if (!KickStarter.stateHandler.IsInGameplay ) { 				isPinching = false; return; } 			if (Input_StartPinch) { 				isPinching = true; startPinchDistance = 0f; } 			else if (Input_EndPinch) { 				isPinching = false; } 			if (isPinching) { 				float currentPinchDistance = Input_PinchDistance; if (startPinchDistance == 0f) { 					startPinchDistance = currentPinchDistance; } 				float pinchDistance = (currentPinchDistance - startPinchDistance) / Screen.dpi; float relativePinchDistance = Mathf.Clamp (pinchDistance / pinchThreshold, -1f, 1f); if (activeCameraZoom != null) { 					SetZoomAmount (-relativePinchDistance); } 				if (relativePinchDistance >= 1f) { 					ActivateHotspot (new Vector2 (ACScreen.width / 2f, ACScreen.height / 2f), true); } 				else if (relativePinchDistance <= -1f) { 					ExitCurrentCamera ; } 				return; } 			else if (activeCameraZoom != null) { 				SetZoomAmount (0f); } 			if (Input_Tap) { 				if (doubleTimeActive > 0f) { 					doubleTimeActive = 0f; ActivateHotspot (lastTapPosition, true); } 				else { 					doubleTimeActive = doubleTapWindow; ActivateHotspot (lastTapPosition, false); } 			}  		}  		#endregion #region PrivateFunctions private void ActivateHotspot (Vector2 screenPosition, bool cameraHotspots = false) { 			Ray ray = KickStarter.CameraMain.ScreenPointToRay (screenPosition); RaycastHit raycastHit; if (cameraHotspots) { 				if (Physics.SphereCast (ray, sphereCastRadius, out raycastHit, KickStarter.settingsManager.hotspotRaycastLength, hotspotLayerMask)) { 					if (raycastHit.collider.tag != cameraHotspotTag) return; Hotspot hotspot = raycastHit.collider.GetComponent ; if (hotspot != null) { 						hotspot.RunUseInteraction ; } 				}  			}  			else { 				if (Physics.Raycast (ray, out raycastHit, KickStarter.settingsManager.hotspotRaycastLength, hotspotLayerMask)) { 					if (raycastHit.collider.tag == cameraHotspotTag) return; Hotspot hotspot = raycastHit.collider.GetComponent ; if (hotspot != null) { 						hotspot.RunUseInteraction ; } 				}  			}  		}  		private void OnSwitchCamera (_Camera fromCamera, _Camera toCamera, float transitionTime) { 			SetZoomAmount (0f); activeCameraZoom = toCamera.GetComponent ; AdvancedThirdPersonCamera fromTPCam = fromCamera as AdvancedThirdPersonCamera; AdvancedThirdPersonCamera toTPCam = toCamera as AdvancedThirdPersonCamera; if (fromTPCam != null && toTPCam == null) { 				fromTPCam.BeginAutoMove (1f, fromTPCam.GenerateTargetAngles (toCamera.Camera.transform), false); } 		}  		private void SetZoomAmount (float amount) { 			if (activeCameraZoom != null) { 				float zoomAmount = zoomCurve.Evaluate (amount); activeCameraZoom.SetZoomAmount (zoomAmount * zoomFactor); } 		}  		private void ExitCurrentCamera { 			if (activeCameraZoom != null && switchCameraActionList != null) { 				_Camera exitCamera = activeCameraZoom.ExitCamera; if (exitCamera != null) { 					List newParameterValues = new List ; ActionParameter newParameter = new ActionParameter (switchCameraActionList.DefaultParameters[0]); newParameter.SetValue (exitCamera.gameObject); newParameterValues.Add (newParameter); switchCameraActionList.AssignParameterValues (newParameterValues); switchCameraActionList.Interact ; } 			}  		}  		#endregion #region GetSet private bool Input_Tap { 			get { 				#if MOBILE_INPUT if (Input.touchCount == 1 && Input.GetTouch (0).phase == TouchPhase.Began) { 					lastTapPosition = Input.GetTouch (0).position; return true; } 				#else if (Input.GetMouseButtonDown (0)) { 					lastTapPosition = Input.mousePosition; return true; } 				#endif return false; } 		}  		private float Input_PinchDistance { 			get { 				#if MOBILE_INPUT return (Input.GetTouch (0).position - Input.GetTouch (1).position).magnitude; #else return Input.mousePosition.y; 				#endif } 		}  		private bool Input_StartPinch { 			get { 				if (isPinching) return false; #if MOBILE_INPUT return Input.touchCount == 2 && Input.GetTouch (1).phase == TouchPhase.Began; #else return Input.GetMouseButtonDown (2); #endif } 		}  		private bool Input_EndPinch { 			get { 				if (!isPinching) return false; #if MOBILE_INPUT return (Input.touchCount != 2); #else return !Input.GetMouseButton (2); #endif } 		}  		#endregion } }
 * 1) if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR
 * 2) define MOBILE_INPUT
 * 3) endif