From 03e1b1303c348a0714c4f27c70d2d8e03106324f Mon Sep 17 00:00:00 2001 From: dal4segno Date: Mon, 16 Mar 2026 10:07:09 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=A0=81=EA=B3=BC=20=EC=B6=A9=EB=8F=8C?= =?UTF-8?q?=20=EC=8B=9C=20=EB=AF=B8=EB=81=84=EB=9F=AC=EC=A7=90=20=EB=B0=A9?= =?UTF-8?q?=EC=A7=80=20=EB=B0=8F=208=EB=B0=A9=ED=96=A5=20=EC=96=91?= =?UTF-8?q?=EC=9E=90=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OnControllerColliderHit으로 적 충돌 감지 - 충돌 방향으로의 이동만 차단하여 튕겨나가지 않음 - 충돌 normal을 45도 간격으로 양자화하여 8각형 충돌 느낌 구현 - Enemy 레이어 추가 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- Assets/Prefabs/Player/Player.prefab | 4 +- Assets/Scenes/Test.unity | 252 ++++++++++++++++++++++++ Assets/Scripts/Player/PlayerMovement.cs | 59 ++++++ ProjectSettings/TagManager.asset | 28 +-- 4 files changed, 315 insertions(+), 28 deletions(-) diff --git a/Assets/Prefabs/Player/Player.prefab b/Assets/Prefabs/Player/Player.prefab index 4beb6905..26019923 100644 --- a/Assets/Prefabs/Player/Player.prefab +++ b/Assets/Prefabs/Player/Player.prefab @@ -107,7 +107,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3} m_Name: m_EditorClassIdentifier: Unity.Netcode.Runtime::Unity.Netcode.NetworkObject - GlobalObjectIdHash: 652883547 + GlobalObjectIdHash: 291279334 InScenePlacedSourceGlobalObjectIdHash: 0 DeferredDespawnTick: 0 Ownership: 1 @@ -134,7 +134,7 @@ MonoBehaviour: m_EditorClassIdentifier: Colosseum.Game::Colosseum.Player.PlayerMovement ShowTopMostFoldoutHeaderGroup: 1 moveSpeed: 5 - rotationSpeed: 10 + rotationSpeed: 20 gravity: -9.81 jumpForce: 5 skillController: {fileID: 6912018896034183004} diff --git a/Assets/Scenes/Test.unity b/Assets/Scenes/Test.unity index 441071b9..b0a865cf 100644 --- a/Assets/Scenes/Test.unity +++ b/Assets/Scenes/Test.unity @@ -2204,6 +2204,90 @@ PrefabInstance: propertyPath: GlobalObjectIdHash value: 860882280 objectReference: {fileID: 0} + - target: {fileID: 104400745685976771, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 206321037099551389, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 431955683210940476, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 594165142498506689, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 842828772729772585, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 1086617606532003110, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 1234617898871017558, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 1292384969107659578, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 1440306172988742875, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 1588122973700742530, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 1740708835082066346, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 1873928265182300824, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2041557239823311723, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2241362454352591909, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2288141680885240895, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2340211872035134925, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2415457036875098620, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2605086358319163350, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2681448383646292488, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 2864310715832157281, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3063111890880673975, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} - target: {fileID: 3122493901255878198, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} propertyPath: m_LocalPosition.x value: 0 @@ -2244,10 +2328,178 @@ PrefabInstance: propertyPath: m_LocalEulerAnglesHint.z value: 0 objectReference: {fileID: 0} + - target: {fileID: 3269600551903220176, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3326888280409569218, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3352725294718723500, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3372720374960809146, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3484575805885599873, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3562221081501593981, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3600023888766224737, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 3909578168288232628, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 4106842225827616212, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 4257474871520186132, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 4881113030068753372, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 4907555613124042924, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 4942734049518229188, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 5145522830100439921, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 5155497143650189391, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} - target: {fileID: 5581648761285601425, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} propertyPath: m_Name value: TestBoss objectReference: {fileID: 0} + - target: {fileID: 5581648761285601425, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 5887309268024433402, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 5970114996815864269, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 5997948210555344810, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6087931461581053018, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6131278199186659323, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6136794623068662212, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6201506335658164542, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6390837018154540695, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6558294504835681445, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6598808044083799047, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6642539862574025585, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 6854064267625523455, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7219756004436029026, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7328507975609936173, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7365417276828796601, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7712328925792866858, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7761531641761992822, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7934168032744731372, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 7942784296981756020, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 8023062474814080782, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 8261813751583458739, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 8391637174048496892, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 8629582234569827256, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 8702064678408005649, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 8799891606027672612, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} + - target: {fileID: 8949738738676772673, guid: 56986b707b0dc09439cb35ff2f87dcc9, type: 3} + propertyPath: m_Layer + value: 6 + objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] diff --git a/Assets/Scripts/Player/PlayerMovement.cs b/Assets/Scripts/Player/PlayerMovement.cs index e5fe7b4c..26038283 100644 --- a/Assets/Scripts/Player/PlayerMovement.cs +++ b/Assets/Scripts/Player/PlayerMovement.cs @@ -31,6 +31,10 @@ namespace Colosseum.Player private bool isJumping; private bool wasGrounded; + // 적 충돌 방향 (이동 차단용) + private Vector3 blockedDirection; + private int enemyLayerMask; + /// /// 현재 이동 속도 (애니메이션용) /// @@ -79,6 +83,9 @@ namespace Colosseum.Player // 카메라 설정 SetupCamera(); + + // 적 레이어 마스크 초기화 + enemyLayerMask = LayerMask.GetMask("Enemy"); } /// @@ -233,10 +240,24 @@ namespace Colosseum.Player moveDirection = TransformDirectionByCamera(moveDirection); moveDirection.Normalize(); + // 충돌 방향으로의 이동 차단 (미끄러짐 방지) + if (blockedDirection != Vector3.zero) + { + float blockedAmount = Vector3.Dot(moveDirection, blockedDirection); + if (blockedAmount > 0f) + { + moveDirection -= blockedDirection * blockedAmount; + moveDirection.Normalize(); + } + } + // 이동 적용 Vector3 moveVector = moveDirection * moveSpeed * Time.deltaTime; characterController.Move(moveVector + velocity * Time.deltaTime); + // 충돌 방향 리셋 + blockedDirection = Vector3.zero; + // 회전 (이동 중일 때만) if (moveDirection != Vector3.zero) { @@ -330,5 +351,43 @@ namespace Colosseum.Player wasGrounded = characterController.isGrounded; } + + /// + /// CharacterController 충돌 처리. 적과 충돌 시 해당 방향 이동을 차단합니다. + /// 충돌 normal을 8방향으로 양자화하여 각진 충돌 느낌을 줍니다. + /// + private void OnControllerColliderHit(ControllerColliderHit hit) + { + // 적과의 충돌인지 확인 + if ((enemyLayerMask & (1 << hit.gameObject.layer)) != 0) + { + // 충돌 방향 저장 (이동 차단용) + blockedDirection = hit.normal; + blockedDirection.y = 0f; + blockedDirection.Normalize(); + + // 8방향으로 양자화 (45도 간격) + blockedDirection = QuantizeToOctagon(blockedDirection); + } + } + + /// + /// 방향을 8각형(45도 간격) 방향으로 양자화합니다. + /// + private Vector3 QuantizeToOctagon(Vector3 direction) + { + if (direction == Vector3.zero) + return direction; + + // 각도 계산 + float angle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg; + + // 45도 단위로 반올림 + float snappedAngle = Mathf.Round(angle / 45f) * 45f; + + // 다시 벡터로 변환 + float radians = snappedAngle * Mathf.Deg2Rad; + return new Vector3(Mathf.Sin(radians), 0f, Mathf.Cos(radians)); + } } } diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index 6413d11f..25813ec7 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -2,7 +2,7 @@ %TAG !u! tag:unity3d.com,2011: --- !u!78 &1 TagManager: - serializedVersion: 2 + serializedVersion: 3 tags: [] layers: - Default @@ -11,7 +11,7 @@ TagManager: - - Water - UI - - + - Enemy - - - @@ -50,27 +50,3 @@ TagManager: - Light Layer 5 - Light Layer 6 - Light Layer 7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -