diff --git a/BlueWater/Assets/02.Scripts/Character/CombatPlayer/CombatPlayer.cs b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/CombatPlayer.cs index 4c6d643a1..d34fa87ea 100644 --- a/BlueWater/Assets/02.Scripts/Character/CombatPlayer/CombatPlayer.cs +++ b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/CombatPlayer.cs @@ -3,6 +3,7 @@ using System.Collections; using Sirenix.OdinInspector; using UnityEngine; using UnityEngine.InputSystem; +using UnityEngine.Serialization; // ReSharper disable once CheckNamespace namespace BlueWaterProject @@ -46,12 +47,18 @@ namespace BlueWaterProject [SerializeField] private Transform visualLook; [field: SerializeField] public Animator Animator { get; set; } [SerializeField] private Transform groundCheck; + + [Title("Extensions Data")] + [SerializeField] private float nextFrameCoefficient = 3f; private Vector2 movementInput; + private Vector3 currentDirection = Vector3.back; public Vector3 PreviousDirection { get; set; } = Vector3.back; [field: SerializeField] public Collider[] HitColliders { get; set; } private RaycastHit slopeHit; private int groundLayer; + private bool isOnSlope; + private bool isGrounded; private const float RAY_DISTANCE = 3f; @@ -107,23 +114,26 @@ namespace BlueWaterProject private void Update() { - var isMoving = Rb.velocity.magnitude > 0.1f; + var isMoving = currentDirection.magnitude > 0.01f; if (isMoving) { - PreviousDirection = Rb.velocity.normalized; + PreviousDirection = currentDirection.normalized; Animator.SetFloat(XDirectionHash, PreviousDirection.x); Animator.SetFloat(ZDirectionHash, PreviousDirection.z); } Animator.SetBool(IsMovingHash, isMoving); var localScale = visualLook.localScale; - localScale.x = Rb.velocity.x switch + localScale.x = PreviousDirection.x switch { > 0.01f => Mathf.Abs(localScale.x), < -0.01f => -Mathf.Abs(localScale.x), _ => localScale.x }; visualLook.localScale = localScale; + + isOnSlope = IsOnSlope(); + isGrounded = IsGrounded(); } private void FixedUpdate() @@ -193,25 +203,38 @@ namespace BlueWaterProject private void HandleMovement() { - var movement = new Vector3(movementInput.x, 0, movementInput.y); - var moveDirection = IsDashing ? PreviousDirection : movement.normalized; + currentDirection = new Vector3(movementInput.x, 0, movementInput.y).normalized; + //var currentDirection = IsDashing ? PreviousDirection : currentMovement.normalized; - var velocity = CalculateNextFrameGroundAngle(moveDirection) < maxSlopeAngle ? moveDirection : Vector3.zero; - var gravity = Vector3.down * Mathf.Abs(Rb.velocity.y); - - if (IsOnSlope() || velocity == moveDirection && IsGrounded()) + if (isOnSlope && isGrounded) { - velocity = Vector3.ProjectOnPlane(moveDirection, slopeHit.normal).normalized; - gravity = Vector3.zero; - Rb.useGravity = false; - } - else - { - Rb.useGravity = true; + currentDirection = Vector3.ProjectOnPlane(currentDirection, slopeHit.normal).normalized; } var moveValue = IsDashing ? DashForce : moveSpeed; - Rb.velocity = velocity * moveValue + gravity; + var newPosition = Rb.position + currentDirection * (moveValue * Time.fixedDeltaTime); + + Rb.MovePosition(newPosition); + + // var currentMovement = new Vector3(movementInput.x, 0, movementInput.y); + // var currentDirection = IsDashing ? PreviousDirection : currentMovement.normalized; + // var isNextFrameInAngle = CalculateNextFrameGroundAngle(currentDirection) < maxSlopeAngle; + // var velocity = isNextFrameInAngle ? currentDirection : Vector3.zero; + // var gravity = Vector3.down * Mathf.Abs(Rb.velocity.y); + // + // if (IsOnSlope() && IsGrounded()) + // { + // velocity = Vector3.ProjectOnPlane(currentDirection, slopeHit.normal).normalized; + // gravity = Vector3.zero; + // Rb.useGravity = false; + // } + // else + // { + // Rb.useGravity = true; + // } + // + // var moveValue = IsDashing ? DashForce : moveSpeed; + // Rb.velocity = velocity * moveValue + gravity; } public bool IsOnSlope() @@ -237,7 +260,7 @@ namespace BlueWaterProject private float CalculateNextFrameGroundAngle(Vector3 direction) { - var nextFramePlayerPosition = transform.position + direction * (3f * moveSpeed * Time.fixedDeltaTime); + var nextFramePlayerPosition = transform.position + direction * (nextFrameCoefficient * moveSpeed * Time.fixedDeltaTime); if (Physics.Raycast(nextFramePlayerPosition, Vector3.down, out var hitInfo, RAY_DISTANCE, groundLayer)) { diff --git a/BlueWater/Assets/02.Scripts/Character/CombatPlayer/NewCombatPlayer.cs b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/NewCombatPlayer.cs new file mode 100644 index 000000000..1858c6409 --- /dev/null +++ b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/NewCombatPlayer.cs @@ -0,0 +1,600 @@ +using System; +using UnityEngine; +using UnityEngine.InputSystem; + +// ReSharper disable once CheckNamespace +namespace BlueWaterProject +{ + public class NewCombatPlayer : MonoBehaviour, IMovement3D + { + /*********************************************************************** + * Definitions + ***********************************************************************/ + + #region Class + + [Serializable] + public class Components + { + public PlayerInput playerInput; + public CapsuleCollider capsuleCollider; + public Rigidbody rb; + public Transform visualLook; + public Animator animator; + public Transform groundCheck; + } + + [Serializable] + public class CheckOption + { + [Tooltip("지면으로 체크할 레이어 설정")] public LayerMask groundLayerMask = -1; + + [Range(0.01f, 0.5f), Tooltip("전방 감지 거리")] + public float forwardCheckDistance = 0.1f; + + [Range(0.1f, 10.0f), Tooltip("지면 감지 거리")] + public float groundCheckDistance = 2.0f; + + [Range(0.0f, 0.1f), Tooltip("지면 인식 허용 거리")] + public float groundCheckThreshold = 0.01f; + } + + [Serializable] + public class MovementOption + { + [Range(1f, 10f), Tooltip("이동속도")] public float speed = 10f; + + [Range(1f, 3f), Tooltip("달리기 이동속도 증가 계수")] + public float runningCoefficient = 1.5f; + + [Range(1f, 75f), Tooltip("등반 가능한 경사각")] + public float maxSlopeAngle = 50f; + + [Range(0f, 4f), Tooltip("경사로 이동속도 변화율(가속/감속)")] + public float slopeAccel = 1f; + + [Range(-9.81f, 0f), Tooltip("중력")] public float gravity = -9.81f; + } + + [Serializable] + public class CurrentState + { + public bool isMoving; + public bool isRunning; + public bool isGrounded; + public bool isOnSteepSlope; // 등반 불가능한 경사로에 올라와 있음 + public bool isForwardBlocked; // 전방에 장애물 존재 + public bool isOutOfControl; // 제어 불가 상태 + } + + [Serializable] + public class CurrentValue + { + public Vector2 movementInput; + public Vector3 worldMoveDirection; + public Vector3 groundNormal; + public Vector3 groundCross; + public Vector3 horizontalVelocity; + + [Space] public float outOfControlDuration; + + [Space] public float groundDistance; + public float groundSlopeAngle; // 현재 바닥의 경사각 + public float groundVerticalSlopeAngle; // 수직으로 재측정한 경사각 + public float forwardSlopeAngle; // 캐릭터가 바라보는 방향의 경사각 + public float slopeAccel; // 경사로 인한 가속/감속 비율 + + [Space] public float gravity; + } + + #endregion + + /*********************************************************************** + * Variables + ***********************************************************************/ + + #region Variables + + // [SerializeField] private Components components = new(); + // [SerializeField] private CheckOption checkOptions = new(); + // [SerializeField] private MovementOption moveOptions = new(); + // [SerializeField] private CurrentState currentStates = new(); + // [SerializeField] private CurrentValue currentValues = new(); + + [field: SerializeField] public Components PlayerComponents { get; private set; } = new(); + [field: SerializeField] public CheckOption PlayerCheckOption { get; private set; } = new(); + [field: SerializeField] public MovementOption PlayerMovementOption { get; private set; } = new(); + [field: SerializeField] public CurrentState PlayerCurrentState { get; set; } = new(); + [field: SerializeField] public CurrentValue PlayerCurrentValue { get; set; } = new(); + + private float capsuleRadiusDifferent; + private float fixedDeltaTime; + + private float castRadius; // Sphere, Capsule 레이캐스트 반지름 + + private Vector3 CapsuleTopCenterPoint => new(transform.position.x, + transform.position.y + PlayerComponents.capsuleCollider.height - PlayerComponents.capsuleCollider.radius, + transform.position.z); + + private Vector3 CapsuleBottomCenterPoint => new(transform.position.x, + transform.position.y + PlayerComponents.capsuleCollider.radius, transform.position.z); + + #endregion + + /*********************************************************************** + * Unity Events + ***********************************************************************/ + + #region Unity Events + + private void Start() + { + InitRigidbody(); + InitCapsuleCollider(); + } + + private void Update() + { + Move(); + } + + private void FixedUpdate() + { + fixedDeltaTime = Time.fixedDeltaTime; + + CheckGround(); + CheckForward(); + + UpdatePhysics(); + UpdateValues(); + + CalculateMovements(); + ApplyMovementsToRigidbody(); + } + + #endregion + + /*********************************************************************** + * Init Methods + ***********************************************************************/ + + #region Init Methods + + private void InitRigidbody() + { + TryGetComponent(out PlayerComponents.rb); + if (PlayerComponents.rb == null) + { + PlayerComponents.rb = gameObject.AddComponent(); + } + + PlayerComponents.rb.constraints = RigidbodyConstraints.FreezeRotation; + PlayerComponents.rb.interpolation = RigidbodyInterpolation.Interpolate; + PlayerComponents.rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; + PlayerComponents.rb.useGravity = false; + } + + private void InitCapsuleCollider() + { + TryGetComponent(out PlayerComponents.capsuleCollider); + if (PlayerComponents.capsuleCollider == null) + { + PlayerComponents.capsuleCollider = gameObject.AddComponent(); + + // 렌더러를 모두 탐색하여 높이 결정 + var maxHeight = -1f; + + // // 1. SMR 확인 + // var smrArr = GetComponentsInChildren(); + // if (smrArr.Length > 0) + // { + // foreach (var smr in smrArr) + // { + // foreach (var vertex in smr.sharedMesh.vertices) + // { + // if(maxHeight < vertex.y) + // maxHeight = vertex.y; + // } + // } + // } + // // 2. MR 확인 + // else + // { + // var mfArr = GetComponentsInChildren(); + // if (mfArr.Length > 0) + // { + // foreach (var mf in mfArr) + // { + // foreach (var vertex in mf.mesh.vertices) + // { + // if (maxHeight < vertex.y) + // maxHeight = vertex.y; + // } + // } + // } + // } + + // 3. 캡슐 콜라이더 값 설정 + if (maxHeight <= 0) + { + maxHeight = 1f; + } + + var center = maxHeight * 0.5f; + + PlayerComponents.capsuleCollider.height = maxHeight; + PlayerComponents.capsuleCollider.center = Vector3.up * center; + PlayerComponents.capsuleCollider.radius = 0.5f; + } + + var capsuleColliderRadius = PlayerComponents.capsuleCollider.radius; + castRadius = capsuleColliderRadius * 0.9f; + capsuleRadiusDifferent = capsuleColliderRadius - castRadius + 0.05f; + } + + #endregion + + /*********************************************************************** + * PlayerInput + ***********************************************************************/ + + #region PlayerInput + + private void OnMove(InputValue value) + { + PlayerCurrentValue.movementInput = value.Get(); + } + + #endregion + + /*********************************************************************** + * IMovement3D interface + ***********************************************************************/ + + #region IMovement3D interface + + public bool IsMoving() => PlayerCurrentState.isMoving; + public bool IsGrounded() => PlayerCurrentState.isGrounded; + public float GetDistanceFromGround() => PlayerCurrentValue.groundDistance; + + public void SetMovement(in Vector3 worldMoveDirection, bool isRunning) + { + PlayerCurrentValue.worldMoveDirection = worldMoveDirection; + PlayerCurrentState.isMoving = worldMoveDirection.sqrMagnitude > 0.01f; + PlayerCurrentState.isRunning = isRunning; + } + + public void StopMoving() + { + PlayerCurrentValue.worldMoveDirection = Vector3.zero; + PlayerCurrentState.isMoving = false; + PlayerCurrentState.isRunning = false; + } + + public void KnockBack(in Vector3 force, float time) + { + SetOutOfControl(time); + PlayerComponents.rb.AddForce(force, ForceMode.Impulse); + } + + public void SetOutOfControl(float time) + { + PlayerCurrentValue.outOfControlDuration = time; + } + + #endregion + + /*********************************************************************** + * Methods + ***********************************************************************/ + + #region Methods + + private void Move() + { + // 이동하지 않는 경우, 미끄럼 방지 + if (PlayerCurrentState.isMoving == false) + { + PlayerComponents.rb.velocity = new Vector3(0f, PlayerComponents.rb.velocity.y, 0f); + return; + } + + // 실제 이동 벡터 계산 + var worldMove = new Vector3(PlayerCurrentValue.movementInput.x, 0, PlayerCurrentValue.movementInput.y).normalized; + worldMove *= (PlayerMovementOption.speed) * (PlayerCurrentState.isRunning ? PlayerMovementOption.runningCoefficient : 1f); + + // Y축 속도는 유지하면서 XZ평면 이동 + PlayerComponents.rb.velocity = new Vector3(worldMove.x, PlayerComponents.rb.velocity.y, worldMove.z); + } + + /// 하단 지면 검사 + private void CheckGround() + { + PlayerCurrentValue.groundDistance = float.MaxValue; + PlayerCurrentValue.groundNormal = Vector3.up; + PlayerCurrentValue.groundSlopeAngle = 0f; + PlayerCurrentValue.forwardSlopeAngle = 0f; + + var cast = Physics.SphereCast(CapsuleBottomCenterPoint, castRadius, + Vector3.down, out var hit, PlayerCheckOption.groundCheckDistance, PlayerCheckOption.groundLayerMask, + QueryTriggerInteraction.Ignore); + + PlayerCurrentState.isGrounded = false; + + if (cast) + { + // 지면 노멀벡터 초기화 + PlayerCurrentValue.groundNormal = hit.normal; + + // 현재 위치한 지면의 경사각 구하기(캐릭터 이동방향 고려) + PlayerCurrentValue.groundSlopeAngle = Vector3.Angle(PlayerCurrentValue.groundNormal, Vector3.up); + PlayerCurrentValue.forwardSlopeAngle = + Vector3.Angle(PlayerCurrentValue.groundNormal, PlayerCurrentValue.worldMoveDirection) - 90f; + + PlayerCurrentState.isOnSteepSlope = + PlayerCurrentValue.groundSlopeAngle >= PlayerMovementOption.maxSlopeAngle; + + // 경사각 이중검증 (수직 레이캐스트) : 뾰족하거나 각진 부분 체크 + //if (State.isOnSteepSlope) + //{ + // Vector3 ro = hit.point + Vector3.up * 0.1f; + // Vector3 rd = Vector3.down; + // bool rayD = + // Physics.SphereCast(ro, 0.09f, rd, out var hitRayD, 0.2f, COption.groundLayerMask, QueryTriggerInteraction.Ignore); + + // Current.groundVerticalSlopeAngle = rayD ? Vector3.Angle(hitRayD.normal, Vector3.up) : Current.groundSlopeAngle; + + // State.isOnSteepSlope = Current.groundVerticalSlopeAngle >= MOption.maxSlopeAngle; + //} + + PlayerCurrentValue.groundDistance = + Mathf.Max(hit.distance - capsuleRadiusDifferent - PlayerCheckOption.groundCheckThreshold, 0f); + + PlayerCurrentState.isGrounded = + (PlayerCurrentValue.groundDistance <= 0.0001f) && !PlayerCurrentState.isOnSteepSlope; + + GzUpdateValue(ref gzGroundTouch, hit.point); + } + + // 월드 이동벡터 회전축 + PlayerCurrentValue.groundCross = Vector3.Cross(PlayerCurrentValue.groundNormal, Vector3.up); + } + + /// 전방 장애물 검사 : 레이어 관계 없이 trigger가 아닌 모든 장애물 검사 + private void CheckForward() + { + bool cast = + Physics.CapsuleCast(CapsuleBottomCenterPoint, CapsuleTopCenterPoint, castRadius, + PlayerCurrentValue.worldMoveDirection + Vector3.down * 0.1f, + out var hit, PlayerCheckOption.forwardCheckDistance, -1, QueryTriggerInteraction.Ignore); + + PlayerCurrentState.isForwardBlocked = false; + if (cast) + { + float forwardObstacleAngle = Vector3.Angle(hit.normal, Vector3.up); + PlayerCurrentState.isForwardBlocked = forwardObstacleAngle >= PlayerMovementOption.maxSlopeAngle; + + GzUpdateValue(ref gzForwardTouch, hit.point); + } + } + + private void UpdatePhysics() + { + // Custom Gravity, Jumping State + if (PlayerCurrentState.isGrounded) + { + PlayerCurrentValue.gravity = 0f; + } + else + { + PlayerCurrentValue.gravity += fixedDeltaTime * PlayerMovementOption.gravity; + } + } + + private void UpdateValues() + { + // Out Of Control + PlayerCurrentState.isOutOfControl = PlayerCurrentValue.outOfControlDuration > 0f; + + if (PlayerCurrentState.isOutOfControl) + { + PlayerCurrentValue.outOfControlDuration -= fixedDeltaTime; + PlayerCurrentValue.worldMoveDirection = Vector3.zero; + } + } + + private void CalculateMovements() + { + if (PlayerCurrentState.isOutOfControl) + { + PlayerCurrentValue.horizontalVelocity = Vector3.zero; + return; + } + + // 0. 가파른 경사면에 있는 경우 : 꼼짝말고 미끄럼틀 타기 + //if (State.isOnSteepSlope && Current.groundDistance < 0.1f) + //{ + // DebugMark(0); + + // Current.horizontalVelocity = + // Quaternion.AngleAxis(90f - Current.groundSlopeAngle, Current.groundCross) * (Vector3.up * Current.gravity); + + // Com.rBody.velocity = Current.horizontalVelocity; + + // return; + //} + + // 2. XZ 이동속도 계산 + // 공중에서 전방이 막힌 경우 제한 (지상에서는 벽에 붙어서 이동할 수 있도록 허용) + if (PlayerCurrentState.isForwardBlocked && !PlayerCurrentState.isGrounded) + { + PlayerCurrentValue.horizontalVelocity = Vector3.zero; + } + else // 이동 가능한 경우 : 지상 or 전방이 막히지 않음 + { + float speed = !PlayerCurrentState.isMoving ? 0f : + !PlayerCurrentState.isRunning ? PlayerMovementOption.speed : + PlayerMovementOption.speed * PlayerMovementOption.runningCoefficient; + + PlayerCurrentValue.horizontalVelocity = PlayerCurrentValue.worldMoveDirection * speed; + } + + // 3. XZ 벡터 회전 + // 지상이거나 지면에 가까운 높이 + if (PlayerCurrentState.isGrounded || + PlayerCurrentValue.groundDistance < PlayerCheckOption.groundCheckDistance) + { + if (PlayerCurrentState.isMoving && !PlayerCurrentState.isForwardBlocked) + { + // 경사로 인한 가속/감속 + if (PlayerMovementOption.slopeAccel > 0f) + { + bool isPlus = PlayerCurrentValue.forwardSlopeAngle >= 0f; + float absFsAngle = isPlus + ? PlayerCurrentValue.forwardSlopeAngle + : -PlayerCurrentValue.forwardSlopeAngle; + float accel = PlayerMovementOption.slopeAccel * absFsAngle * 0.01111f + 1f; + PlayerCurrentValue.slopeAccel = !isPlus ? accel : 1.0f / accel; + + PlayerCurrentValue.horizontalVelocity *= PlayerCurrentValue.slopeAccel; + } + + // 벡터 회전 (경사로) + PlayerCurrentValue.horizontalVelocity = + Quaternion.AngleAxis(-PlayerCurrentValue.groundSlopeAngle, PlayerCurrentValue.groundCross) * + PlayerCurrentValue.horizontalVelocity; + } + } + + GzUpdateValue(ref gzRotatedWorldMoveDirection, PlayerCurrentValue.horizontalVelocity * 0.2f); + } + + /// 리지드바디 최종 속도 적용 + private void ApplyMovementsToRigidbody() + { + if (PlayerCurrentState.isOutOfControl) + { + PlayerComponents.rb.velocity = new Vector3(PlayerComponents.rb.velocity.x, PlayerCurrentValue.gravity, + PlayerComponents.rb.velocity.z); + return; + } + + PlayerComponents.rb.velocity = + PlayerCurrentValue.horizontalVelocity + Vector3.up * (PlayerCurrentValue.gravity); + } + + #endregion + + /*********************************************************************** + * Gizmos, GUI + ***********************************************************************/ + + #region . + + private Vector3 gzGroundTouch; + private Vector3 gzForwardTouch; + private Vector3 gzRotatedWorldMoveDirection; + + [Header("Gizmos Option")] public bool showGizmos = true; + + [SerializeField, Range(0.01f, 2f)] private float gizmoRadius = 0.05f; + + [System.Diagnostics.Conditional("UNITY_EDITOR")] + private void OnDrawGizmos() + { + if (Application.isPlaying == false) return; + if (!showGizmos) return; + if (!enabled) return; + + Gizmos.color = Color.red; + Gizmos.DrawSphere(gzGroundTouch, gizmoRadius); + + if (PlayerCurrentState.isForwardBlocked) + { + Gizmos.color = Color.blue; + Gizmos.DrawSphere(gzForwardTouch, gizmoRadius); + } + + Gizmos.color = Color.blue; + Gizmos.DrawLine(gzGroundTouch - PlayerCurrentValue.groundCross, + gzGroundTouch + PlayerCurrentValue.groundCross); + + Gizmos.color = Color.black; + Gizmos.DrawLine(transform.position, transform.position + gzRotatedWorldMoveDirection); + + Gizmos.color = new Color(0.5f, 1.0f, 0.8f, 0.8f); + Gizmos.DrawWireSphere(CapsuleTopCenterPoint, castRadius); + Gizmos.DrawWireSphere(CapsuleBottomCenterPoint, castRadius); + } + + [System.Diagnostics.Conditional("UNITY_EDITOR")] + private void GzUpdateValue(ref T variable, in T value) + { + variable = value; + } + + [SerializeField, Space] private bool showGUI = true; + [SerializeField] private int guiTextSize = 28; + + private float prevForwardSlopeAngle; + + private void OnGUI() + { + if (Application.isPlaying == false) return; + if (!showGUI) return; + if (!enabled) return; + + GUIStyle labelStyle = GUI.skin.label; + labelStyle.normal.textColor = Color.yellow; + labelStyle.fontSize = Math.Max(guiTextSize, 20); + + prevForwardSlopeAngle = PlayerCurrentValue.forwardSlopeAngle == -90f + ? prevForwardSlopeAngle + : PlayerCurrentValue.forwardSlopeAngle; + + var oldColor = GUI.color; + GUI.color = new Color(0f, 0f, 0f, 0.5f); + GUI.Box(new Rect(40, 40, 420, 260), ""); + GUI.color = oldColor; + + GUILayout.BeginArea(new Rect(50, 50, 1000, 500)); + GUILayout.Label($"Ground Height : {Mathf.Min(PlayerCurrentValue.groundDistance, 99.99f): 00.00}", + labelStyle); + GUILayout.Label($"Slope Angle(Ground) : {PlayerCurrentValue.groundSlopeAngle: 00.00}", labelStyle); + GUILayout.Label($"Slope Angle(Forward) : {prevForwardSlopeAngle: 00.00}", labelStyle); + GUILayout.Label($"Allowed Slope Angle : {PlayerMovementOption.maxSlopeAngle: 00.00}", labelStyle); + GUILayout.Label($"Current Slope Accel : {PlayerCurrentValue.slopeAccel: 00.00}", labelStyle); + GUILayout.Label($"Current Speed Mag : {PlayerCurrentValue.horizontalVelocity.magnitude: 00.00}", + labelStyle); + GUILayout.EndArea(); + + float sWidth = Screen.width; + float sHeight = Screen.height; + + GUIStyle RTLabelStyle = GUI.skin.label; + RTLabelStyle.fontSize = 20; + RTLabelStyle.normal.textColor = Color.green; + + oldColor = GUI.color; + GUI.color = new Color(1f, 1f, 1f, 0.5f); + GUI.Box(new Rect(sWidth - 355f, 5f, 340f, 100f), ""); + GUI.color = oldColor; + + var yPos = 10f; + GUI.Label(new Rect(sWidth - 350f, yPos, 150f, 30f), $"Speed : {PlayerMovementOption.speed: 00.00}", + RTLabelStyle); + PlayerMovementOption.speed = GUI.HorizontalSlider(new Rect(sWidth - 200f, yPos + 10f, 180f, 20f), + PlayerMovementOption.speed, 1f, 10f); + + yPos += 20f; + GUI.Label(new Rect(sWidth - 350f, yPos, 150f, 30f), $"Max Slope : {PlayerMovementOption.maxSlopeAngle: 00}", + RTLabelStyle); + PlayerMovementOption.maxSlopeAngle = (int)GUI.HorizontalSlider( + new Rect(sWidth - 200f, yPos + 10f, 180f, 20f), PlayerMovementOption.maxSlopeAngle, 1f, 75f); + + labelStyle.fontSize = Math.Max(guiTextSize, 20); + } + + #endregion + } +} \ No newline at end of file diff --git a/BlueWater/Assets/02.Scripts/Character/CombatPlayer/NewCombatPlayer.cs.meta b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/NewCombatPlayer.cs.meta new file mode 100644 index 000000000..7b7dfdd6e --- /dev/null +++ b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/NewCombatPlayer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 01fef22c346a235499c530436f7c9c53 diff --git a/BlueWater/Assets/02.Scripts/Interface/IMovement3D.cs b/BlueWater/Assets/02.Scripts/Interface/IMovement3D.cs new file mode 100644 index 000000000..bbc2559c3 --- /dev/null +++ b/BlueWater/Assets/02.Scripts/Interface/IMovement3D.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +// ReSharper disable once CheckNamespace +namespace BlueWaterProject +{ + public interface IMovement3D + { + /// 현재 이동 중인지 여부 + bool IsMoving(); + /// 지면에 닿아 있는지 여부 + bool IsGrounded(); + /// 지면으로부터의 거리 + float GetDistanceFromGround(); + + /// 월드 이동벡터 초기화(이동 명령) + void SetMovement(in Vector3 worldMoveDirection, bool isRunning); + /// 이동 중지 + void StopMoving(); + + /// 밀쳐내기 + void KnockBack(in Vector3 force, float time); + } +} diff --git a/BlueWater/Assets/02.Scripts/Interface/IMovement3D.cs.meta b/BlueWater/Assets/02.Scripts/Interface/IMovement3D.cs.meta new file mode 100644 index 000000000..2c58ea409 --- /dev/null +++ b/BlueWater/Assets/02.Scripts/Interface/IMovement3D.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1165eeeca2febd42b2f40167c74d02f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/BlueWater/Assets/03.Images/Island/island/Materials/land01.mat b/BlueWater/Assets/03.Images/Island/island/Materials/land01.mat index 19983a47c..66618de46 100644 --- a/BlueWater/Assets/03.Images/Island/island/Materials/land01.mat +++ b/BlueWater/Assets/03.Images/Island/island/Materials/land01.mat @@ -64,7 +64,7 @@ Material: m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _MainTex: - m_Texture: {fileID: 2800000, guid: ee40cf7053c686c49a4d70e09c6cff39, type: 3} + m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _MetallicGlossMap: diff --git a/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab b/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab index fbaeff306..a850c7492 100644 --- a/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab +++ b/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab @@ -159,7 +159,7 @@ GameObject: - component: {fileID: 7729150195808218711} - component: {fileID: 6121288256300454469} - component: {fileID: 4906016173319036404} - - component: {fileID: 2650321273105086144} + - component: {fileID: 1096317451054001340} m_Layer: 9 m_Name: CombatPlayer m_TagString: Untagged @@ -231,9 +231,9 @@ Rigidbody: m_ImplicitTensor: 1 m_UseGravity: 1 m_IsKinematic: 0 - m_Interpolate: 0 + m_Interpolate: 1 m_Constraints: 112 - m_CollisionDetection: 0 + m_CollisionDetection: 2 --- !u!114 &6121288256300454469 MonoBehaviour: m_ObjectHideFlags: 0 @@ -272,7 +272,7 @@ MonoBehaviour: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2391945466483065398} - m_Enabled: 1 + m_Enabled: 0 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5258cddac7934c1469d147dddbdb5023, type: 3} m_Name: @@ -302,29 +302,63 @@ MonoBehaviour: visualLook: {fileID: 8557381169392297019} k__BackingField: {fileID: 3138574858532492034} groundCheck: {fileID: 7407663186225048994} + nextFrameCoefficient: 3 k__BackingField: [] ---- !u!64 &2650321273105086144 -MeshCollider: +--- !u!114 &1096317451054001340 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2391945466483065398} - m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 - m_IsTrigger: 0 - m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 5 - m_Convex: 0 - m_CookingOptions: 30 - m_Mesh: {fileID: 0} + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 01fef22c346a235499c530436f7c9c53, type: 3} + m_Name: + m_EditorClassIdentifier: + k__BackingField: + playerInput: {fileID: 6121288256300454469} + capsuleCollider: {fileID: 6858674358337067996} + rb: {fileID: 7729150195808218711} + visualLook: {fileID: 8557381169392297019} + animator: {fileID: 3138574858532492034} + groundCheck: {fileID: 7407663186225048994} + k__BackingField: + groundLayerMask: + serializedVersion: 2 + m_Bits: 8 + forwardCheckDistance: 0.1 + groundCheckDistance: 2 + groundCheckThreshold: 0.01 + k__BackingField: + speed: 10 + runningCoefficient: 1.5 + maxSlopeAngle: 50 + slopeAccel: 1 + gravity: -9.81 + k__BackingField: + isMoving: 0 + isRunning: 0 + isGrounded: 0 + isOnSteepSlope: 0 + isForwardBlocked: 0 + isOutOfControl: 0 + k__BackingField: + worldMoveDirection: {x: 0, y: 0, z: 0} + groundNormal: {x: 0, y: 0, z: 0} + groundCross: {x: 0, y: 0, z: 0} + horizontalVelocity: {x: 0, y: 0, z: 0} + outOfControlDuration: 0 + groundDistance: 0 + groundSlopeAngle: 0 + groundVerticalSlopeAngle: 0 + forwardSlopeAngle: 0 + slopeAccel: 0 + gravity: 0 + showGizmos: 1 + gizmoRadius: 0.05 + showGUI: 1 + guiTextSize: 28 --- !u!1 &3669261844365681366 GameObject: m_ObjectHideFlags: 0 diff --git a/BlueWater/Assets/Distant Lands/Cozy Weather/Custom Render Pipelines/Import for SW2 Underwater Integration.unitypackage.meta b/BlueWater/Assets/Distant Lands/Cozy Weather/Custom Render Pipelines/Import for SW2 Underwater Integration.unitypackage.meta deleted file mode 100644 index 7c4bab1a1..000000000 --- a/BlueWater/Assets/Distant Lands/Cozy Weather/Custom Render Pipelines/Import for SW2 Underwater Integration.unitypackage.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: aba6fa52907672a4da99307e9c925639 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: