using System; using System.Collections; using UnityEngine; public class WorldSwitcher : MonoBehaviour { [Range(0, 5)] [SerializeField] float transitionDuration; [SerializeField] AnimationCurve transitionCurve; [SerializeField] Camera[] cameras; [SerializeField] Transform renderQuad; [SerializeField] float quadOffset; int lastWorldIndex; int currentWorldIndex; Coroutine transition; RenderTexture renderTexture; Material renderMaterial; void Awake() { if (cameras.Length <= 1) Debug.LogWarning("WorldSwitcher should have multiple cameras"); currentWorldIndex = 0; lastWorldIndex = 0; renderMaterial = renderQuad.GetComponent().material; GenerateRenderTexture(); } public void SwitchWorld(int index) { if (index == currentWorldIndex) return; if (index < 0 || index >= cameras.Length) throw new IndexOutOfRangeException($"{index} is not an available world."); lastWorldIndex = currentWorldIndex; currentWorldIndex = index; Camera currCam = cameras[currentWorldIndex]; currCam.enabled = true; //TODO Block window resize during transition? if (Screen.width != renderTexture.width || Screen.height != renderTexture.height) GenerateRenderTexture(); currCam.targetTexture = renderTexture; renderQuad.localScale = new Vector3(cameras[lastWorldIndex].aspect, 1f, 1f); transition = StartCoroutine(TransitionCamera()); } void OnGUI() { for (int i = 0; i < cameras.Length; ++i) { if (i == currentWorldIndex) continue; if (GUILayout.Button($"World {i}")) SwitchWorld(i); } } IEnumerator TransitionCamera() { float startTime = Time.time; Transform lastCam = cameras[lastWorldIndex].transform; while (Time.time < startTime + transitionDuration) { float t = transitionCurve.Evaluate((Time.time - startTime) / transitionDuration); renderQuad.position = lastCam.position + Vector3.forward * quadOffset + Vector3.right * (2f * t - 2f); yield return null; } cameras[currentWorldIndex].targetTexture = null; cameras[lastWorldIndex].enabled = false; transition = null; } void GenerateRenderTexture() { renderTexture = new RenderTexture(Screen.width, Screen.height, 32); renderMaterial.mainTexture = renderTexture; } }