CombatPlayer 움직임 로직 보완 중

This commit is contained in:
NTG_Lenovo 2024-01-25 16:16:53 +09:00
parent da3c952d78
commit 9dd465a8ed
8 changed files with 732 additions and 46 deletions

View File

@ -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))
{

View File

@ -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<Rigidbody>();
}
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<CapsuleCollider>();
// 렌더러를 모두 탐색하여 높이 결정
var maxHeight = -1f;
// // 1. SMR 확인
// var smrArr = GetComponentsInChildren<SkinnedMeshRenderer>();
// 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<MeshFilter>();
// 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<Vector2>();
}
#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);
}
/// <summary> 하단 지면 검사 </summary>
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);
}
/// <summary> 전방 장애물 검사 : 레이어 관계 없이 trigger가 아닌 모든 장애물 검사 </summary>
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);
}
/// <summary> 리지드바디 최종 속도 적용 </summary>
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<T>(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
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 01fef22c346a235499c530436f7c9c53

View File

@ -0,0 +1,23 @@
using UnityEngine;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public interface IMovement3D
{
/// <summary> 현재 이동 중인지 여부 </summary>
bool IsMoving();
/// <summary> 지면에 닿아 있는지 여부 </summary>
bool IsGrounded();
/// <summary> 지면으로부터의 거리 </summary>
float GetDistanceFromGround();
/// <summary> 월드 이동벡터 초기화(이동 명령) </summary>
void SetMovement(in Vector3 worldMoveDirection, bool isRunning);
/// <summary> 이동 중지 </summary>
void StopMoving();
/// <summary> 밀쳐내기 </summary>
void KnockBack(in Vector3 force, float time);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d1165eeeca2febd42b2f40167c74d02f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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:

View File

@ -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}
<Animator>k__BackingField: {fileID: 3138574858532492034}
groundCheck: {fileID: 7407663186225048994}
nextFrameCoefficient: 3
<HitColliders>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:
<PlayerComponents>k__BackingField:
playerInput: {fileID: 6121288256300454469}
capsuleCollider: {fileID: 6858674358337067996}
rb: {fileID: 7729150195808218711}
visualLook: {fileID: 8557381169392297019}
animator: {fileID: 3138574858532492034}
groundCheck: {fileID: 7407663186225048994}
<PlayerCheckOption>k__BackingField:
groundLayerMask:
serializedVersion: 2
m_Bits: 8
forwardCheckDistance: 0.1
groundCheckDistance: 2
groundCheckThreshold: 0.01
<PlayerMovementOption>k__BackingField:
speed: 10
runningCoefficient: 1.5
maxSlopeAngle: 50
slopeAccel: 1
gravity: -9.81
<PlayerCurrentState>k__BackingField:
isMoving: 0
isRunning: 0
isGrounded: 0
isOnSteepSlope: 0
isForwardBlocked: 0
isOutOfControl: 0
<PlayerCurrentValue>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

View File

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: aba6fa52907672a4da99307e9c925639
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: