using System; using System.Collections.Generic; using Blobcreate.ProjectileToolkit; using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.InputSystem; // ReSharper disable once CheckNamespace namespace BlueWaterProject { [RequireComponent(typeof(Rigidbody))] [RequireComponent(typeof(PlayerInput))] public class Player : MonoBehaviour { [Title("Component")] private Rigidbody rb; private Vector2 movementInput; [Title("쉽의 기본 설정")] [Tooltip("최대 스피드")] public float maxSpeed = 10f; [Tooltip("가속 수치")] public float acceleration = 2f; [Tooltip("감속 수치")] public float deceleration = 2f; [Tooltip("회전 속도")] public float turnSpeed = 10f; [Title("캐릭터의 기본 설정")] private GameObject character; [Tooltip("캐릭터의 이동 속도")] public float characterSpeed = 10f; [Title("레이더")] public Collider[] radar = new Collider[10]; public List inCameraRadar = new (10); public Transform target; public bool IsTargeting { get; private set; } [Title("캐논")] public Rigidbody projectilePrefab; public Transform launchPoint; public float timeOfFlight; public Transform predictedPos; [field: SerializeField] public List Canons { get; private set; } = new (GlobalValue.MAX_CANON_COUNT); [field: Title("Mode")] [field: SerializeField] public bool IsAssaultMode { get; set; } [field: SerializeField] public bool IsInShipMode { get; set; } [field: SerializeField] public bool IsDredgeMode { get; set; } [field: SerializeField] public bool IsTakeAim { get; set; } [Title("Interaction")] public bool IsIslandInteraction { get; set; } private float rayLength; private LayerMask groundLayer; private void Init() { character = transform.Find("Character").gameObject; rb = GetComponent(); GetComponentsInChildren(Canons); rayLength = 15f; groundLayer = LayerMask.GetMask("Ground"); } #region Unity Function private void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, GlobalValue.RADAR_RANGE); } private void Awake() { Init(); } private void Start() { SwitchDredgeMode(true); } private void FixedUpdate() { HandleMovement(); } private void Update() { FindInRadarRange(); FilterInCameraObjects(); LookAtTarget(); Raycast8Direction(); } #endregion #region Movement public void OnMove(InputValue value) // WASD { movementInput = value.Get(); } private void MoveShipPlayer() { var desiredVelocity = transform.forward * (movementInput.y * maxSpeed); var speedChange = (movementInput.y != 0 ? acceleration : deceleration) * Time.fixedDeltaTime; rb.velocity = Vector3.MoveTowards(rb.velocity, desiredVelocity, speedChange); } private void RotatePlayer() { var turn = movementInput.x; var turnRotation = Quaternion.Euler(0f, turn * turnSpeed, 0f); rb.MoveRotation(rb.rotation * turnRotation); } private void MoveCharacterPlayer() { var movement = character.transform.rotation * new Vector3(-movementInput.y, 0, movementInput.x) * (characterSpeed * Time.deltaTime); character.transform.position += movement; } private void HandleMovement() { if (IsInShipMode) { MoveCharacterPlayer(); } else { MoveShipPlayer(); RotatePlayer(); } } private void StopShipMovement() { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } #endregion #region AssaultMode/DreadgeMode Switch private void OnAssaultMode(InputValue value) // V { SwitchAssaultMode(!IsAssaultMode); } private void SwitchAssaultMode(bool isOn) { if (isOn) { SwitchTakeAim(false); SwitchInShipMode(false); SwitchDredgeMode(false); GameManager.Inst.CameraController.CamAssaultMode(); UiManager.Inst.CardLayoutGroupAnimator.Play(); IsAssaultMode = true; } else if (IsAssaultMode) { GameManager.Inst.CameraController.CamDredgeMode(); UiManager.Inst.CardLayoutGroupAnimator.Reverse(); IsAssaultMode = false; } } private void SwitchDredgeMode(bool isOn) { if (isOn) { SwitchTakeAim(false); SwitchAssaultMode(false); SwitchInShipMode(false); GameManager.Inst.CameraController.CamDredgeMode(); IsDredgeMode = true; } else if (IsDredgeMode) { IsDredgeMode = false; } } #endregion #region Interaction Key private void OnTargeting(InputValue value) //Q { if(inCameraRadar.Count == 0) return; IsTargeting = true; UiManager.Inst.RadarUIOnOff(IsTargeting); FindTarget(); } private void OnTargetingHold(InputValue value) //Q Hold { IsTargeting = false; UiManager.Inst.RadarUIOnOff(IsTargeting); } private void OnInteractionE(InputValue value) //E { if(IsTargeting) UiManager.Inst.CheckRadarOverlap(); } private void OnInteraction(InputValue value) //F { if (!IsIslandInteraction) return; SwitchAssaultMode(true); UiManager.Inst.DefaultInteractionOnOff(false); StopShipMovement(); } private void OnInteractionHold(InputValue value) //F Hold { SwitchInShipMode(!IsInShipMode); } private void SwitchInShipMode(bool isOn) { if (isOn) { SwitchTakeAim(false); SwitchAssaultMode(false); SwitchDredgeMode(false); GameManager.Inst.CameraController.CamInShipMode(); IsInShipMode = true; } else if (IsInShipMode) { GameManager.Inst.CameraController.CamDredgeMode(); IsInShipMode = false; } } #endregion private void OnZkey(InputValue value) { UiManager.Inst.AddCard(); } #region TakeAim private void OnTakeAim(InputValue value) // Space { SwitchTakeAim(!IsTakeAim); } private void SwitchTakeAim(bool isOn) { if (isOn) { SwitchAssaultMode(false); SwitchInShipMode(false); SwitchDredgeMode(false); GameManager.Inst.CameraController.CamTakeAim(true); Cursor.visible = false; Cursor.lockState = CursorLockMode.Locked; IsTakeAim = true; } else if (IsTakeAim) { GameManager.Inst.CameraController.CamTakeAim(false); Cursor.visible = true; Cursor.lockState = CursorLockMode.Confined; IsTakeAim = false; } UiManager.Inst.AimOnOff(isOn); } #endregion #region CanonAndRader private void FindInRadarRange() { Physics.OverlapSphereNonAlloc(transform.position, GlobalValue.RADAR_RANGE, radar, LayerMask.GetMask(GlobalValue.ENEMY_LAYER)); } private void FilterInCameraObjects() { inCameraRadar.Clear(); foreach (var col in radar) { if (col == null) continue; var screenPoint = GameManager.Inst.CameraController.MainCam.WorldToViewportPoint(col.transform.position); if (screenPoint.z > 0 && screenPoint.x >= 0 && screenPoint.x <= 1 && screenPoint.y >= 0 && screenPoint.y <= 1) { inCameraRadar.Add(col.transform); } } inCameraRadar.Sort((a, b) => Vector3.Distance(transform.position, a.position).CompareTo(Vector3.Distance(transform.position, b.position))); } private void FindTarget() { var oldTarget = target; foreach (var trans in inCameraRadar) { if (trans.Find("TestTarget") == null) continue; if (target != null && trans.Find("TestTarget").transform == oldTarget) continue; target = trans.Find("TestTarget").transform; // Set new target break; // Exit the loop } // Check if target has changed if (target != oldTarget) { // Call some method if target has changed UiManager.Inst.RadarTargetInit(); } } private void LookAtTarget() { if (target == null) return; foreach (var canon in Canons) { canon.predictedPos = target; canon.LookAtTarget(); UiManager.Inst.UpdateEnemyMarker(target); } } #endregion #region Raycast 8 Direction private void Raycast8Direction() { if (!IsDredgeMode) return; Vector3[] directions = { transform.forward, -transform.forward, transform.right, -transform.right, transform.forward + transform.right, transform.forward - transform.right, -transform.forward + transform.right, -transform.forward - transform.right }; Vector3 halfExtents = new Vector3(5, 5, 5); // 박스 크기의 절반을 나타내는 벡터값을 설정합니다. var isOn = false; foreach (Vector3 dir in directions) { RaycastHit hit; if (Physics.BoxCast(transform.position, halfExtents, dir, out hit, Quaternion.identity, rayLength, groundLayer)) { isOn = true; var islandInfo = hit.transform.parent.parent.GetComponent(); if (GameManager.Inst.CameraController.AssaultCam != islandInfo.IslandCam) GameManager.Inst.CameraController.AssaultCam = islandInfo.IslandCam; // 박스가 Ground 레이어에 닿았을 때 빨간색으로 표시 Debug.DrawRay(transform.position, dir * rayLength, Color.red); IsIslandInteraction = true; break; } // 박스가 Ground 레이어에 닿지 않았을 때 녹색으로 표시 Debug.DrawRay(transform.position, dir * rayLength, Color.green); IsIslandInteraction = false; } UiManager.Inst.DefaultInteractionOnOff(isOn); } #endregion } }