using System.Collections.Generic; using UnityEngine; using static UnityEngine.GraphicsBuffer; public class RealCamera : MyCoroutine { [Header("Camera Properties")] private float DistanceAway; //how far the camera is from the player. public float minDistance = 1; //min camera distance public float maxDistance = 2; //max camera distance public float DistanceUp = -2; //how high the camera is above the player public float smooth = 4.0f; //how smooth the camera moves into place public float rotateAround = 70f; //the angle at which you will rotate the camera (on an axis) public Vector3 m_LookAt = Vector3.up; public Vector3 m_BackOffSet = new Vector3(0f, 0.1f, -0.2f); [HideInInspector] public bool m_BackMove; [Header("Player to follow")] public Transform target; //the target the camera follows Actor m_Target; bool isTarget; [Header("Layer(s) to include")] public LayerMask CamOcclusion; //the layers that will be affected by collision [Header("Map coordinate script")] // public worldVectorMap wvm; public float cameraHeight = 55f; public float cameraPan = 0f; float camRotateSpeed = 180f; Vector3 camPosition; Vector3 camMask; float OriminDistance, OrimaxDistance, OriDistanceUp, OricameraHeight; private float HorizontalAxis, VerticalAxis; int CamStatus = 1; // 0 초기, 1 평소, 2 건물 내부 float DragEndTime; GameObject godummy, gowitch; List list_tfCamactionTarget = new List(); bool islockTarget; Transform tf_lockTarget; private void Awake() { OriminDistance = minDistance; OrimaxDistance = maxDistance; OriDistanceUp = DistanceUp; OricameraHeight = cameraHeight; } public bool IsEnter() { return CamStatus == 0; } public void Set_Target(Transform _target) { target = _target; isTarget = target; if (isTarget) { m_Target = target.GetComponent(); Add_CamActionTarget(_target); } } public void Set_Target(Transform _target, float _camrot) { Set_Target(_target); CamStatus = 0; rotateAround = _camrot; Set_DistanceUp(false); VerticalAxis = maxDistance = OrimaxDistance; } public void Set_DistanceUp(bool vertical) { DistanceUp = vertical ? 0f : OriDistanceUp; } public void Set_InsideBuilding(bool _active) { if (_active) { OriminDistance = minDistance; OrimaxDistance = maxDistance; OriDistanceUp = DistanceUp; OricameraHeight = cameraHeight; maxDistance = minDistance = 2f; DistanceUp = 1.5f; cameraHeight = 25f; } else { minDistance = OriminDistance; VerticalAxis = maxDistance = OrimaxDistance; Set_DistanceUp(false); cameraHeight = OricameraHeight; } } public void Add_CamActionTarget(Transform _target) { list_tfCamactionTarget.Add(_target); } public void Set_LockTarget(Transform locktarget) { tf_lockTarget = locktarget; islockTarget = tf_lockTarget; } public void Set_TargetShow(Transform _target) { if (CamStatus != 0 && isTarget) { // 매개변수 타겟을 보게 카메라 회전 Set_CamDummy(_target); Set_Coroutine(() => { rotateAround = godummy.transform.eulerAngles.y - 45f; }, 0.1f); } } void Set_CamDummy(Transform _target) { if (godummy == null) godummy = new GameObject("CamDummy"); godummy.transform.position = target.position; godummy.transform.LookAt(_target); } public void Set_Axis(bool _horizontal, float _value) { DragEndTime = 1f; if (_horizontal) HorizontalAxis = _value; else VerticalAxis = _value; //NewGameUI.Ins.m_GuideQuestUI.Add_GuideQuest(ePurpose.ScreenRot); } public void Set_AutoCam_byMyPC() { if (DragEndTime <= 0f) { if (DSUtil.CheckNull(gowitch)) gowitch = new GameObject("witchDummy"); gowitch.transform.position = MyValue.MyPC.Get_position() + MyValue.MyPC.transform.forward; Set_TargetShow(gowitch.transform); } } // Use this for initialization void Start() { //the statement below automatically positions the camera behind the target. //rotateAround = target.eulerAngles.y - 45f; } void LateUpdate() { if (DragEndTime > 0f) DragEndTime -= Time.deltaTime; if (!isTarget) return; //if (m_Target.Get_CurAnim() == eAnim.Attack) return; // 캐릭터의 이동 방향 계산 //Vector3 direction = target.position - previousPosition; //// 이동 방향이 존재할 때 캐릭터가 보는 방향으로 카메라 회전 //if (direction.sqrMagnitude > 0.01f) //{ // // 캐릭터가 움직이고 있는 방향으로 회전 목표 각도 계산 // float targetRotationAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg; // // 현재 회전 각도에서 목표 회전 각도로 부드럽게 보간 // rotateAround = Mathf.LerpAngle(rotateAround, targetRotationAngle, rotationSpeed * Time.deltaTime); //} // 카메라를 설정된 로직에 따라 업데이트 if (CamStatus == 0) { var camTarget = list_tfCamactionTarget[0]; Vector3 lTargetDir = camTarget.position - transform.position; transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(lTargetDir + m_LookAt), Time.deltaTime * 2.5f); Vector3 targetOffset = target.position; Quaternion rotation = Quaternion.Euler(cameraHeight, rotateAround, cameraPan); Vector3 vectorMask = Vector3.one; Vector3 rotateVector = rotation * vectorMask; DistanceAway = Mathf.Clamp(DistanceAway += VerticalAxis, minDistance, maxDistance); camPosition = targetOffset + Vector3.up * DistanceUp - rotateVector * DistanceAway; //transform.position = Vector3.Lerp(transform.position, camPosition, Time.deltaTime * 2.5f); transform.position = Vector3.Lerp(transform.position, camPosition, 1f); // 즉시 이동 if (Vector3.Distance(transform.position, camPosition) < 0.05f) { list_tfCamactionTarget.RemoveAt(0); if (list_tfCamactionTarget.Count <= 0) { CamStatus = 1; Start_Game(); } } } else if (CamStatus == 1) Update_Cam(); } void Start_Game() { ActorInfo.Ins.All_Stop(false); Time.timeScale = MyValue.Get_GameSpeed(); DungeonInfo.Ins.Start_Dungeon(true); } void Update_Cam() { Vector3 targetOffset = target.position; Quaternion rotation = Quaternion.Euler(cameraHeight, rotateAround, cameraPan); Vector3 vectorMask = Vector3.one; Vector3 rotateVector = rotation * vectorMask; camPosition = targetOffset + Vector3.up * DistanceUp - rotateVector * DistanceAway; camMask = targetOffset + Vector3.up * DistanceUp - rotateVector * DistanceAway; //occludeRay(ref targetOffset); transform.position = Vector3.Lerp(transform.position, camPosition, Time.deltaTime * smooth); if (m_BackMove) { Vector3 backOffsetDirection = -transform.forward.normalized * m_BackOffSet.z; transform.position += new Vector3(backOffsetDirection.x, 0f, backOffsetDirection.z); } if (islockTarget) { Set_CamDummy(tf_lockTarget); rotateAround = godummy.transform.eulerAngles.y - 45f; } transform.LookAt(target.position + m_LookAt); #region wrap the cam orbit rotation if (rotateAround > 360) rotateAround = 0f; else if (rotateAround < 0f) rotateAround += 360f; #endregion rotateAround += HorizontalAxis * camRotateSpeed * Time.deltaTime; if (HorizontalAxis >= -0.1f || HorizontalAxis <= 0.1f) HorizontalAxis = 0f; //DistanceUp = Mathf.Clamp(DistanceUp += VerticalAxis, -0.79f, 2.3f); DistanceAway = Mathf.Clamp(DistanceAway += VerticalAxis, minDistance, maxDistance); if (VerticalAxis >= -0.1f || VerticalAxis <= 0.1f) VerticalAxis = 0f; } void occludeRay(ref Vector3 targetFollow) { #region prevent wall clipping //declare a new raycast hit. //linecast from your player (targetFollow) to your cameras mask (camMask) to find collisions. if (Physics.Linecast(targetFollow, camMask, out RaycastHit wallHit, CamOcclusion)) { if (wallHit.collider.tag == "Untagged" && wallHit.collider.GetComponent() == null && (wallHit.collider.GetComponent() != null || wallHit.collider.GetComponent() != null || wallHit.collider.GetComponent() != null)) { //the smooth is increased so you detect geometry collisions faster. smooth = 10f; //the x and z coordinates are pushed away from the wall by hit.normal. //the y coordinate stays the same. camPosition = new Vector3(wallHit.point.x + wallHit.normal.x * 0.5f, camPosition.y, wallHit.point.z + wallHit.normal.z * 0.5f); } } else smooth = 4f; #endregion } }