using DG.Tweening; using DG.Tweening.Core; using DG.Tweening.Plugins.Options; using UnityEngine; #if UNITY_EDITOR [ExecuteInEditMode] //[RequireComponent(typeof(Camera))] #endif public class IVCameraController : MonoBehaviour { protected static IVCameraController curMgr = null; protected Transform trfWrapper; protected Transform trfCamera; protected Camera cameraControl; protected bool isShake; [SerializeField] private int _vibatro = 1; // Set this to the in-world distance between the left & right edges of your scene. [SerializeField] protected float sceneWidth = 40f; [SerializeField] protected float[] minZooms = new float[3] { 6.5f, 8f, 9.5f }; [SerializeField] protected float[] maxZooms = new float[3] { 9.5f, 12f, 13.5f }; [SerializeField] protected float maxX = 25f; [SerializeField] protected float maxY = 25f; protected static float[] cameraSize = new float[3] { 10f, 10f, 10f }; protected static float[] fClampXMin = new float[3] { -5f, -5f, -5f }; protected static float[] fClampXMax = new float[3] { 5f, 5f, 5f }; protected static float[] fClampYMin = new float[3] { -20f, -20f, -20f }; protected static float[] fClampYMax = new float[3] { 20f, 20f, 20f }; //protected static Vector3 v3ClampMin = new Vector3(-5f, -20f, -20f); //protected static Vector3 v3ClampMax = new Vector3(5f, 20f, -20f); #if UNITY_EDITOR private bool bInitNeed = true; #endif protected Transform trfTarget; protected bool bTraceTarget = false; protected int iZoom = 1; protected bool isShaking = false; protected float saveStrength; TweenerCore twcMove = null; protected Vector3 v3MoveTo = Vector3.zero; void Start() { curMgr = this; trfWrapper = transform; trfCamera = trfWrapper.GetChild(0); cameraControl = trfCamera.GetComponent(); #if UNITY_EDITOR bInitNeed = false; #endif InitCamera(); } void LateUpdate() { if (cameraControl == null || trfWrapper == null) return; #if UNITY_EDITOR bInitNeed = false; if (bInitNeed) InitCamera(); #endif if (bTraceTarget && trfTarget != null) MoveCamera(trfTarget.position); } // 카메라 초기화. protected void InitCamera() { if (cameraControl == null || trfWrapper == null) return; float unitsPerPixel = sceneWidth / Screen.width; float aspectRatio = (float)Screen.width / Screen.height; cameraSize[1] = 0.5f * unitsPerPixel * Screen.height; cameraSize[0] = cameraSize[1] * 0.8f; cameraSize[2] = cameraSize[1] * 1.2f; for (int i = 0; i < cameraSize.Length; i++) { if (cameraSize[i] > maxZooms[i]) cameraSize[i] = maxZooms[i]; else if (cameraSize[i] < minZooms[i]) cameraSize[i] = minZooms[i]; float fx = maxX - (cameraSize[i] * aspectRatio); fClampXMax[i] = fx; fClampXMin[i] = fx * -1f; float fy = maxY - cameraSize[i]; fClampYMax[i] = fy - 1.5f; // CameraWrapper 안의 mainCamera 위치 고려. fClampYMin[i] = fClampYMax[i] * -1f - 1.5f; } iZoom = ES3.Load(Global.ES3_Zoom, 1); cameraControl.orthographicSize = cameraSize[iZoom]; } // 추적 타겟 설정. public static void SSetTarget(Transform trftarget) { if (curMgr == null) return; curMgr.trfTarget = trftarget; } // 추적 On/Off. public static void SSetTrace(bool btrace) { if (curMgr == null) return; curMgr.bTraceTarget = btrace; } // 카메라 흔들기. public static void SShakeCamera(float fduration, float strength, int ivibrato = 100) { if (curMgr == null || curMgr.trfCamera == null || !curMgr.isShake)// || !curMgr.isShake return; //curMgr.StartCoroutine(curMgr.Shake(fduration, strength)); if(strength > curMgr.saveStrength) { curMgr.isShaking = true; curMgr.saveStrength = strength; curMgr.trfCamera.DOShakePosition(fduration, strength, ivibrato, randomnessMode: ShakeRandomnessMode.Harmonic).OnComplete(curMgr.setFalseShake); // vibrato : 1000, } } public void setFalseShake() { trfCamera.localPosition = Global.V3_Camera; isShaking = false; saveStrength = 0; } public static void SSetShake(bool value) { curMgr.isShake = value; } public static bool SgetShake() { return curMgr.isShake; } public static int SChangeZoom() { if (curMgr == null) return 1; return curMgr.ChangeZoom(); } // 줌 변경. protected int ChangeZoom() { // MoveToCamera로 이동중일 경우. if (twcMove != null && twcMove.IsPlaying()) return iZoom; iZoom++; if (iZoom >= cameraSize.Length) iZoom = 0; ES3.Save(Global.ES3_Zoom, iZoom); cameraControl.orthographicSize = cameraSize[iZoom]; if (bTraceTarget) { //MoveCamera(trfTarget.position); } else { MoveCamera(trfWrapper.position); } return iZoom; } public static int SGetZoom() { if (curMgr == null) return 1; return curMgr.iZoom; } public static void SMoveToCamera(float fduration, Vector3 v3worldpos) { if (curMgr == null || curMgr.trfWrapper == null) return; curMgr.MoveToCamera(fduration, v3worldpos); } // 일정 시간에 걸쳐서 특정 위치로 이동. protected void MoveToCamera(float fduration, Vector3 v3worldpos) { v3MoveTo = v3worldpos; v3worldpos.x = Mathf.Clamp(v3worldpos.x, fClampXMin[iZoom], fClampXMax[iZoom]); v3worldpos.y = Mathf.Clamp(v3worldpos.y, fClampYMin[iZoom], fClampYMax[iZoom]); v3worldpos.z = trfWrapper.position.z; twcMove = trfWrapper.DOMove(v3worldpos, fduration); } public static void SMoveCamera(Vector3 v3worldpos) { if (curMgr == null || curMgr.trfWrapper == null) return; curMgr.MoveCamera(v3worldpos); } // 특정 위치로 바로 이동. protected void MoveCamera(Vector3 v3worldpos) { v3worldpos.x = Mathf.Clamp(v3worldpos.x, fClampXMin[iZoom], fClampXMax[iZoom]); v3worldpos.y = Mathf.Clamp(v3worldpos.y, fClampYMin[iZoom], fClampYMax[iZoom]); v3worldpos.z = trfWrapper.position.z; trfWrapper.position = v3worldpos; } public static void CameraXRangeChange(int x) { curMgr.maxX = x; curMgr.InitCamera(); } }