From 7b4408247e488c75fc2d79f553dcfb50ad45bba3 Mon Sep 17 00:00:00 2001 From: NTG Date: Sun, 18 Feb 2024 04:40:14 +0900 Subject: [PATCH] =?UTF-8?q?#165=20=EC=A0=84=ED=88=AC=20=ED=94=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=20=EC=9B=80=EC=A7=81=EC=9E=84=20=EB=B3=B4?= =?UTF-8?q?=EC=99=84=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + 전방 장애물 감지 보완 + 경사면에서 움직임 보완 --- BlueWater/Assets/01.Scenes/02.Combat.unity | 46 ++++++- .../Character/CombatPlayer/PhysicsMovement.cs | 117 +++++++++++------- .../Characters/Players/CombatPlayer.prefab | 12 +- .../09.BehaviorTree/Enemy/Rhinoceros.asset | 2 +- 4 files changed, 120 insertions(+), 57 deletions(-) diff --git a/BlueWater/Assets/01.Scenes/02.Combat.unity b/BlueWater/Assets/01.Scenes/02.Combat.unity index 50aff2d95..3d7898251 100644 --- a/BlueWater/Assets/01.Scenes/02.Combat.unity +++ b/BlueWater/Assets/01.Scenes/02.Combat.unity @@ -12188,6 +12188,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (1) objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex @@ -97203,6 +97208,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (8) objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex @@ -267599,6 +267609,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex @@ -329270,6 +329285,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (5) objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex @@ -455325,6 +455345,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (2) objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex @@ -487855,10 +487880,10 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (7) objectReference: {fileID: 0} - - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} - propertyPath: m_Convex - value: 0 + propertyPath: m_Layer + value: 3 objectReference: {fileID: 0} - target: {fileID: 3339676424458973423, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} @@ -492464,6 +492489,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (6) objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex @@ -553584,6 +553614,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (3) objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex @@ -724532,6 +724567,11 @@ PrefabInstance: propertyPath: m_Name value: SM_staircase (4) objectReference: {fileID: 0} + - target: {fileID: 2671543527693871701, guid: abf04c401523f1e4d93d7e1004a6a196, + type: 3} + propertyPath: m_Layer + value: 3 + objectReference: {fileID: 0} - target: {fileID: 3013562905558963970, guid: abf04c401523f1e4d93d7e1004a6a196, type: 3} propertyPath: m_Convex diff --git a/BlueWater/Assets/02.Scripts/Character/CombatPlayer/PhysicsMovement.cs b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/PhysicsMovement.cs index 19000e1d9..28f9bb90f 100644 --- a/BlueWater/Assets/02.Scripts/Character/CombatPlayer/PhysicsMovement.cs +++ b/BlueWater/Assets/02.Scripts/Character/CombatPlayer/PhysicsMovement.cs @@ -28,16 +28,22 @@ namespace BlueWaterProject public class CheckOption { [Tooltip("지면으로 체크할 레이어 설정")] - public LayerMask groundLayer = -1; + public LayerMask groundLayer; + + [Tooltip("장애물로 체크할 레이어 설정")] + public LayerMask obstacleLayer = -1; [Range(0.01f, 0.5f), Tooltip("전방 감지 거리")] public float forwardCheckDistance = 0.1f; + + [Range(0.0f, 0.5f), Tooltip("전방 지면 인식 허용 거리")] + public float forwardCheckThreshold = 0.4f; [Range(0.1f, 10.0f), Tooltip("지면 감지 거리")] public float groundCheckDistance = 2.0f; - [Range(0.0f, 0.5f), Tooltip("지면 인식 허용 거리")] - public float groundCheckThreshold = 0.01f; + [Range(0.0f, 1f), Tooltip("지면 인식 허용 거리")] + public float groundCheckThreshold = 0.2f; } [Serializable] @@ -47,10 +53,10 @@ namespace BlueWaterProject public float moveSpeed = 10f; [Range(1f, 75f), Tooltip("등반 가능한 경사각")] - public float maxSlopeAngle = 50f; + public float maxSlopeAngle = 30f; [Range(1f, 50f), Tooltip("대쉬 속도")] - public float dashSpeed = 30f; + public float dashSpeed = 20f; [Range(0.1f, 1f), Tooltip("대쉬 시간")] public float dashTime = 0.2f; @@ -119,16 +125,15 @@ namespace BlueWaterProject get => MyCurrentState.isStunned; set => MyCurrentState.isStunned = value; } - private float capsuleRadiusDifferent; - private float castRadius; - private Vector3 CapsuleTopCenterPoint => new(transform.position.x, - transform.position.y + MyComponents.capsuleCollider.height - MyComponents.capsuleCollider.radius, - transform.position.z); - - private Vector3 CapsuleBottomCenterPoint => new(transform.position.x, - transform.position.y + MyComponents.capsuleCollider.radius, - transform.position.z); + private Vector3 CapsuleTop => MyComponents.rb.position + (MyComponents.capsuleCollider.center + + Vector3.up * (MyComponents.capsuleCollider.height * 0.5f - MyComponents.capsuleCollider.radius)) + * transform.localScale.x; + private Vector3 CapsuleBottom => MyComponents.rb.position + (MyComponents.capsuleCollider.center - + Vector3.up * (MyComponents.capsuleCollider.height * 0.5f - MyComponents.capsuleCollider.radius)) + * transform.localScale.x; + private float CapsuleRadius => MyComponents.capsuleCollider.radius * transform.localScale.x * 0.9f; + private float CapsuleHeight => MyComponents.capsuleCollider.height * transform.localScale.y; public static readonly int IsDashingHash = Animator.StringToHash("isDashing"); @@ -184,15 +189,10 @@ namespace BlueWaterProject if (!TryGetComponent(out MyComponents.capsuleCollider)) { MyComponents.capsuleCollider = gameObject.AddComponent(); - MyComponents.capsuleCollider.height = 2f; MyComponents.capsuleCollider.center = Vector3.up; MyComponents.capsuleCollider.radius = 0.5f; } - - var capsuleColliderRadius = MyComponents.capsuleCollider.radius; - castRadius = capsuleColliderRadius * 0.9f; - capsuleRadiusDifferent = capsuleColliderRadius - castRadius + 0.05f; } private void InitStartValue() @@ -282,10 +282,10 @@ namespace BlueWaterProject MyCurrentValue.groundNormal = Vector3.up; MyCurrentValue.groundSlopeAngle = 0f; MyCurrentValue.forwardSlopeAngle = 0f; - - var groundRaycast = Physics.SphereCast(CapsuleBottomCenterPoint, castRadius,Vector3.down, - out var hit, MyCheckOption.groundCheckDistance, MyCheckOption.groundLayer, QueryTriggerInteraction.Ignore); - + + var groundRaycast = Physics.CapsuleCast(CapsuleBottom, CapsuleTop, CapsuleRadius, + Vector3.down, out var hit, MyCheckOption.groundCheckDistance, MyCheckOption.groundLayer, QueryTriggerInteraction.Ignore); + MyCurrentState.isGrounded = false; if (groundRaycast) @@ -295,22 +295,8 @@ namespace BlueWaterProject MyCurrentValue.forwardSlopeAngle = Vector3.Angle(MyCurrentValue.groundNormal, MyCurrentValue.currentMoveDirection) - 90f; MyCurrentState.isOnSlope = MyCurrentValue.groundSlopeAngle > 0f && MyCurrentValue.groundSlopeAngle < MyMovementOption.maxSlopeAngle; MyCurrentState.isOnSteepSlope = MyCurrentValue.groundSlopeAngle >= MyMovementOption.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; - //} - - MyCurrentValue.groundDistance = Mathf.Max(hit.distance - capsuleRadiusDifferent - MyCheckOption.groundCheckThreshold, 0f); - MyCurrentState.isGrounded = (MyCurrentValue.groundDistance <= 0.0001f) && !MyCurrentState.isOnSteepSlope; + MyCurrentValue.groundDistance = Mathf.Max(hit.distance, 0f); + MyCurrentState.isGrounded = MyCurrentValue.groundDistance <= MyCheckOption.groundCheckThreshold; GizmosUpdateValue(ref gzGroundTouch, hit.point); } @@ -321,17 +307,34 @@ namespace BlueWaterProject /// 전방 장애물 검사 : 레이어 관계 없이 trigger가 아닌 모든 장애물 검사 private void CheckForward() { - var obstacleRaycast = Physics.CapsuleCast(CapsuleBottomCenterPoint, CapsuleTopCenterPoint, castRadius, - MyCurrentValue.currentMoveDirection + Vector3.down * 0.1f, - out var hit, MyCheckOption.forwardCheckDistance, -1, QueryTriggerInteraction.Ignore); + var start = MyComponents.rb.position + Vector3.up * (CapsuleHeight - (CapsuleHeight - MyCheckOption.forwardCheckThreshold) * 0.5f); + var boxScale = new Vector3(CapsuleRadius, (CapsuleHeight - MyCheckOption.forwardCheckThreshold) * 0.5f, CapsuleRadius); + var raycast = Physics.BoxCast(start, boxScale, MyCurrentValue.currentMoveDirection, out var hit, + Quaternion.identity, MyCheckOption.forwardCheckDistance,MyCheckOption.obstacleLayer, QueryTriggerInteraction.Ignore); MyCurrentState.isForwardBlocked = false; - if (obstacleRaycast) + + if (raycast) { - var forwardObstacleAngle = Vector3.Angle(hit.normal, Vector3.up); - MyCurrentState.isForwardBlocked = forwardObstacleAngle >= MyMovementOption.maxSlopeAngle; + MyCurrentState.isForwardBlocked = true; + return; + } - GizmosUpdateValue(ref gzForwardTouch, hit.point); + if (MyCurrentState.isOnSteepSlope) + { + start = MyComponents.rb.position + Vector3.up * 0.9f + MyCurrentValue.currentMoveDirection * MyCheckOption.forwardCheckDistance; + boxScale = new Vector3(CapsuleRadius, (CapsuleHeight - 0.4f) * 0.5f, CapsuleRadius); + var raycast2 = Physics.BoxCast(start, boxScale, Vector3.down, out var hit2, + Quaternion.identity, MyCheckOption.groundCheckDistance,MyCheckOption.groundLayer, QueryTriggerInteraction.Ignore); + + if (raycast2) + { + var angle = Vector3.Angle(hit2.normal, Vector3.up); + if (angle < MyMovementOption.maxSlopeAngle) + { + MyCurrentState.isOnSteepSlope = false; + } + } } } @@ -476,8 +479,26 @@ namespace BlueWaterProject gzGroundTouch + MyCurrentValue.groundCross); Gizmos.color = new Color(0.5f, 1.0f, 0.8f, 0.8f); - Gizmos.DrawWireSphere(CapsuleTopCenterPoint, castRadius); - Gizmos.DrawWireSphere(CapsuleBottomCenterPoint, castRadius); + + // CapsuleCast의 시작과 끝 위치를 표현 + Gizmos.color = Color.red; + Gizmos.DrawWireSphere(CapsuleBottom, CapsuleRadius); + Gizmos.DrawWireSphere(CapsuleTop, CapsuleRadius); + + // CapsuleCast가 이동할 경로 표현 + Gizmos.color = Color.blue; + Gizmos.DrawLine(CapsuleBottom, CapsuleBottom + Vector3.down * MyCheckOption.groundCheckDistance); + Gizmos.DrawLine(CapsuleTop, CapsuleTop + Vector3.down * MyCheckOption.groundCheckDistance); + + Gizmos.color = Color.green; + var start = MyComponents.rb.position + Vector3.up * 0.9f + + MyCurrentValue.previousMoveDirection * MyCheckOption.forwardCheckDistance; + var boxScale = new Vector3(CapsuleRadius, (CapsuleHeight - 0.4f) * 0.5f, CapsuleRadius); + Gizmos.DrawWireCube(start, boxScale * 2); + + // CapsuleCast의 종료 위치에 대한 캡슐을 표현 + //Gizmos.DrawWireSphere(CapsuleBottom + Vector3.down * MyCheckOption.groundCheckDistance, CapsuleRadius); + //Gizmos.DrawWireSphere(CapsuleTop + Vector3.down * MyCheckOption.groundCheckDistance, CapsuleRadius); } [System.Diagnostics.Conditional("UNITY_EDITOR")] diff --git a/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab b/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab index fce20a006..514dce3ab 100644 --- a/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab +++ b/BlueWater/Assets/05.Prefabs/Characters/Players/CombatPlayer.prefab @@ -297,9 +297,13 @@ MonoBehaviour: groundLayer: serializedVersion: 2 m_Bits: 8 - forwardCheckDistance: 0.1 - groundCheckDistance: 2 - groundCheckThreshold: 0.01 + obstacleLayer: + serializedVersion: 2 + m_Bits: 2183374079 + forwardCheckDistance: 0.2 + forwardCheckThreshold: 0.4 + groundCheckDistance: 1 + groundCheckThreshold: 0.5 k__BackingField: moveSpeed: 10 maxSlopeAngle: 30 @@ -332,8 +336,6 @@ MonoBehaviour: stunParticle: {fileID: 1597267395097946864} showGizmos: 1 gizmoRadius: 0.05 - showGUI: 1 - guiTextSize: 28 --- !u!1 &5711603842414715359 GameObject: m_ObjectHideFlags: 0 diff --git a/BlueWater/Assets/09.BehaviorTree/Enemy/Rhinoceros.asset b/BlueWater/Assets/09.BehaviorTree/Enemy/Rhinoceros.asset index 8981d5ae3..ece46848e 100644 --- a/BlueWater/Assets/09.BehaviorTree/Enemy/Rhinoceros.asset +++ b/BlueWater/Assets/09.BehaviorTree/Enemy/Rhinoceros.asset @@ -13,7 +13,7 @@ MonoBehaviour: m_Name: Rhinoceros m_EditorClassIdentifier: mBehaviorSource: - behaviorName: FieldMinion + behaviorName: Rhinoceros behaviorDescription: mTaskData: types: []