diff --git a/Assets/Editor/EnemyControllerEditor.cs b/Assets/Editor/EnemyControllerEditor.cs index 23ac07cc..82dc98de 100644 --- a/Assets/Editor/EnemyControllerEditor.cs +++ b/Assets/Editor/EnemyControllerEditor.cs @@ -30,12 +30,6 @@ public class EnemyControllerEditor : Editor case EnemyState.Attack: GUI.backgroundColor = new Color(1, 1, 0, 1f); break; - case EnemyState.Move: - GUI.backgroundColor = new Color(0, 1, 1, 1f); - break; - case EnemyState.GetHit: - GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 1f); - break; case EnemyState.Dead: GUI.backgroundColor = new Color(1, 0, 0, 1f); break; @@ -55,12 +49,10 @@ public class EnemyControllerEditor : Editor EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Idle")) enemyController.SetState(EnemyState.Idle); if (GUILayout.Button("Trace")) enemyController.SetState(EnemyState.Trace); - if (GUILayout.Button("Attack")) enemyController.SetState(EnemyState.Attack); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Move")) enemyController.SetState(EnemyState.Move); - if (GUILayout.Button("GetHit")) enemyController.SetState(EnemyState.GetHit); + if (GUILayout.Button("Attack")) enemyController.SetState(EnemyState.Attack); if (GUILayout.Button("Dead")) enemyController.SetState(EnemyState.Dead); EditorGUILayout.EndHorizontal(); } diff --git a/Assets/JAY/Animation/Attack04.anim b/Assets/JAY/Animation/Attack04.anim index 0dd4649a..4c55f7c4 100644 --- a/Assets/JAY/Animation/Attack04.anim +++ b/Assets/JAY/Animation/Attack04.anim @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b7cd9ef4b089d4cb8c37104f3c8394664b89cb584cf7b9cb976a1f1843ebb4b2 -size 915194 +oid sha256:5d83b7ac61c2e7be0c4df6529e2a716d552181ebf981da79c54f2ccc8b4df009 +size 915187 diff --git a/Assets/JAY/Animation/Dead.anim b/Assets/JAY/Animation/Dead.anim new file mode 100644 index 00000000..2199b0f5 --- /dev/null +++ b/Assets/JAY/Animation/Dead.anim @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad0d83df86a9359a0c6c8155736ee5976da3ba1cd2193305968b96aa42686c67 +size 936551 diff --git a/Assets/JAY/Animation/Dead.anim.meta b/Assets/JAY/Animation/Dead.anim.meta new file mode 100644 index 00000000..88b82162 --- /dev/null +++ b/Assets/JAY/Animation/Dead.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 26572f377ac934546b30d6d9e0cab051 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JAY/Animation/UpperBody_Passthrough.anim b/Assets/JAY/Animation/UpperBody_Passthrough.anim new file mode 100644 index 00000000..119b1bfa --- /dev/null +++ b/Assets/JAY/Animation/UpperBody_Passthrough.anim @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1454353b71088e1cf194335868e06e115062d15030a5b00b96b3370bd3261595 +size 1309 diff --git a/Assets/JAY/Animation/UpperBody_Passthrough.anim.meta b/Assets/JAY/Animation/UpperBody_Passthrough.anim.meta new file mode 100644 index 00000000..ce377cbc --- /dev/null +++ b/Assets/JAY/Animation/UpperBody_Passthrough.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5caba6316080f564091600905868fb66 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JAY/Animation/WholeBody.mask b/Assets/JAY/Animation/WholeBody.mask new file mode 100644 index 00000000..849725b2 --- /dev/null +++ b/Assets/JAY/Animation/WholeBody.mask @@ -0,0 +1,109 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!319 &31900000 +AvatarMask: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: WholeBody + m_Mask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 + m_Elements: + - m_Path: + m_Weight: 1 + - m_Path: Body05 + m_Weight: 1 + - m_Path: Eye01 + m_Weight: 1 + - m_Path: Hair01 + m_Weight: 1 + - m_Path: Head01_Male + m_Weight: 1 + - m_Path: Mouth01 + m_Weight: 1 + - m_Path: root + m_Weight: 1 + - m_Path: root/pelvis + m_Weight: 1 + - m_Path: root/pelvis/spine_01 + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02 + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03 + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/BackpackBone + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/shoulderPadJoint_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/index_01_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/index_01_l/index_02_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/index_01_l/index_02_l/index_03_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/thumb_01_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/thumb_01_l/thumb_02_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/thumb_01_l/thumb_02_l/thumb_03_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_l/upperarm_l/lowerarm_l/hand_l/weapon_l + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/shoulderPadJoint_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/index_01_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/index_01_r/index_02_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/index_01_r/index_02_r/index_03_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/thumb_01_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/thumb_01_r/thumb_02_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/thumb_01_r/thumb_02_r/thumb_03_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/clavicle_r/upperarm_r/lowerarm_r/hand_r/weapon_r + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/CloakBone01 + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/CloakBone01/CloakBone02 + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/CloakBone01/CloakBone02/CloakBone03 + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/neck_01 + m_Weight: 1 + - m_Path: root/pelvis/spine_01/spine_02/spine_03/neck_01/head + m_Weight: 1 + - m_Path: root/pelvis/thigh_l + m_Weight: 1 + - m_Path: root/pelvis/thigh_l/calf_l + m_Weight: 1 + - m_Path: root/pelvis/thigh_l/calf_l/foot_l + m_Weight: 1 + - m_Path: root/pelvis/thigh_l/calf_l/foot_l/ball_l + m_Weight: 1 + - m_Path: root/pelvis/thigh_r + m_Weight: 1 + - m_Path: root/pelvis/thigh_r/calf_r + m_Weight: 1 + - m_Path: root/pelvis/thigh_r/calf_r/foot_r + m_Weight: 1 + - m_Path: root/pelvis/thigh_r/calf_r/foot_r/ball_r + m_Weight: 1 diff --git a/Assets/JAY/Animation/WholeBody.mask.meta b/Assets/JAY/Animation/WholeBody.mask.meta new file mode 100644 index 00000000..039ab723 --- /dev/null +++ b/Assets/JAY/Animation/WholeBody.mask.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6593ee38fd371db459652c920630d2c9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 31900000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JAY/Animation/Win.anim b/Assets/JAY/Animation/Win.anim new file mode 100644 index 00000000..efd6b576 --- /dev/null +++ b/Assets/JAY/Animation/Win.anim @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95e075dd19030d24e7199ebe2413567d8b80e2993d1726120c0c5eac4e8e73a9 +size 1220591 diff --git a/Assets/JAY/Animation/Win.anim.meta b/Assets/JAY/Animation/Win.anim.meta new file mode 100644 index 00000000..07a52f33 --- /dev/null +++ b/Assets/JAY/Animation/Win.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a3b0144fdb439d941b9e9014a1635178 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JAY/Animator/PlayerController.controller b/Assets/JAY/Animator/PlayerController.controller index 4c9ad755..9e9d7b5a 100644 --- a/Assets/JAY/Animator/PlayerController.controller +++ b/Assets/JAY/Animator/PlayerController.controller @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1c91b275bd31dd5542b32ae3205c9b28e7dd0225cde394431b345bee95a06306 -size 16228 +oid sha256:133f2c5386e1eb7ef1f6b0de157b50f79c31843107cc8d4291a128e3bd1b2a81 +size 20655 diff --git a/Assets/JAY/HousingUI.unity b/Assets/JAY/HousingUI.unity index 3f604c83..ba46b242 100644 --- a/Assets/JAY/HousingUI.unity +++ b/Assets/JAY/HousingUI.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:04d17aad8f57adf668bc3fe3bef9a990ac563a32935d0435a5c934a2e9b8ebda -size 73969 +oid sha256:55cf84a51994b5762122636fec95fc4053dab6d94394c496ce3dfc5b78d48970 +size 74215 diff --git a/Assets/JAY/Scripts/IPlayerAction/PlayerActionDash.cs b/Assets/JAY/Scripts/IPlayerAction/PlayerActionDash.cs new file mode 100644 index 00000000..e8336ea7 --- /dev/null +++ b/Assets/JAY/Scripts/IPlayerAction/PlayerActionDash.cs @@ -0,0 +1,56 @@ +using UnityEngine; + +public class PlayerActionDash : IPlayerAction +{ + private PlayerController player; + private float duration = 0.25f; // 대시 유지 시간 + private float timer; // 대시 경과 시간 + private Vector3 direction; // 대시 방향 + + private float dashSpeedMultiplier = 3f; // 기본 이동 속도의 n배 + private float dashSpeed; // 실제 대시 속도(계산한 값) + + public bool IsActive { get; private set; } // 현재 대시 중인지 여부 + + public void StartAction(PlayerController player) + { + this.player = player; + IsActive = true; + timer = 0f; + + // 조이스틱 입력값 있으면 그 방향, 없으면 캐릭터가 바라보는 방향 + direction = player.GetMoveDirectionOrForward().normalized; + + // 대시 속도 = 이동 속도 x 배수 + dashSpeed = player.moveSpeed * dashSpeedMultiplier; + + // TODO: 필요 시 애니메이션 재생 + // player.PlayerAnimator.SetTrigger("Roll"); + } + + public void UpdateAction() + { + if (!IsActive) return; + + DoDash(); + } + + private void DoDash() + { + timer += Time.deltaTime; + if (timer < duration) + { + player.CharacterController.Move(direction * dashSpeed * Time.deltaTime); + } + else + { + EndAction(); + } + } + + public void EndAction() + { + IsActive = false; + player = null; + } +} diff --git a/Assets/JAY/Scripts/IPlayerAction/PlayerActionDash.cs.meta b/Assets/JAY/Scripts/IPlayerAction/PlayerActionDash.cs.meta new file mode 100644 index 00000000..fd30de5b --- /dev/null +++ b/Assets/JAY/Scripts/IPlayerAction/PlayerActionDash.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: eceb0c738c2c4690b8b4dd02e10c7df4 +timeCreated: 1745459840 \ No newline at end of file diff --git a/Assets/JAY/Scripts/PlayerController.cs b/Assets/JAY/Scripts/PlayerController.cs index 33d0f019..2c841575 100644 --- a/Assets/JAY/Scripts/PlayerController.cs +++ b/Assets/JAY/Scripts/PlayerController.cs @@ -3,7 +3,7 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public enum PlayerState { None, Idle, Move, Hit, Dead } +public enum PlayerState { None, Idle, Move, Win, Hit, Dead } public class PlayerController : CharacterBase, IObserver { @@ -17,18 +17,22 @@ public class PlayerController : CharacterBase, IObserver private GameObject weapon; private WeaponController _weaponController; - private IPlayerState CurrentStateClass { get; set; } - private IPlayerAction currentAction; + private IPlayerState _currentStateClass { get; set; } + private IPlayerAction _currentAction; + public IPlayerAction CurrentAction => _currentAction; // 상태 관련 private PlayerStateIdle _playerStateIdle; private PlayerStateMove _playerStateMove; + private PlayerStateWin _playerStateWin; + private PlayerStateDead _playerStateDead; // 행동 관련 - private PlayerActionAttack attackAction; + private PlayerActionAttack _attackAction; + private PlayerActionDash _actionDash; // 외부에서도 사용하는 변수 - public FixedJoystick joystick { get; private set; } + public FixedJoystick Joystick { get; private set; } public PlayerState CurrentState { get; private set; } private Dictionary _playerStates; public Animator PlayerAnimator { get; private set; } @@ -38,9 +42,9 @@ public class PlayerController : CharacterBase, IObserver { PlayerAnimator = GetComponent(); _characterController = GetComponent(); - if (joystick == null) + if (Joystick == null) { - joystick = FindObjectOfType(); + Joystick = FindObjectOfType(); } } @@ -51,14 +55,19 @@ public class PlayerController : CharacterBase, IObserver // 상태 초기화 _playerStateIdle = new PlayerStateIdle(); _playerStateMove = new PlayerStateMove(); + _playerStateWin = new PlayerStateWin(); + _playerStateDead = new PlayerStateDead(); _playerStates = new Dictionary { { PlayerState.Idle, _playerStateIdle }, { PlayerState.Move, _playerStateMove }, + { PlayerState.Win, _playerStateWin }, + { PlayerState.Dead, _playerStateDead }, }; - attackAction = new PlayerActionAttack(); + _attackAction = new PlayerActionAttack(); + _actionDash = new PlayerActionDash(); PlayerInit(); } @@ -70,20 +79,23 @@ public class PlayerController : CharacterBase, IObserver _playerStates[CurrentState].Update(); } - // 현재 액션이 활성화 되어 있으면 Update 호출 - if (currentAction != null && currentAction.IsActive) { - currentAction.UpdateAction(); + // 대시 우선 입력 처리 + if (Input.GetKeyDown(KeyCode.Space)) + { + StartDashAction(); + return; } // 공격 입력 처리 - if (Input.GetKeyDown(KeyCode.X) && (currentAction == null || !currentAction.IsActive)) { + if (Input.GetKeyDown(KeyCode.X) && (_currentAction == null || !_currentAction.IsActive)) { StartAttackAction(); } - } - - public void StartAttackAction() { - currentAction = attackAction; - currentAction.StartAction(this); + + // 액션 업데이트 + if (_currentAction != null && _currentAction.IsActive) + { + _currentAction.UpdateAction(); + } } #region 초기화 관련 @@ -108,7 +120,9 @@ public class PlayerController : CharacterBase, IObserver } #endregion - + + #region 상태, 동작 변화 관련 + public void SetState(PlayerState state) { if (CurrentState != PlayerState.None) @@ -116,10 +130,36 @@ public class PlayerController : CharacterBase, IObserver _playerStates[CurrentState].Exit(); } CurrentState = state; - CurrentStateClass = _playerStates[state]; - CurrentStateClass.Enter(this); + _currentStateClass = _playerStates[state]; + _currentStateClass.Enter(this); } + + public void StartAttackAction() { + _currentAction = _attackAction; + _currentAction.StartAction(this); + } + + public void StartDashAction() + { + // 만약 공격 중이면 강제로 공격 종료 + if (_currentAction == _attackAction && _attackAction.IsActive) + { + _attackAction.EndAction(); // 애니메이션도 중단 + } + + // 기존 대시 중이면 중복 실행 안 함 + if (_actionDash.IsActive) + return; + + _currentAction = _actionDash; + _actionDash.StartAction(this); + } + + #endregion + + #region 공격 관련 + public void SwitchBattleMode() { _isBattle = !_isBattle; @@ -130,25 +170,43 @@ public class PlayerController : CharacterBase, IObserver public void SetAttackComboTrue() { if (_weaponController.IsAttacking) return; // 이미 공격 중이면 실행 안함 - if (currentAction == attackAction) { - attackAction.EnableCombo(); + if (_currentAction == _attackAction) { + _attackAction.EnableCombo(); _weaponController.AttackStart(); } } public void SetAttackComboFalse() { - if (currentAction == attackAction) { - attackAction.DisableCombo(); + if (_currentAction == _attackAction) { + _attackAction.DisableCombo(); _weaponController.AttackEnd(); } } + #endregion + + #region 대시 관련 + + public Vector3 GetMoveDirectionOrForward() + { + Vector3 dir = new Vector3(Joystick.Horizontal, 0, Joystick.Vertical); + return dir.sqrMagnitude > 0.01f ? dir.normalized : transform.forward; + } + + public void DashButtonPressed() + { + if (!_actionDash.IsActive) + { + StartDashAction(); + } + } + + #endregion + #region IObserver 관련 public void OnNext(GameObject value) { - Debug.Log("무기 타격"); - float playerAttackPower = _weaponController.AttackPower * attackPower; // 플레이어 공격 데미지(막타는 일반 데미지의 4배) } public void OnError(Exception error) @@ -161,4 +219,5 @@ public class PlayerController : CharacterBase, IObserver } #endregion + } diff --git a/Assets/JAY/Scripts/PlayerControllerEditor.cs b/Assets/JAY/Scripts/PlayerControllerEditor.cs index 0c7a78db..ffc4ec76 100644 --- a/Assets/JAY/Scripts/PlayerControllerEditor.cs +++ b/Assets/JAY/Scripts/PlayerControllerEditor.cs @@ -22,6 +22,7 @@ public class PlayerControllerEditor : Editor EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.LabelField("현재 상태", playerController.CurrentState.ToString(), EditorStyles.boldLabel); + EditorGUILayout.LabelField("현재 행동", playerController.CurrentAction != null ? playerController.CurrentAction.ToString() : "-", EditorStyles.boldLabel); EditorGUILayout.EndVertical(); @@ -38,10 +39,12 @@ public class PlayerControllerEditor : Editor if (GUILayout.Button("BattleMode")) playerController.SwitchBattleMode(); + if (GUILayout.Button("Win")) + playerController.SetState(PlayerState.Win); // if (GUILayout.Button("Hit")) // playerController.SetState(PlayerState.Hit); - // if (GUILayout.Button("Dead")) - // playerController.SetState(PlayerState.Dead); + if (GUILayout.Button("Dead")) + playerController.SetState(PlayerState.Dead); EditorGUILayout.EndHorizontal(); } diff --git a/Assets/JAY/Scripts/PlayerState/PlayerStateDead.cs b/Assets/JAY/Scripts/PlayerState/PlayerStateDead.cs new file mode 100644 index 00000000..7cdc433e --- /dev/null +++ b/Assets/JAY/Scripts/PlayerState/PlayerStateDead.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class PlayerStateDead : IPlayerState +{ + private PlayerController _playerController; + + public void Enter(PlayerController playerController) + { + _playerController = playerController; + _playerController.PlayerAnimator.SetBool("Dead", true); + } + + public void Update() + { + } + + public void Exit() + { + _playerController.PlayerAnimator.SetBool("Dead", false); + _playerController = null; + } +} diff --git a/Assets/JAY/Scripts/PlayerState/PlayerStateDead.cs.meta b/Assets/JAY/Scripts/PlayerState/PlayerStateDead.cs.meta new file mode 100644 index 00000000..7d0fa73a --- /dev/null +++ b/Assets/JAY/Scripts/PlayerState/PlayerStateDead.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b6fc619c4dc14ad98c56d083a62b56b7 +timeCreated: 1745481194 \ No newline at end of file diff --git a/Assets/JAY/Scripts/PlayerState/PlayerStateIdle.cs b/Assets/JAY/Scripts/PlayerState/PlayerStateIdle.cs index 733053ba..ed8ff3d3 100644 --- a/Assets/JAY/Scripts/PlayerState/PlayerStateIdle.cs +++ b/Assets/JAY/Scripts/PlayerState/PlayerStateIdle.cs @@ -11,8 +11,8 @@ public class PlayerStateIdle : IPlayerState public void Update() { - float inputHorizontal = _playerController.joystick.Horizontal; - float inputVertical = _playerController.joystick.Vertical; + float inputHorizontal = _playerController.Joystick.Horizontal; + float inputVertical = _playerController.Joystick.Vertical; // 이동 if (inputHorizontal != 0 || inputVertical != 0) diff --git a/Assets/JAY/Scripts/PlayerState/PlayerStateMove.cs b/Assets/JAY/Scripts/PlayerState/PlayerStateMove.cs index 97a6e84e..19f5bd7a 100644 --- a/Assets/JAY/Scripts/PlayerState/PlayerStateMove.cs +++ b/Assets/JAY/Scripts/PlayerState/PlayerStateMove.cs @@ -14,8 +14,8 @@ public class PlayerStateMove : IPlayerState public void Update() { - float inputHorizontal = _playerController.joystick.Horizontal; - float inputVertical = _playerController.joystick.Vertical; + float inputHorizontal = _playerController.Joystick.Horizontal; + float inputVertical = _playerController.Joystick.Vertical; // 이동 if (inputHorizontal != 0 || inputVertical != 0) @@ -36,8 +36,8 @@ public class PlayerStateMove : IPlayerState private void HandleMovement() { - float inputHorizontal = _playerController.joystick.Horizontal; - float inputVertical = _playerController.joystick.Vertical; + float inputHorizontal = _playerController.Joystick.Horizontal; + float inputVertical = _playerController.Joystick.Vertical; Vector3 moveDir = new Vector3(inputHorizontal, 0, inputVertical); Vector3 move = moveDir.normalized * _playerController.moveSpeed; diff --git a/Assets/JAY/Scripts/PlayerState/PlayerStateWin.cs b/Assets/JAY/Scripts/PlayerState/PlayerStateWin.cs new file mode 100644 index 00000000..83b8a1e4 --- /dev/null +++ b/Assets/JAY/Scripts/PlayerState/PlayerStateWin.cs @@ -0,0 +1,22 @@ +using UnityEngine; + +public class PlayerStateWin : IPlayerState +{ + private PlayerController _playerController; + + public void Enter(PlayerController playerController) + { + _playerController = playerController; + _playerController.PlayerAnimator.SetBool("Win", true); + } + + public void Update() + { + } + + public void Exit() + { + _playerController.PlayerAnimator.SetBool("Win", false); + _playerController = null; + } +} diff --git a/Assets/JAY/Scripts/PlayerState/PlayerStateWin.cs.meta b/Assets/JAY/Scripts/PlayerState/PlayerStateWin.cs.meta new file mode 100644 index 00000000..66374cd1 --- /dev/null +++ b/Assets/JAY/Scripts/PlayerState/PlayerStateWin.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e54b8d32431d4263a6a470f9a150b003 +timeCreated: 1745479273 \ No newline at end of file diff --git a/Assets/JAY/Scripts/WeaponController.cs b/Assets/JAY/Scripts/WeaponController.cs index 032227ce..199dbe04 100644 --- a/Assets/JAY/Scripts/WeaponController.cs +++ b/Assets/JAY/Scripts/WeaponController.cs @@ -47,6 +47,11 @@ public class WeaponController : MonoBehaviour, IObservable } _playerController = GetComponent(); + if (_playerController == null) + { + _playerController = GameObject.FindGameObjectWithTag("Player").GetComponent(); + } + _previousPositions = new Vector3[_triggerZones.Length]; _hitColliders = new HashSet(); } @@ -96,6 +101,17 @@ public class WeaponController : MonoBehaviour, IObservable if (!_hitColliders.Contains(hit.collider)) { _hitColliders.Add(hit.collider); + + Debug.Log("hit.collider.name: " + hit.collider.name); + if (hit.collider.gameObject.CompareTag("Enemy")) + { + var enemyController = hit.transform.GetComponent(); + if (enemyController != null) + { + enemyController.TakeDamage(AttackPower * _playerController.attackPower); + } + } + Notify(hit.collider.gameObject); } } diff --git a/Assets/JYY/Animator/PldDogControl.controller b/Assets/JYY/Animator/PldDogControl.controller index a67e40bf..7b80e503 100644 --- a/Assets/JYY/Animator/PldDogControl.controller +++ b/Assets/JYY/Animator/PldDogControl.controller @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9e37c8d0a91f3599d34a7715c632cbcf76fd3c0a96c5d5335ab9d6ff65d3b4c -size 18916 +oid sha256:9473c357cb74d4228523205a76d0a1a1cc71d82baf736270906c82a171efe7e6 +size 16154 diff --git a/Assets/JYY/Models.meta b/Assets/JYY/Models.meta new file mode 100644 index 00000000..7143abc3 --- /dev/null +++ b/Assets/JYY/Models.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ac3af37988877784e91ab90c4ade37d9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Models/Y Bot.fbx b/Assets/JYY/Models/Y Bot.fbx new file mode 100644 index 00000000..a5c4d7be --- /dev/null +++ b/Assets/JYY/Models/Y Bot.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:470fcb658dd731d414d635615d6232be394e7ea23915fb92ad41a0fca4d592bc +size 1982368 diff --git a/Assets/JYY/Models/Y Bot.fbx.meta b/Assets/JYY/Models/Y Bot.fbx.meta new file mode 100644 index 00000000..2e914645 --- /dev/null +++ b/Assets/JYY/Models/Y Bot.fbx.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: decb96f75d6a2344baa18f902f21a131 +ModelImporter: + serializedVersion: 22200 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + rigImportErrors: + rigImportWarnings: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 3 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 0 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 1 + importBlendShapes: 1 + importCameras: 1 + importLights: 1 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 0 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 3 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 1 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 1 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 3 + humanoidOversampling: 1 + avatarSetup: 1 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/AOEIndicator.prefab b/Assets/JYY/Prefabs/AOEIndicator.prefab deleted file mode 100644 index 6ac5eda7..00000000 --- a/Assets/JYY/Prefabs/AOEIndicator.prefab +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8b8cb01bd819acc4a85f049a7fa119e05a3587e1f3b9e88ce1f0f0729a09b326 -size 4274 diff --git a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab b/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab deleted file mode 100644 index 5b73b6cb..00000000 --- a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:db1f3ad7db0d99b20fdfe95c0ba7248476edee0875596606eb05ac19c33e84f2 -size 4283 diff --git a/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab b/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab index 72d92b28..10a01d7f 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab +++ b/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf0fd0659c187d35c8492ff925145c94fc5cac08dead6b13188f3f4cbb2f3052 -size 3988 +oid sha256:5fd0a892305c7a4c4e18543cf88703c940210e639e0a0a94aba30f0fe7fb4a2d +size 3986 diff --git a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab index d6ba9554..2617bea6 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab +++ b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5dfaa59aeffa4e948edd40e96f05e2c708e491bb80c2a3446d9d1335b05adf0 +oid sha256:a8dcf363afeb774bbc49dde7a349e233c2ff8531d33694113013455fc7a4c7ca size 3995 diff --git a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta index 586188cb..49096c4a 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta +++ b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 44d67bf59c049fb46876a549120a16d7 +guid: 0e60f1766f73dbc439ff69a154cc9a99 PrefabImporter: externalObjects: {} userData: diff --git a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab index 28217b13..7acabcd4 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab +++ b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02ada0ed142206f604609397dd5b6a2349df7db879e9ab1cb7bdfc1fca8e6f75 +oid sha256:e8da3f157ed92e5524a0fb90cbd4335a8b757a2ef2889f00ae2e66bd704017e6 size 3985 diff --git a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta index 2202360a..877a5f21 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta +++ b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9adff7c5e2e43974fa9f2d241ef2e433 +guid: dc0537feab3e2944aa554e23fb3923a3 PrefabImporter: externalObjects: {} userData: diff --git a/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab new file mode 100644 index 00000000..20a9ce49 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da22007db35be49ea0f412048256923f214ff6be182768aba94ea8137146c067 +size 5237 diff --git a/Assets/JYY/Prefabs/AOEIndicator.prefab.meta b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab.meta similarity index 100% rename from Assets/JYY/Prefabs/AOEIndicator.prefab.meta rename to Assets/JYY/Prefabs/AoE Indicator Chariot.prefab.meta diff --git a/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab b/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab new file mode 100644 index 00000000..3b79cddf --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27404af56e20a87bf6555fc1bbad80f7756f8412d15bccca896ea8c98a221ff7 +size 4474 diff --git a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab.meta b/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab.meta similarity index 74% rename from Assets/JYY/Prefabs/AOEIndicatorChariot.prefab.meta rename to Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab.meta index 1d15c4e7..586188cb 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab.meta +++ b/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e9e020ef2784edf4ca2a83ae9e1edefd +guid: 44d67bf59c049fb46876a549120a16d7 PrefabImporter: externalObjects: {} userData: diff --git a/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab b/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab new file mode 100644 index 00000000..438c2522 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6f2c2d8b80d4562e9a72bfc313a716717ae8bf33192053e85b12aeea9b9b9ff +size 4459 diff --git a/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab.meta b/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab.meta new file mode 100644 index 00000000..2202360a --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9adff7c5e2e43974fa9f2d241ef2e433 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab new file mode 100644 index 00000000..995bcd81 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d42386e12ec2eec2385f13fdcd2558718c9150245a834d5a667060f750b1ced +size 3100 diff --git a/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab.meta b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab.meta new file mode 100644 index 00000000..5ba3ecc5 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3f431e991bd65014c833e89305ddd5e3 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/Charge slash red.prefab b/Assets/JYY/Prefabs/Charge slash red.prefab new file mode 100644 index 00000000..3f562bef --- /dev/null +++ b/Assets/JYY/Prefabs/Charge slash red.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:401068a261779945bc03fed98b231b07965d7520470f19f5b1ff2b6bf73b4f59 +size 710841 diff --git a/Assets/JYY/Prefabs/Charge slash red.prefab.meta b/Assets/JYY/Prefabs/Charge slash red.prefab.meta new file mode 100644 index 00000000..bf5f20d3 --- /dev/null +++ b/Assets/JYY/Prefabs/Charge slash red.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8a0ddc8dd6d760e4e93999c4d49dc16c +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/Explosion.prefab b/Assets/JYY/Prefabs/Explosion.prefab new file mode 100644 index 00000000..780b51ec --- /dev/null +++ b/Assets/JYY/Prefabs/Explosion.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a95da2a8bdc43724d48bc36adc162d419090185d28b9df881af7de481a53c4f3 +size 473754 diff --git a/Assets/JYY/Prefabs/Explosion.prefab.meta b/Assets/JYY/Prefabs/Explosion.prefab.meta new file mode 100644 index 00000000..5f3ac223 --- /dev/null +++ b/Assets/JYY/Prefabs/Explosion.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2ccd5acc2f6d74d4bb687fd2ee94b9de +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/Red energy explosion 1.prefab b/Assets/JYY/Prefabs/Red energy explosion 1.prefab new file mode 100644 index 00000000..39f7c17d --- /dev/null +++ b/Assets/JYY/Prefabs/Red energy explosion 1.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1364f3853992b0997dcd5fb86204334c243e4b464bf6d96da6374dcb2e98f8d9 +size 1305159 diff --git a/Assets/JYY/Prefabs/Red energy explosion 1.prefab.meta b/Assets/JYY/Prefabs/Red energy explosion 1.prefab.meta new file mode 100644 index 00000000..a8bb01f0 --- /dev/null +++ b/Assets/JYY/Prefabs/Red energy explosion 1.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 49ada3fea2be23f4a988d4bc21dcaa32 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/Snow slash 1.prefab b/Assets/JYY/Prefabs/Snow slash 1.prefab new file mode 100644 index 00000000..4b1759bb --- /dev/null +++ b/Assets/JYY/Prefabs/Snow slash 1.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72a13e9bb38f18954e603c863b4b610882f8b43d55ba27499daf3bcfe42830b8 +size 474114 diff --git a/Assets/JYY/Prefabs/Snow slash 1.prefab.meta b/Assets/JYY/Prefabs/Snow slash 1.prefab.meta new file mode 100644 index 00000000..a886fdef --- /dev/null +++ b/Assets/JYY/Prefabs/Snow slash 1.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 03a874e2d684ee04a9729b8363fdbb9c +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/[Enemy] PldDog.prefab b/Assets/JYY/Prefabs/[Enemy] PldDog.prefab index f383c5f8..8b998d43 100644 --- a/Assets/JYY/Prefabs/[Enemy] PldDog.prefab +++ b/Assets/JYY/Prefabs/[Enemy] PldDog.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7b23e4a2f6475f6cfe0641a03fd4415fe2b732fe649a14f93b72ea104f250f3 -size 80026 +oid sha256:a4cedd199100ba2d66a0dfe22b6ab902677fcc6485b02d0553115d0e012b3c97 +size 79510 diff --git a/Assets/JYY/Scenes/MonsterTest.unity b/Assets/JYY/Scenes/MonsterTest.unity index a2f28549..f315080d 100644 --- a/Assets/JYY/Scenes/MonsterTest.unity +++ b/Assets/JYY/Scenes/MonsterTest.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec97ec66df4283ed273c243f4aa1642c492661d1163184ce650d833e5a36bd87 -size 19269 +oid sha256:70e2e15667c9821fdb140d6ca8987d4caf3436e36abc139ba9da1192a5428331 +size 21018 diff --git a/Assets/KJM/KJM.unity b/Assets/KJM/KJM.unity index 0d91b2f4..09606b0d 100644 --- a/Assets/KJM/KJM.unity +++ b/Assets/KJM/KJM.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7f13f719e71b8e944fc097d5a437f5e135e094a1cf536cc80881327f9a5dbe59 -size 48687 +oid sha256:72074771a04b1e569bf2994ccbbf0fa4598b680121664c502cf750c8f77fd2f7 +size 49861 diff --git a/Assets/KJM/KJM_Test/ISaveable.cs b/Assets/KJM/KJM_Test/ISaveable.cs new file mode 100644 index 00000000..a7d44c8e --- /dev/null +++ b/Assets/KJM/KJM_Test/ISaveable.cs @@ -0,0 +1,8 @@ +/// +/// 세이브 데이터를 주고 받는 함수 인터페이스 +/// +public interface ISaveable +{ + void ApplySaveData(Save save); + Save ExtractSaveData(); +} diff --git a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs.meta b/Assets/KJM/KJM_Test/ISaveable.cs.meta similarity index 83% rename from Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs.meta rename to Assets/KJM/KJM_Test/ISaveable.cs.meta index 032dac99..d61a3136 100644 --- a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs.meta +++ b/Assets/KJM/KJM_Test/ISaveable.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a5765847dbef51e4f9bccde712eeda30 +guid: b8b6bcb2e37dea949b70a8a96f96e44b MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/KJM/KJM_Test/Save.cs b/Assets/KJM/KJM_Test/Save.cs index 5687fb38..0cab35af 100644 --- a/Assets/KJM/KJM_Test/Save.cs +++ b/Assets/KJM/KJM_Test/Save.cs @@ -6,14 +6,27 @@ using UnityEngine; public class DungeonSave { // 강화 수치 - public int attackLevel; - public int attackSpeedLevel; - public int heartLevel; - public int moveSpeedLevel; - public int evasionTimeLevel; + public int attackLevel = 0; + public int attackSpeedLevel = 0; + public int heartLevel = 0; + public int moveSpeedLevel = 0; + public int evasionTimeLevel = 0; // 현재 진행 중인 스테이지 - public int stageLevel; + public int stageLevel = 0; + + //병합을 위한 메서드 + public void MergeWith(DungeonSave other) + { + if (other == null) return; + + if (other.attackLevel != 0) attackLevel = other.attackLevel; + if (other.attackSpeedLevel != 0) attackSpeedLevel = other.attackSpeedLevel; + if (other.heartLevel != 0) heartLevel = other.heartLevel; + if (other.moveSpeedLevel != 0) moveSpeedLevel = other.moveSpeedLevel; + if (other.evasionTimeLevel != 0) evasionTimeLevel = other.evasionTimeLevel; + if (other.stageLevel != 0) stageLevel = other.stageLevel; + } } // 일상(자취방) 관련 저장 데이터 @@ -21,17 +34,30 @@ public class DungeonSave public class HomeSave { // 일상 시간 - public float time; - public int day; + public int currentDay = 0; + public float time = 999; + // 체력 및 평판 수치 - public float health; - public float reputation; + public float health = 999; + public float reputation = 999; //이벤트 - public bool isEvent; - public int mealCount; - public int houseworkCount; + public int mealCount = 999; + public int houseworkCount = 999; + + //병합을 위한 메서드 + public void MergeWith(HomeSave other) + { + if (other == null) return; + + if (other.currentDay != 0) currentDay = other.currentDay; + if (other.time < 999) time = other.time; + if (other.health < 999) health = other.health; + if (other.reputation < 999) reputation = other.reputation; + if (other.mealCount < 999) mealCount = other.mealCount; + if (other.houseworkCount < 999) houseworkCount = other.houseworkCount; + } } // 게임 전체 저장 구조 diff --git a/Assets/KJM/KJM_Test/SaveDataController.cs b/Assets/KJM/KJM_Test/SaveDataController.cs new file mode 100644 index 00000000..58cb82e8 --- /dev/null +++ b/Assets/KJM/KJM_Test/SaveDataController.cs @@ -0,0 +1,82 @@ +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using UnityEngine; + +public class SaveDataController : MonoBehaviour +{ + [SerializeField] private MonoBehaviour[] saveableBehaviours; + private ISaveable[] saveables; + private Save tmpSave; + + void Awake() + { + tmpSave = new Save(); + + saveables = saveableBehaviours.OfType().ToArray(); + + if (saveables == null || saveables.Length == 0) + saveables = FindObjectsOfType().OfType().ToArray(); + } + + //세이브를 현재 상태에 적용 + public void ApplySaveData(Save saveData) + { + GetSaveDataFromManager(saveData); + SendSaveDataToClass(); + } + + //현재 상태를 세이브에 적용 + public Save GetSaveData() + { + UpdateSaveData(); + return tmpSave; + } + + //로컬에서 로드한 세이브 데이터를 받아오는 함수. + private void GetSaveDataFromManager(Save saveData) + { + tmpSave = saveData; + } + + //세이브 데이터를 각클래스에게 적용하는 함수. + private void SendSaveDataToClass() + { + foreach (var s in saveables) + { + s.ApplySaveData(tmpSave); + } + } + + //각 클래스에게서 현재 정보를 받아오는 함수. + private void UpdateSaveData() + { + foreach (var s in saveables) + { + Save partial = s.ExtractSaveData(); + MergeSave(ref tmpSave, partial); + } + } + + private void MergeSave(ref Save baseSave, Save newSave) + { + if (newSave == null) return; + + if (newSave.dungeonSave != null) + { + if (baseSave.dungeonSave == null) + baseSave.dungeonSave = new DungeonSave(); + + baseSave.dungeonSave.MergeWith(newSave.dungeonSave); + } + + if (newSave.homeSave != null) + { + if (baseSave.homeSave == null) + baseSave.homeSave = new HomeSave(); + + baseSave.homeSave.MergeWith(newSave.homeSave); + } + } +} diff --git a/Assets/KJM/KJM_Test/SaveDataController.cs.meta b/Assets/KJM/KJM_Test/SaveDataController.cs.meta new file mode 100644 index 00000000..895cec8c --- /dev/null +++ b/Assets/KJM/KJM_Test/SaveDataController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2e5de90e465e1ed4f91e2e6f11e17273 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/KJM/KJM_Test/SaveManager.cs b/Assets/KJM/KJM_Test/SaveManager.cs index 0b9c8df1..773cff46 100644 --- a/Assets/KJM/KJM_Test/SaveManager.cs +++ b/Assets/KJM/KJM_Test/SaveManager.cs @@ -12,7 +12,8 @@ public class SaveManager : Singleton private const string SaveFolder = "QuickSave"; private string MainSaveFilePath => GetSavePath("Save_Main"); private string BackupSaveFilePath => GetSavePath("Save_Backup"); - + + [SerializeField] private SaveDataController saveDataController; private Save mainSave; private Save backupSave; @@ -25,7 +26,7 @@ public class SaveManager : Singleton public void Save() { - if(JsonUtility.ToJson(mainSave) == JsonUtility.ToJson(StatManager.instance.ToSaveData())) //같은 상태는 저장되지 않음. 백업 덮어쓰기 방지. + if(JsonUtility.ToJson(mainSave) == JsonUtility.ToJson(saveDataController.GetSaveData())) //같은 상태는 저장되지 않음. 백업 덮어쓰기 방지. return; EnsureSaveExists(); @@ -45,7 +46,7 @@ public class SaveManager : Singleton mainSave = LoadMain(); backupSave = LoadBackup(); - StatManager.instance.loadSaveData2StataManager(mainSave); + saveDataController.ApplySaveData(mainSave); Debug.Log("메인 로드" + mainSave.homeSave.reputation); //임시 코드 Debug.Log("백업 로드" + backupSave.homeSave.reputation); //임시 코드 @@ -53,7 +54,7 @@ public class SaveManager : Singleton private void UpdateSaveInfo() { - mainSave = StatManager.instance.ToSaveData(); //스탯을 관리하는 클래스에 선언된 스탯 업데이트 함수를 호출 + mainSave = saveDataController.GetSaveData(); //스탯을 관리하는 클래스에 선언된 스탯 업데이트 함수를 호출 } private void SaveMain() @@ -119,7 +120,7 @@ public class SaveManager : Singleton //더미 세이브 파일 생성 private Save CreateNewSave() { - var fresh = StatManager.instance.ToSaveData(); + var fresh = saveDataController.GetSaveData(); SaveMain(); SaveBackup(); return fresh; diff --git a/Assets/KJM/KJM_Test/StatManager.cs b/Assets/KJM/KJM_Test/StatManager.cs deleted file mode 100644 index b0129abc..00000000 --- a/Assets/KJM/KJM_Test/StatManager.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.SceneManagement; -using Random = UnityEngine.Random; - -/// -/// 테스트용 임시 클래스 -/// -public class StatManager : MonoBehaviour -{ - public static StatManager instance; - - public int attackLevel; - public int attackSpeedLevel; - public int heartLevel; - public int moveSpeedLevel; - public int evasionTimeLevel; - public int stageLevel; - - public float time; - public int day; - public float health; - public float reputation; - - public bool isEvent; //Todo 이벤트 여부 및 관련 조건들 추가 - public int mealCount; - public int houseworkCount; - - - private void Awake() - { - instance = this; - } - - /// - /// 스탯값 변화 - /// - public void ChangeValue() - { - float floatValue = Random.Range(0f, 2f); - Debug.Log(floatValue); - int intValue = Random.Range(0, 10); - Debug.Log(intValue); - - attackLevel = intValue; - attackSpeedLevel = intValue; - heartLevel = intValue; - moveSpeedLevel = intValue; - evasionTimeLevel = intValue; - stageLevel = intValue; - - - time = floatValue; - day = intValue; - health = floatValue; - reputation = floatValue; - - isEvent = false; - mealCount = intValue; - houseworkCount = intValue; - - Debug.Log("ChangeValue"); - - } - - /// - /// 스탯값 반환 - /// - /// - public Save ToSaveData() - { - return new Save - { - dungeonSave = new DungeonSave - { - attackLevel = this.attackLevel, - attackSpeedLevel = this.attackSpeedLevel, - heartLevel = this.heartLevel, - moveSpeedLevel = this.moveSpeedLevel, - evasionTimeLevel = this.evasionTimeLevel, - stageLevel = this.stageLevel - }, - homeSave = new HomeSave - { - time = this.time, - day = this.day, - health = this.health, - reputation = this.reputation, - isEvent = false, - mealCount = this.mealCount, - houseworkCount = this.houseworkCount, - } - }; - } - - public void loadSaveData2StataManager(Save saveData) - { - attackLevel = saveData.dungeonSave.attackLevel; - attackSpeedLevel = saveData.dungeonSave.attackSpeedLevel; - heartLevel = saveData.dungeonSave.heartLevel; - moveSpeedLevel = saveData.dungeonSave.moveSpeedLevel; - evasionTimeLevel = saveData.dungeonSave.evasionTimeLevel; - stageLevel = saveData.dungeonSave.stageLevel; - - time = saveData.homeSave.time; - day = saveData.homeSave.day; - health = saveData.homeSave.health; - reputation = saveData.homeSave.reputation; - isEvent = saveData.homeSave.isEvent; - mealCount = saveData.homeSave.mealCount; - houseworkCount = saveData.homeSave.houseworkCount; - } - - public void SceneChange() - { - SceneManager.LoadScene("Main"); - } -} diff --git a/Assets/KJM/KJM_Test/TestScript.cs b/Assets/KJM/KJM_Test/TestScript.cs new file mode 100644 index 00000000..107b18ab --- /dev/null +++ b/Assets/KJM/KJM_Test/TestScript.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; +using Random = UnityEngine.Random; + +/// +/// 테스트용 임시 클래스 +/// +public class TestScript : MonoBehaviour,ISaveable +{ + //던전 + private int attackLevel; + private int attackSpeedLevel; + private int heartLevel; + private int moveSpeedLevel; + private int evasionTimeLevel; + private int stageLevel; + + //일상 + private float time; + private int currentDay; + private float health; + private float reputation; + private int mealCount; + private int houseworkCount; + + /// + /// 스탯값 랜덤 변화 + /// + public void ChangeValue() + { + float floatValue = Random.Range(0f, 2f); + int intValue = Random.Range(0, 10); + + attackLevel = intValue; + attackSpeedLevel = intValue; + heartLevel = intValue; + moveSpeedLevel = intValue; + stageLevel = intValue; + + + time = floatValue; + currentDay = intValue; + health = floatValue; + reputation = floatValue; + mealCount = intValue; + houseworkCount = intValue; + + Debug.Log("ChangeValue : " + floatValue); + } + + /// + /// 인터페이스 함수1, 데이터 불러오기 + /// + /// + public void ApplySaveData(Save save) + { + if (save?.dungeonSave != null) + { + attackLevel = save.dungeonSave.attackLevel; + attackSpeedLevel = save.dungeonSave.attackSpeedLevel; + heartLevel = save.dungeonSave.heartLevel; + moveSpeedLevel = save.dungeonSave.moveSpeedLevel; + evasionTimeLevel = save.dungeonSave.evasionTimeLevel; + stageLevel = save.dungeonSave.stageLevel; + } + + if (save?.homeSave != null) + { + time = save.homeSave.time; + currentDay = save.homeSave.currentDay; + health = save.homeSave.health; + reputation = save.homeSave.reputation; + mealCount = save.homeSave.mealCount; + houseworkCount = save.homeSave.houseworkCount; + + Debug.Log("ApplySaveData : " + reputation); + } + } + + /// + /// 인터페이스 함수2, 데이터 전달 + /// + /// + public Save ExtractSaveData() + { + return new Save + { + dungeonSave = new DungeonSave() + { + attackLevel = this.attackLevel, + attackSpeedLevel = this.attackSpeedLevel, + heartLevel = this.heartLevel, + moveSpeedLevel = this.moveSpeedLevel, + evasionTimeLevel = this.evasionTimeLevel, + stageLevel = this.stageLevel, + + }, + + homeSave = new HomeSave + { + time = this.time, + currentDay = this.currentDay, + health = this.health, + reputation = this.reputation, + mealCount = this.mealCount, + houseworkCount = this.houseworkCount + } + }; + } + + /// + /// 씬 전환 테스트용 함수 + /// + public void SceneChange() + { + SceneManager.LoadScene("Main"); + } + +} diff --git a/Assets/KJM/KJM_Test/StatManager.cs.meta b/Assets/KJM/KJM_Test/TestScript.cs.meta similarity index 100% rename from Assets/KJM/KJM_Test/StatManager.cs.meta rename to Assets/KJM/KJM_Test/TestScript.cs.meta diff --git a/Assets/KSH/DungeonLogic.cs b/Assets/KSH/DungeonLogic.cs new file mode 100644 index 00000000..3a8bccc6 --- /dev/null +++ b/Assets/KSH/DungeonLogic.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class DungeonLogic : MonoBehaviour +{ + [NonSerialized] public bool isCompleted = false; // 던전 클리어 여부 + [NonSerialized] public bool isFailed = false; // 던전 실패 여부 + + private PlayerController _player; + private EnemyController _enemy; + + // 던전 결과 이벤트 + public event Action OnDungeonSuccess; + public event Action OnDungeonFailure; + + private void Start() + { + // tag를 통해 할당 / 추후 플레이어와 에너미 태그 추가 필요 + _player = GameObject.FindGameObjectWithTag("Player").GetComponent(); + _enemy = GameObject.FindGameObjectWithTag("Enemy").GetComponent(); + + // 죽음 이벤트 구독 + if (_player != null) + { + _player.OnDeath += OnPlayerDeath; + } + + if (_enemy != null) + { + _enemy.OnDeath += OnEnemyDeath; + } + } + + // 플레이어 사망 처리 + private void OnPlayerDeath(CharacterBase player) + { + Debug.Log("player name:" + player.characterName); + if (!isFailed) // 중복 실행 방지 + { + FailDungeon(); + } + } + + // 적 사망 처리 + private void OnEnemyDeath(CharacterBase enemy) + { + Debug.Log("enemy name:" + enemy.characterName); + if (!isCompleted) // 중복 실행 방지 + { + CompleteDungeon(); + } + } + + // 던전 성공 처리 + public void CompleteDungeon() + { + if (!isCompleted && !isFailed) + { + Debug.Log("던전 공략 성공~!"); + isCompleted = true; + OnDungeonSuccess?.Invoke(); + + // 성공 UI 표시 ?? 강화 표기 + // TODO: 강화 시스템으로 넘어가고 일상 맵으로 이동 + } + } + + // 던전 실패 처리 + public void FailDungeon() + { + if (!isCompleted && !isFailed) + { + Debug.Log("던전 공략 실패~!"); + isFailed = true; + OnDungeonFailure?.Invoke(); + + // 죽음 애니메이션 + 실패 UI 표시 ? + // GameManager.Instance.ChangeToHomeScene(); + + StartCoroutine(DelayedSceneChange()); // 테스트를 위해 3초 대기 후 전환 + } + } + + private IEnumerator DelayedSceneChange() + { + yield return new WaitForSeconds(3f); + GameManager.Instance.ChangeToHomeScene(); + } + + // 게임 오브젝트 제거 시 이벤트 구독 해제 + private void OnDestroy() + { + if (_player != null) + { + _player.OnDeath -= OnPlayerDeath; + } + + if (_enemy != null) + { + _enemy.OnDeath -= OnEnemyDeath; + } + } +} diff --git a/Assets/KSH/DungeonLogic.cs.meta b/Assets/KSH/DungeonLogic.cs.meta new file mode 100644 index 00000000..3aba7c5a --- /dev/null +++ b/Assets/KSH/DungeonLogic.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ecf4896d6eb9a514e8f83175d8a33a22 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/KSH/DungeonTestScene.unity b/Assets/KSH/DungeonTestScene.unity new file mode 100644 index 00000000..b8ce1c3e --- /dev/null +++ b/Assets/KSH/DungeonTestScene.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3f988deb686f35d4ca0aeb90dcf4d726ccff34a27d1b5f0e020b0ceeb008606 +size 185731 diff --git a/Assets/KSH/DungeonTestScene.unity.meta b/Assets/KSH/DungeonTestScene.unity.meta new file mode 100644 index 00000000..644cb14d --- /dev/null +++ b/Assets/KSH/DungeonTestScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4563b107911b0e54cbdf659694a6f17a +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/LIN/DailyRoutine/InteractionController.cs b/Assets/LIN/DailyRoutine/InteractionController.cs index fc12daee..8841923d 100644 --- a/Assets/LIN/DailyRoutine/InteractionController.cs +++ b/Assets/LIN/DailyRoutine/InteractionController.cs @@ -13,6 +13,13 @@ public class InteractionController : MonoBehaviour [Header("UI 연동")] [SerializeField] HousingCanvasController housingCanvasController; + private SuddenEventController _suddenEventController = new SuddenEventController(); + + private void Start() + { + playerStats.OnWorked += SuddenAfterWorkEventHappen; + } + // 상호작용 가능한 사물 범위에 들어올 때 private void OnTriggerEnter(Collider other) { @@ -37,64 +44,47 @@ public class InteractionController : MonoBehaviour // ActionType 별로 화면에 상호작용 내용 표시, 상호작용 버튼에 이벤트 작성 private void PopActionOnScreen(ActionType interactionType) { - switch (interactionType) + HousingConstants.interactions.TryGetValue(interactionType, out var interactionTexts); + + housingCanvasController.ShowInteractionButton(interactionTexts.ActionText,interactionTexts.DescriptionText,()=> { - case ActionType.Sleep: - housingCanvasController.ShowInteractionButton("침대에서 잘까?","숙면으로 시간 당 체력 1을 회복한다.", () => + if (playerStats.CanPerformByHealth(interactionType)) + { + playerStats.PerformAction(interactionType); + } + else + { + housingCanvasController.SetActionText(interactionTexts.LackOfHealth); + housingCanvasController.SetDescriptionText(); + } + }); + } + + public Action SuddenEventHappen() + { + return null; + } + + public void SuddenAfterWorkEventHappen() + { + AfterWorkEvent afterWorkEvent = _suddenEventController.SuddenEventCalculator(); + if (afterWorkEvent == AfterWorkEvent.None) + return; + switch (afterWorkEvent) + { + case AfterWorkEvent.OvertimeWork: + housingCanvasController.ShowSuddenEventPanel("부장님이 퇴근을 안하셔.. 야근할까?", () => { - playerStats.PerformAction(ActionType.Sleep); - housingCanvasController.HideInteractionButton(); - //TODO: 화면 전환 효과와 UI 업데이트 작업 + //Todo: 컷씬과 스테이터스 변경 + housingCanvasController.HideSuddenEventPanel(); }); break; - case ActionType.Housework: - housingCanvasController.ShowInteractionButton("밀린 집안일을 처리할까?","체력 1을 사용하고 좋은일이 일어날지도 모른다", () => + case AfterWorkEvent.TeamGathering: + housingCanvasController.ShowSuddenEventPanel("갑자기 팀 회식이 잡혔다. 참석 하러 가자", () => { - if (playerStats.CanPerformByHealth(ActionType.Housework)) - { - playerStats.PerformAction(ActionType.Housework); - housingCanvasController.HideInteractionButton(); - //TODO: 집안일 후 랜덤 강화 효과 적용 - } - else - { - housingCanvasController.SetActionText("힘들어서 못해.."); - housingCanvasController.SetDescriptionText(); - } + housingCanvasController.HideSuddenEventPanel(); }); break; - case ActionType.Dungeon: - housingCanvasController.ShowInteractionButton("던전에 입장할까?","체력 3을 사용하고 3시간이 흐른다.", () => - { - if (playerStats.CanPerformByHealth(ActionType.Dungeon)) - { - playerStats.PerformAction(ActionType.Dungeon); - housingCanvasController.HideInteractionButton(); - } - else - { - housingCanvasController.SetActionText("던전에 갈 체력이 되지 않아.."); - housingCanvasController.SetDescriptionText(); - } - }); - break; - case ActionType.Work: - housingCanvasController.ShowInteractionButton("출근한다.","체력 3을 사용하고 저녁 6시에나 돌아오겠지..", () => - { - if (playerStats.CanPerformByHealth(ActionType.Work)) - { - playerStats.PerformAction(ActionType.Work); - housingCanvasController.HideInteractionButton(); - } - else - { - housingCanvasController.SetActionText("도저히 출근할 체력이 안되는걸..?"); - housingCanvasController.SetDescriptionText(); - } - }); - break; - default: - break; } } } diff --git a/Assets/LIN/Housing Copy.unity b/Assets/LIN/Housing Copy.unity index 7c1098ee..cf259123 100644 --- a/Assets/LIN/Housing Copy.unity +++ b/Assets/LIN/Housing Copy.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:755350a1d82168eb856b35a68d3c8a4b6fdd9630582d73deee588582866e05c8 -size 137425 +oid sha256:8f764336a02a303a122209f43a83c7d017262b0f322f2024075f668031752b57 +size 161697 diff --git a/Assets/LIN/HousingCanvasController.cs b/Assets/LIN/HousingCanvasController.cs index ec3eb64e..ef0baf3c 100644 --- a/Assets/LIN/HousingCanvasController.cs +++ b/Assets/LIN/HousingCanvasController.cs @@ -6,19 +6,26 @@ using UnityEngine; public class HousingCanvasController : MonoBehaviour { + [Header("일상행동 상호작용")] [SerializeField] GameObject interactionButton; [SerializeField] TMP_Text actionText; [SerializeField] TMP_Text descriptionText; - - public Action OnInteractionButtonPressed; + [Header("돌발 이벤트")] + [SerializeField] private GameObject suddenPanel; + [SerializeField] private TMP_Text suddenText; + + public Action OnInteractionButtonPressed; + public Action OnSuddenButtonPressed; void Awake() { - InitTexts(); + InitInteractionTexts(); interactionButton.SetActive(false); + suddenPanel.SetActive(false); } + #region 상호작용 일상 행동 //사물 이름 세팅 public void SetActionText(string text = "") { @@ -30,7 +37,7 @@ public class HousingCanvasController : MonoBehaviour descriptionText.text = text; } - private void InitTexts() + private void InitInteractionTexts() { SetActionText(); SetDescriptionText(); @@ -46,7 +53,6 @@ public class HousingCanvasController : MonoBehaviour //각 행동 별로 실행되어야 할 이벤트 구독 OnInteractionButtonPressed = onInteractionButtonPressed; } - //범위에서 벗어나면 상호작용 버튼 off public void HideInteractionButton() { @@ -62,5 +68,27 @@ public class HousingCanvasController : MonoBehaviour public void OnClickInteractionButton() { OnInteractionButtonPressed?.Invoke(); + HideInteractionButton(); } + #endregion + + #region 돌발 이벤트 + public void ShowSuddenEventPanel(string actText, Action onSuddenButtonPressed) + { + suddenPanel.SetActive(true); + suddenText.text = actText; + OnSuddenButtonPressed += onSuddenButtonPressed; + } + public void HideSuddenEventPanel() + { + suddenPanel.SetActive(false); + suddenText.text = ""; + OnSuddenButtonPressed = null; + } + public void OnSuddenConfirmButton() + { + OnSuddenButtonPressed?.Invoke(); + } + #endregion + } diff --git a/Assets/LIN/HousingConstants.cs b/Assets/LIN/HousingConstants.cs new file mode 100644 index 00000000..ee2e457b --- /dev/null +++ b/Assets/LIN/HousingConstants.cs @@ -0,0 +1,43 @@ +//퇴근 후 발생할 수 있는 돌발 이벤트 + +using System.Collections.Generic; + +public enum AfterWorkEvent +{ + None, + TeamGathering, + OvertimeWork +} + +public static class HousingConstants +{ + //돌발 이벤트 확률 계산 + public static int AFTER_WORK_DENOMINATOR = 4; + + + #region 상호작용 멘트 + + public static readonly Dictionary interactions = + new Dictionary + { + { ActionType.Sleep, new InteractionTexts("침대에서 잘까?","숙면으로 시간 당 체력 1을 회복한다.", ".")}, + { ActionType.Housework, new InteractionTexts("밀린 집안일을 처리할까?","체력 1을 사용하고 좋은일이 일어날지도 모른다","힘들어서 못해..")}, + { ActionType.Dungeon, new InteractionTexts("던전에 입장할까?","체력 3을 사용하고 3시간이 흐른다.","던전에 갈 체력이 되지 않아..")}, + { ActionType.Work, new InteractionTexts("출근한다.","체력 3을 사용하고 저녁 6시에나 돌아오겠지..", "도저히 출근할 체력이 안되는걸..?")} + }; + #endregion + + public struct InteractionTexts + { + public string ActionText { get; private set; } + public string DescriptionText { get; private set; } + public string LackOfHealth { get; private set; } + + public InteractionTexts(string actionText, string descriptionText, string lackOfHealth) + { + ActionText = actionText; + DescriptionText = descriptionText; + LackOfHealth = lackOfHealth; + } + } +} diff --git a/Assets/LIN/HousingConstants.cs.meta b/Assets/LIN/HousingConstants.cs.meta new file mode 100644 index 00000000..00a41565 --- /dev/null +++ b/Assets/LIN/HousingConstants.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b0ce52df52334b1eaf37479fdda66f7a +timeCreated: 1745303266 \ No newline at end of file diff --git a/Assets/LIN/SuddenEventController.cs b/Assets/LIN/SuddenEventController.cs new file mode 100644 index 00000000..f334803b --- /dev/null +++ b/Assets/LIN/SuddenEventController.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using Random = UnityEngine.Random; + +public class SuddenEventController +{ + // 랜덤 값에 일치하는 함수를 리턴하기 위한 딕셔너리 + // AFTER_WORK_DENOMINATOR 값 확정 후에 키 값 수정 + private Dictionary afterWorkEvents = new Dictionary(); + public SuddenEventController() + { + afterWorkEvents.Add(0, AfterWorkEvent.OvertimeWork); + afterWorkEvents.Add(1, AfterWorkEvent.TeamGathering); + } + + //퇴근 후 돌발 이벤트 + public AfterWorkEvent SuddenEventCalculator() + { + var index = Random.Range(0,HousingConstants.AFTER_WORK_DENOMINATOR); + return afterWorkEvents.GetValueOrDefault(index, AfterWorkEvent.None); + } + +} diff --git a/Assets/LIN/SuddenEventController.cs.meta b/Assets/LIN/SuddenEventController.cs.meta new file mode 100644 index 00000000..9645366a --- /dev/null +++ b/Assets/LIN/SuddenEventController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 26ce8577425c4630903173b182839514 +timeCreated: 1745306651 \ No newline at end of file diff --git a/Assets/Resources/Player/Weapon/Chopstick.prefab b/Assets/Resources/Player/Weapon/Chopstick.prefab index 810dcc1c..25756e01 100644 --- a/Assets/Resources/Player/Weapon/Chopstick.prefab +++ b/Assets/Resources/Player/Weapon/Chopstick.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d539e2dc365e5f928744e7478a1785defad00891355f53d0f9a5fa87940fa13d -size 7199 +oid sha256:e0b9376d541c7a230686b60c2aa94246dcb4ea06e36fdec6b6692d89a8ea11f9 +size 7184 diff --git a/Assets/Scenes/Housing.meta b/Assets/Scenes/Housing.meta new file mode 100644 index 00000000..4f9b62ea --- /dev/null +++ b/Assets/Scenes/Housing.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57342d13612d4a240981df8a13a16c12 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Housing.unity b/Assets/Scenes/Housing.unity index ce147068..9a2628e7 100644 --- a/Assets/Scenes/Housing.unity +++ b/Assets/Scenes/Housing.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:56c7c829ffd91cd42fa0653c05b5e81708b30f5b364c2fc5570f4a0c3fb810d2 -size 100544 +oid sha256:208ecb0c73a3316229232d356a4ae82d1a70e3418e187edc7073d67c6b27699c +size 253 diff --git a/Assets/Scenes/Housing/LightingData.asset b/Assets/Scenes/Housing/LightingData.asset new file mode 100644 index 00000000..860488c5 Binary files /dev/null and b/Assets/Scenes/Housing/LightingData.asset differ diff --git a/Assets/Scenes/Housing/LightingData.asset.meta b/Assets/Scenes/Housing/LightingData.asset.meta new file mode 100644 index 00000000..84a0b77c --- /dev/null +++ b/Assets/Scenes/Housing/LightingData.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10550dbcfa71e3e4cb0e91a0bb7a19f0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 112000000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Housing/Lightmap-0_comp_dir.png b/Assets/Scenes/Housing/Lightmap-0_comp_dir.png new file mode 100644 index 00000000..75272086 --- /dev/null +++ b/Assets/Scenes/Housing/Lightmap-0_comp_dir.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8f501336a0ae5032dba5c467df07c68448319d3c2062d3f48a85149d56a860a +size 364518 diff --git a/Assets/Scenes/Housing/Lightmap-0_comp_dir.png.meta b/Assets/Scenes/Housing/Lightmap-0_comp_dir.png.meta new file mode 100644 index 00000000..d22fe1ed --- /dev/null +++ b/Assets/Scenes/Housing/Lightmap-0_comp_dir.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: e30dc677714519945b30e7215332fd38 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 1 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 3 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 12 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Housing/Lightmap-0_comp_light.exr b/Assets/Scenes/Housing/Lightmap-0_comp_light.exr new file mode 100644 index 00000000..7927e59c Binary files /dev/null and b/Assets/Scenes/Housing/Lightmap-0_comp_light.exr differ diff --git a/Assets/Scenes/Housing/Lightmap-0_comp_light.exr.meta b/Assets/Scenes/Housing/Lightmap-0_comp_light.exr.meta new file mode 100644 index 00000000..fd024133 --- /dev/null +++ b/Assets/Scenes/Housing/Lightmap-0_comp_light.exr.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 2ff23c25ba734b9468d6f3bb8a24be15 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 1 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 3 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 6 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Housing/Lightmap-0_comp_shadowmask.png b/Assets/Scenes/Housing/Lightmap-0_comp_shadowmask.png new file mode 100644 index 00000000..c1bf67f2 --- /dev/null +++ b/Assets/Scenes/Housing/Lightmap-0_comp_shadowmask.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3019abbbe7223d2e4edb750f173efad2b232fb1b57166615e914192505cc8f28 +size 34799 diff --git a/Assets/Scenes/Housing/Lightmap-0_comp_shadowmask.png.meta b/Assets/Scenes/Housing/Lightmap-0_comp_shadowmask.png.meta new file mode 100644 index 00000000..cf086e7c --- /dev/null +++ b/Assets/Scenes/Housing/Lightmap-0_comp_shadowmask.png.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 66363697428821b4eaa87bdcb2da8ff1 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 1 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 3 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 11 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 2 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/Housing/ReflectionProbe-0.exr b/Assets/Scenes/Housing/ReflectionProbe-0.exr new file mode 100644 index 00000000..342037e2 Binary files /dev/null and b/Assets/Scenes/Housing/ReflectionProbe-0.exr differ diff --git a/Assets/Scenes/Housing/ReflectionProbe-0.exr.meta b/Assets/Scenes/Housing/ReflectionProbe-0.exr.meta new file mode 100644 index 00000000..96bb2fe5 --- /dev/null +++ b/Assets/Scenes/Housing/ReflectionProbe-0.exr.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 643882fa4c2925347bd364c2285322af +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 1 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 100 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Character/CharacterBase.cs b/Assets/Scripts/Character/CharacterBase.cs index 9bfa4132..4a35b463 100644 --- a/Assets/Scripts/Character/CharacterBase.cs +++ b/Assets/Scripts/Character/CharacterBase.cs @@ -16,6 +16,8 @@ public abstract class CharacterBase : MonoBehaviour [Header("상태 이상")] public List statusEffects = new List(); + + public event System.Action OnDeath; // 사망 이벤트 protected virtual void Start() { @@ -38,6 +40,7 @@ public abstract class CharacterBase : MonoBehaviour { Debug.Log($"{characterName}이 사망했습니다."); // TODO: 사망 처리 + OnDeath?.Invoke(this); } // 상태이상 추가 메서드 diff --git a/Assets/Scripts/Character/Enemy/BossPattern.meta b/Assets/Scripts/Character/Enemy/BossPattern.meta new file mode 100644 index 00000000..e375e2dd --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d3b800a343fe42afa7494329ef235461 +timeCreated: 1745300808 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs new file mode 100644 index 00000000..61aef323 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections; +using UnityEngine; + + +[Serializable] +public struct DamageEffectData +{ + public int damage; + public float radius; + public float delay; + public LayerMask targetLayer; + public GameObject explosionEffectPrefab; +} + +/// +/// AOE 범위 공격의 공통 로직을 처리하는 추상 베이스 클래스입니다. +/// +public abstract class AoeControllerBase : MonoBehaviour +{ + [Header("경고 이펙트")] + [SerializeField] protected GameObject warningEffectInstance; + + protected DamageEffectData _data; + private Action _slashAction; + private Action _destroyAction; + + /// + /// 범위 공격 이펙트를 설정하고, 딜레이 후 폭발을 실행합니다. + /// + public void SetEffect(DamageEffectData data, Action slashAction, Action destroyAction) + { + _data = data; + _slashAction = slashAction; + _destroyAction = destroyAction; + + ShowWarningEffect(); + StartCoroutine(ExplodeAfterDelay()); + } + + protected virtual void ShowWarningEffect() + { + if (warningEffectInstance != null) + warningEffectInstance.SetActive(true); + + float diameter = _data.radius * 2f; + transform.localScale = new Vector3(diameter, 1f, diameter); + } + + private IEnumerator ExplodeAfterDelay() + { + yield return new WaitForSeconds(_data.delay); + Explode(); + } + + /// + /// 폭발 이펙트 생성, 데미지 처리, 콜백 호출 순서로 실행합니다. + /// + protected virtual void Explode() + { + // 경고 이펙트 숨기기 + if (warningEffectInstance != null) + warningEffectInstance.SetActive(false); + + ShowDamageEffect(); + + // 슬래시 액션(애니메이션 트리거) 호출 + _slashAction?.Invoke(); + + // 범위 내 데미지 처리 + HitCheck(); + + // 패턴 클리어 콜백 + _destroyAction?.Invoke(); + + // 자기 자신 제거 + Destroy(gameObject, 2f); + } + + protected virtual void HitCheck() + { + var hits = Physics.OverlapSphere(transform.position, _data.radius, _data.targetLayer); + foreach (var hit in hits) + { + if (hit.CompareTag("Player")) + { + Debug.Log($"{hit.name}에게 {_data.damage} 데미지 적용"); + // TODO: 실제 데미지 처리 로직 호출 + // 임시 데이미 처리 로직 + PlayerController playerController = hit.transform.GetComponent(); + if (playerController != null) + { + playerController.TakeDamage(_data.damage); + } + } + } + } + + protected virtual void ShowDamageEffect() + { + // 폭발 이펙트 생성 + if (_data.explosionEffectPrefab != null) + { + var effect = Instantiate(_data.explosionEffectPrefab, transform.position, transform.rotation); + effect.transform.localScale = new Vector3(_data.radius, _data.radius, _data.radius); + Destroy(effect, 2f); + } + } + + protected virtual void OnDrawGizmosSelected() + { + Gizmos.color = Color.red; + Gizmos.DrawWireSphere(transform.position, _data.radius); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs.meta new file mode 100644 index 00000000..532cedaa --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1dd40dca214a4038be21f64ce645e5d9 +timeCreated: 1745393630 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs new file mode 100644 index 00000000..560b885d --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs @@ -0,0 +1,4 @@ +public class BoomAoeController : AoeControllerBase +{ + +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs.meta new file mode 100644 index 00000000..8bf641f6 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e32c2002701d49df83faa36b3da55436 +timeCreated: 1745395178 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs new file mode 100644 index 00000000..e658d92a --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections; +using UnityEngine; + + + +public class ChariotAoeController : AoeControllerBase +{ + protected override void ShowDamageEffect() + { + // 폭발 이펙트 생성 + if (_data.explosionEffectPrefab != null) + { + var effect = Instantiate(_data.explosionEffectPrefab, transform.position, transform.rotation); + effect.transform.localScale = new Vector3(2f, 2f, 2f); + Destroy(effect, 2f); + } + } +} diff --git a/Assets/Scripts/Character/Enemy/EnemyAttackController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs.meta similarity index 100% rename from Assets/Scripts/Character/Enemy/EnemyAttackController.cs.meta rename to Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs.meta diff --git a/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs new file mode 100644 index 00000000..0ec4a415 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs @@ -0,0 +1,58 @@ +using UnityEngine; + +public class HorizontalAoeController : AoeControllerBase +{ + private float slashAngle = 270f; + private int gizmoSegments = 20; + protected override void HitCheck() + { + var hits = Physics.OverlapSphere(transform.position, _data.radius, _data.targetLayer); + foreach (var hit in hits) + { + if (!hit.CompareTag("Player")) continue; + + Vector3 dir = hit.transform.position - transform.position; + dir.y = 0; + float angleToForward = Vector3.Angle(transform.forward, dir); + + if (angleToForward <= slashAngle * 0.5f) + { + Debug.Log($"{hit.name}이(가) 횡적 슬래시 데미지 범위에 있습니다."); + Debug.Log($"{hit.name}에게 {_data.damage} 데미지 적용"); + // TODO: 실제 데미지 처리 로직 호출 + // 임시 데이미 처리 로직 + PlayerController playerController = hit.transform.GetComponent(); + if (playerController != null) + { + playerController.TakeDamage(_data.damage); + } + } + } + } + + private void OnDrawGizmosSelected() + { + // 부채꼴 형태 기즈모 드로잉 + Gizmos.color = Color.red; + Vector3 origin = transform.position; + float halfAngle = slashAngle * 0.5f; + float step = slashAngle / gizmoSegments; + + // 시작 포인트 + Vector3 prevDir = Quaternion.AngleAxis(-halfAngle, Vector3.up) * transform.forward; + Vector3 prevPoint = origin + prevDir.normalized * _data.radius; + Gizmos.DrawLine(origin, prevPoint); + + for (int i = 1; i <= gizmoSegments; i++) + { + float currentAngle = -halfAngle + step * i; + Vector3 currDir = Quaternion.AngleAxis(currentAngle, Vector3.up) * transform.forward; + Vector3 currPoint = origin + currDir.normalized * _data.radius; + Gizmos.DrawLine(prevPoint, currPoint); + prevPoint = currPoint; + } + + // 마지막 라인 + Gizmos.DrawLine(origin, prevPoint); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs.meta new file mode 100644 index 00000000..0fc4ea79 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e77da766410d47f9a7effebd30fd33f6 +timeCreated: 1745394588 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs new file mode 100644 index 00000000..4126f60f --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +public class VerticalAoeController : AoeControllerBase +{ + + protected override void ShowWarningEffect() + { + if (warningEffectInstance != null) + warningEffectInstance.SetActive(true); + + var centerCap = Vector3.forward * _data.radius; + float diameter = _data.radius * 2f; + transform.localScale = new Vector3(_data.radius, 1f, diameter); + transform.Translate(centerCap, Space.Self); + } + + protected override void ShowDamageEffect() + { + // 폭발 이펙트 생성 + if (_data.explosionEffectPrefab != null) + { + var effect = Instantiate(_data.explosionEffectPrefab, transform.position, transform.rotation); + effect.transform.localScale = new Vector3(_data.radius, _data.radius, _data.radius); + Destroy(effect, 2f); + } + } + + protected override void HitCheck() + { + // 박스 판정 (사각형 직선) + Vector3 halfExtents = new Vector3(_data.radius, 1f, _data.radius * 2f); + Collider[] hits = Physics.OverlapBox(transform.position, halfExtents, transform.rotation, _data.targetLayer); + + foreach (var hit in hits) + { + if (!hit.CompareTag("Player")) continue; + Debug.Log($"{hit.name} 사각형 범위에 있어 데미지 적용"); + // TODO: 데미지 로직 + // 임시 데이미 처리 로직 + PlayerController playerController = hit.transform.GetComponent(); + if (playerController != null) + { + playerController.TakeDamage(_data.damage); + } + } + } + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.red; + Vector3 center = transform.position; + Vector3 size = new Vector3(_data.radius, 1f, _data.radius * 2f); + Gizmos.matrix = Matrix4x4.TRS(center, transform.rotation, Vector3.one); + Gizmos.DrawWireCube(Vector3.zero, size); + Gizmos.matrix = Matrix4x4.identity; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs.meta new file mode 100644 index 00000000..9fe09225 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8eb40ee5f0d943469026d2b6522dbe46 +timeCreated: 1745393484 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs b/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs deleted file mode 100644 index 91bdc4a1..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class EnemyAnimatorStateAttack : StateMachineBehaviour -{ - // OnStateExit is called when a transition ends and the state machine finishes evaluating this state - // override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) - // { - // animator.gameObject.GetComponent().SetState(EnemyState.Trace); - // } - - -} diff --git a/Assets/Scripts/Character/Enemy/EnemyAttackController.cs b/Assets/Scripts/Character/Enemy/EnemyAttackController.cs deleted file mode 100644 index 543db2f9..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyAttackController.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -public class EnemyAttackController : MonoBehaviour -{ - [Header("각종 전조 오브젝트")] - [SerializeField] private GameObject verticalWarningArea; - [SerializeField] private GameObject horizontalWarningArea; - [SerializeField] private GameObject chariotWarningArea; - [SerializeField] private GameObject dynamoWarningArea; - - // 배열에 담아서 관리 - private List warningAreas; - private GameObject _activeArea; - - private void Awake() - { - warningAreas = new List() - { - verticalWarningArea, - horizontalWarningArea, - chariotWarningArea, - dynamoWarningArea - }; - } - - // 랜덤 전조 호출 - public void TriggerRandomWarning(Vector3 spawnPosition, Quaternion spawnRotation) - { - // 0 ~ Count-1 사이 랜덤 인덱스 - int idx = Random.Range(0, warningAreas.Count); - GameObject selected = warningAreas[idx]; - - // 예시: Instantiate 방식으로 화면에 띄우기 - _activeArea = Instantiate(selected, spawnPosition, spawnRotation); - } - - public void DestroyWarningArea() - { - Destroy(_activeArea); - } -} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyController.cs b/Assets/Scripts/Character/Enemy/EnemyController.cs index 58534e20..07f72e13 100644 --- a/Assets/Scripts/Character/Enemy/EnemyController.cs +++ b/Assets/Scripts/Character/Enemy/EnemyController.cs @@ -2,49 +2,46 @@ using UnityEngine; using UnityEngine.AI; -public enum EnemyState { None, Idle, Trace, Attack, GetHit, Move, Dead } +public enum EnemyState { None, Idle, Trace, Attack, Dead } [RequireComponent(typeof(NavMeshAgent))] [RequireComponent(typeof(Animator))] -[RequireComponent(typeof(EnemyAttackController))] public abstract class EnemyController : CharacterBase { [Header("AI")] [SerializeField] private float detectCircleRadius = 10f; // 플레이어 탐지 범위 [SerializeField] private LayerMask targetLayerMask; // 플레이어 레이어 마스크 + public Transform TraceTargetTransform { get; private set; } public NavMeshAgent Agent { get; private set; } public Animator EnemyAnimator { get; private set; } - public EnemyState CurrentState {get; private set;} + public LayerMask TargetLayerMask => targetLayerMask; + public float MoveSpeed => moveSpeed; + public bool IsMeleeCombat { get; protected set; } - public EnemyAttackController EnemyAttackController { get; private set; } - - public float WalkSpeed => walkSpeed; - public float RunSpeed => runSpeed; - - public Transform TraceTargetTransform { get; private set; } - - [SerializeField] private float walkSpeed = 5; - [SerializeField] private float runSpeed = 8; + // ----- + // 애니메이션 관련 + private int _currentAnimationTrigger = -1; + // 애니메이션 파라미터 해시값 + public static readonly int Idle = Animator.StringToHash("Idle"); + public static readonly int Dead = Animator.StringToHash("Dead"); + public static readonly int Trace = Animator.StringToHash("Trace"); // ----- // 상태 변수 private EnemyStateIdle _enemyStateIdle; private EnemyStateTrace _enemyStateTrace; private EnemyStateAttack _enemyStateAttack; - private EnemyStateGetHit _enemyStateGetHit; private EnemyStateDead _enemyStateDead; - private EnemyStateMove _enemyStateMove; private Dictionary _enemyStates; - private void Awake() + protected virtual void Awake() { EnemyAnimator = GetComponent(); Agent = GetComponent(); - EnemyAttackController = GetComponent(); } protected override void Start() @@ -55,24 +52,20 @@ public abstract class EnemyController : CharacterBase _enemyStateIdle = new EnemyStateIdle(); _enemyStateTrace = new EnemyStateTrace(); _enemyStateAttack = new EnemyStateAttack(); - _enemyStateGetHit = new EnemyStateGetHit(); _enemyStateDead = new EnemyStateDead(); - _enemyStateMove = new EnemyStateMove(); _enemyStates = new Dictionary { { EnemyState.Idle, _enemyStateIdle }, { EnemyState.Trace, _enemyStateTrace }, { EnemyState.Attack, _enemyStateAttack }, - { EnemyState.GetHit, _enemyStateGetHit }, { EnemyState.Dead, _enemyStateDead }, - { EnemyState.Move, _enemyStateMove} }; SetState(EnemyState.Idle); } - private void Update() + protected virtual void Update() { if (CurrentState != EnemyState.None) { @@ -90,6 +83,14 @@ public abstract class EnemyController : CharacterBase _enemyStates[CurrentState].Enter(this); } + + public override void Die() + { + base.Die(); + // TODO : 사망 후 동작 + SetState(EnemyState.Dead); + } + #region 적 탐지 // 일정 반경에 플레이어가 진입하면 플레이어 소리를 감지했다고 판단 @@ -107,5 +108,38 @@ public abstract class EnemyController : CharacterBase #endregion + #region 애니메이션 제어 + + // Trigger + public void SetAnimation(int hashName) + { + if (_currentAnimationTrigger != -1) + { + EnemyAnimator.ResetTrigger(_currentAnimationTrigger); + } + + EnemyAnimator.SetTrigger(hashName); + _currentAnimationTrigger = hashName; + } + + // Bool + public void SetAnimation(int hashName, bool value) + { + EnemyAnimator.SetBool(hashName, value); + } + + // Float + public void SetAnimation(int hashName, float value) + { + EnemyAnimator.SetFloat(hashName, value); + } + + // Integer + public void SetAnimation(int hashName, int value) + { + EnemyAnimator.SetInteger(hashName, value); + } + + #endregion } diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs index 6cc865a5..194ce30c 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs @@ -4,65 +4,21 @@ using UnityEngine; public class EnemyStateAttack : IEnemyState { - private static readonly int VertiSlash = Animator.StringToHash("VertiSlash"); - private static readonly int VertiAttack = Animator.StringToHash("VertiAttack"); - private EnemyController _enemyController; - private Animator _animator; - private Coroutine _attackRoutine; - private EnemyAttackController _enemyAttackController; - private enum AttackType - { - VerticalAttack, // 위에서 아래로 베는 것 - HorizontalAttack, // 옆으로 베는 것 - ChariotAttack, // 원형 - DynamoAttack, // 도넛 - }; - private AttackType _currentAttackType; public void Enter(EnemyController enemyController) { _enemyController = enemyController; - _animator = _enemyController.EnemyAnimator; - _enemyAttackController = _enemyController.EnemyAttackController; - _animator.SetBool(VertiAttack, true); - _attackRoutine = _enemyController.StartCoroutine(VerticalAttackSequence()); } public void Update() { - } - private IEnumerator VerticalAttackSequence() - { - // 1. 전조 이펙트 생성 - _enemyAttackController.TriggerRandomWarning(_enemyController.transform.position, _enemyController.transform.rotation); - // 2. 검을 들어올림 - yield return new WaitForSeconds(3f); - - // 3. 대기(전조와 검 들어올리는 애니메이션을 위함) - - // 4. 검 휘두르기 - _animator.SetTrigger(VertiSlash); - _enemyAttackController.DestroyWarningArea(); - // TODO : 5. 공격 판정 발생 - - yield return new WaitForSeconds(1f); - // 6. 애니메이션 트리거 종료 -> 애니메이터 상태 머신으로 처리 - _enemyController.SetState(EnemyState.Trace); } public void Exit() { - if (_attackRoutine != null) - { - _enemyController.StopCoroutine(_attackRoutine); - _attackRoutine = null; - } - _animator.SetBool(VertiAttack, false); - _animator = null; - _enemyAttackController = null; _enemyController = null; } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs index 158b9eab..ba34bb17 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs @@ -5,7 +5,7 @@ public void Enter(EnemyController enemyController) { _enemyController = enemyController; - _enemyController.EnemyAnimator.SetTrigger("Dead"); + _enemyController.SetAnimation(EnemyController.Dead); } public void Update() diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs deleted file mode 100644 index b4c44e8a..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs +++ /dev/null @@ -1,19 +0,0 @@ -public class EnemyStateGetHit: IEnemyState -{ - private EnemyController _enemyController; - - public void Enter(EnemyController enemyController) - { - _enemyController = enemyController; - } - - public void Update() - { - - } - - public void Exit() - { - _enemyController = null; - } -} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs.meta b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs.meta deleted file mode 100644 index e0212137..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 7067b1b0eacf490c863a4cb68c290d3a -timeCreated: 1744799049 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs index b8714ef6..a0fbbc52 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs @@ -2,13 +2,14 @@ public class EnemyStateIdle: IEnemyState { - private static readonly int Idle = Animator.StringToHash("Idle"); + private EnemyController _enemyController; public void Enter(EnemyController enemyController) { _enemyController = enemyController; - _enemyController.EnemyAnimator.SetBool(Idle, true); + Debug.Log("## Idle 상태 진입"); + _enemyController.SetAnimation(EnemyController.Idle, true); } public void Update() @@ -22,7 +23,7 @@ public class EnemyStateIdle: IEnemyState public void Exit() { - _enemyController.EnemyAnimator.SetBool(Idle, false); + _enemyController.SetAnimation(EnemyController.Idle, false); _enemyController = null; } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs deleted file mode 100644 index e68bdcd3..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs +++ /dev/null @@ -1,19 +0,0 @@ -public class EnemyStateMove : IEnemyState -{ - private EnemyController _enemyController; - - public void Enter(EnemyController enemyController) - { - _enemyController = enemyController; - } - - public void Update() - { - - } - - public void Exit() - { - _enemyController = null; - } -} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs.meta b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs.meta deleted file mode 100644 index 05ec512c..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 5abb29c9137942fe95bc66670d8ef521 -timeCreated: 1744799142 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs index ae814987..b301d19a 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs @@ -2,9 +2,6 @@ public class EnemyStateTrace : IEnemyState { - private static readonly int MoveSpeed = Animator.StringToHash("MoveSpeed"); - private static readonly int Trace = Animator.StringToHash("Trace"); - private EnemyController _enemyController; private Transform _detectPlayerTransform; @@ -14,7 +11,7 @@ public class EnemyStateTrace : IEnemyState public void Enter(EnemyController enemyController) { _enemyController = enemyController; - + Debug.Log("## Trace 상태 진입"); _detectPlayerTransform = _enemyController.TraceTargetTransform; if (!_detectPlayerTransform) { @@ -28,24 +25,31 @@ public class EnemyStateTrace : IEnemyState _enemyController.Agent.SetDestination(_detectPlayerTransform.position); } - _enemyController.EnemyAnimator.SetBool(Trace, true); + _enemyController.SetAnimation(EnemyController.Trace, true); } public void Update() { - // 일정 주기로 찾은 플레이어의 위치를 갱신해서 갱신된 위치로 이동 - FindTargetPosition(); + if(_enemyController.IsMeleeCombat) return; + if (_enemyController.Agent.enabled != true) return; PlayerTracking(); if (_enemyController.Agent.remainingDistance <= _enemyController.Agent.stoppingDistance) { // TODO: 타겟에 도착함 -> 공격 준비 - _enemyController.SetState(EnemyState.Attack); + // _enemyController.SetState(EnemyState.Attack); } - } + public void Exit() + { + _detectPlayerTransform = null; + _enemyController.SetAnimation(EnemyController.Trace, false); + _enemyController = null; + } + + // 일정 주기로 찾은 플레이어의 위치를 갱신해서 갱신된 위치로 이동 private void FindTargetPosition() { if (_detectPlayerInCircleWaitTime > MaxDetectPlayerInCircleWaitTime) @@ -67,26 +71,16 @@ public class EnemyStateTrace : IEnemyState // 플레이어를 추적하는 속도를 제어하는 함수 private void PlayerTracking() { + FindTargetPosition(); + float distance = (_detectPlayerTransform.position - _enemyController.transform.position).magnitude; - if (distance > 5f) - { - // 먼 거리: 뛰기 - _enemyController.Agent.speed = _enemyController.RunSpeed; - _enemyController.Agent.acceleration = 20f; - _enemyController.Agent.angularSpeed = 270f; - // _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 1f); // 애니메이션도 Run으로 - - // NavMeshAgent 회전에 맡기기 - _enemyController.Agent.updateRotation = true; - } - else if (distance > 2f) + if (distance > 2f) { // 가까운 거리: 걷기 - _enemyController.Agent.speed = _enemyController.WalkSpeed; + _enemyController.Agent.speed = _enemyController.MoveSpeed; _enemyController.Agent.acceleration = 8f; _enemyController.Agent.angularSpeed = 720f; - // _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 0.4f); // Walk 애니메이션 _enemyController.Agent.updateRotation = true; } @@ -107,23 +101,7 @@ public class EnemyStateTrace : IEnemyState Time.deltaTime * 10f // 회전 속도 ); } - - // _enemyController.Agent.angularSpeed = 1080f; - // _enemyController.Agent.acceleration = 999f; - - // _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 0f); } - - // 실제 속도 기반으로 애니메이션 제어 - float currentSpeed = _enemyController.Agent.velocity.magnitude; - _enemyController.EnemyAnimator.SetFloat(MoveSpeed, currentSpeed); - } - - public void Exit() - { - _detectPlayerTransform = null; - _enemyController.EnemyAnimator.SetBool(Trace, false); - _enemyController = null; } } diff --git a/Assets/Scripts/Character/Enemy/PldDogController.cs b/Assets/Scripts/Character/Enemy/PldDogController.cs index 1a9eb28d..2655b9e8 100644 --- a/Assets/Scripts/Character/Enemy/PldDogController.cs +++ b/Assets/Scripts/Character/Enemy/PldDogController.cs @@ -1,7 +1,208 @@ using System; +using System.Collections; +using System.Collections.Generic; +using Unity.VisualScripting; using UnityEngine; +using UnityEngine.Serialization; +using Random = UnityEngine.Random; public class PldDogController : EnemyController { + private static readonly int WindUp = Animator.StringToHash("WindUp"); + private static readonly int Slash = Animator.StringToHash("Slash"); + private static readonly int BoomShot = Animator.StringToHash("BoomShot"); + [Header("공격 패턴 관련")] + [SerializeField] private float patternInterval = 3f; + [SerializeField] private float meleeRange = 2f; + [SerializeField] private float bombTriggerDelay = 1.5f; + + [Header("폭탄 패턴 설정")] + [SerializeField] private int bombCount = 1; + [SerializeField] private Vector3 bombScale = new Vector3(5f, 5f, 5f); + + [Header("각종 데미지 이펙트 세트")] + [SerializeField] private GameObject chariotSlashWarning; + [SerializeField] private GameObject chariotSlash; + [SerializeField] private GameObject boomExplosion; + + [Space(10)] + [SerializeField] private GameObject verticalWarning; + [SerializeField] private GameObject verticalSlash; + + [Space(10)] + [SerializeField] private GameObject horizontalWarning; + [SerializeField] private GameObject horizontalSlash; + + private float _patternTimer = 0f; + private int _currentPatternIndex = 0; + private bool _isPatternRunning = false; + private bool _isFirstAttack = true; + + private List _patternActions; + + protected override void Awake() + { + base.Awake(); + + _patternActions = new List + { + ChariotSlashPattern, + VerticalSlashPattern, + HorizontalSlashPattern + }; + } + + protected override void Update() + { + base.Update(); + + if (CurrentState != EnemyState.Trace || _isPatternRunning) + return; + + float distanceToPlayer = Vector3.Distance(transform.position, TraceTargetTransform.position); + + if (distanceToPlayer <= meleeRange) // 근접 범위 + { + if (!Agent.isStopped) Agent.isStopped = true; + _patternTimer += Time.deltaTime; + + if (!_isPatternRunning && (_isFirstAttack || _patternTimer >= patternInterval)) + { + ExecutePattern(_currentPatternIndex); + + _isFirstAttack = false; + } + } + else + { + if (Agent.isStopped) Agent.isStopped = false; + Agent.SetDestination(TraceTargetTransform.position); + _patternTimer += Time.deltaTime; + + if (!_isPatternRunning && _patternTimer >= patternInterval) + { + BombThrowPattern(); + } + } + } + + private void ExecutePattern(int patternIndex) + { + _isPatternRunning = true; + Agent.isStopped = true; + IsMeleeCombat = true; + + _patternActions[_currentPatternIndex]?.Invoke(); + + _currentPatternIndex = (_currentPatternIndex + 1) % _patternActions.Count; // 패턴 순환 + } + + // 순환 패턴과 별개로 동작하는 특수 패턴 + private void BombThrowPattern() + { + Debug.Log("BombThrowPattern: 보스가 폭탄을 던집니다."); + SetAnimation(BoomShot); + _isPatternRunning = true; + Agent.isStopped = true; + + for (int i = 0; i < bombCount; i++) + { + Vector3 targetPos = TraceTargetTransform.position; + targetPos.y = 0.1f; // 지면에 맞춤 + + var warning = Instantiate(chariotSlashWarning, targetPos, Quaternion.identity); + warning.transform.localScale = bombScale; + var aoe = warning.GetComponent(); + + var effectData = new DamageEffectData + { + damage = (int)attackPower, + radius = bombScale.x, + delay = bombTriggerDelay, + targetLayer = TargetLayerMask, + explosionEffectPrefab = boomExplosion + }; + + aoe.SetEffect(effectData, null, PatternClear); + } + } + + private void ChariotSlashPattern() + { + Debug.Log("ChariotSlashPattern: 보스가 차지 슬래시를 사용합니다."); + WindUpAnimation(); + + var warning = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity) + .GetComponent(); + + var effectData = new DamageEffectData + { + damage = (int)attackPower, + radius = 7.5f, + delay = 2.5f, + targetLayer = TargetLayerMask, + explosionEffectPrefab = chariotSlash + }; + + warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); + } + + private void VerticalSlashPattern() + { + Debug.Log("VerticalSlashPattern: 보스가 수직 슬래시를 사용합니다."); + WindUpAnimation(); + + var warning = Instantiate(verticalWarning, transform.position, transform.rotation) + .GetComponent(); + + var effectData = new DamageEffectData + { + damage = (int)attackPower, + radius = 5f, + delay = 2f, + targetLayer = TargetLayerMask, + explosionEffectPrefab = verticalSlash + }; + + warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); + } + + private void HorizontalSlashPattern() + { + Debug.Log("HorizontalSlashPattern: 보스가 횡적 슬래시를 사용합니다."); + WindUpAnimation(); + + var warning = Instantiate(horizontalWarning, transform.position, transform.rotation) + .GetComponent(); + + var effectData = new DamageEffectData + { + damage = (int)attackPower, + radius = 15f, + delay = 2f, + targetLayer = TargetLayerMask, + explosionEffectPrefab = horizontalSlash + }; + + warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); + } + + private void WindUpAnimation() + { + SetAnimation(WindUp); + } + + private void SlashAnimationPlay() + { + SetAnimation(Slash); + } + + private void PatternClear() + { + _isPatternRunning = false; + IsMeleeCombat = false; + _patternTimer = 0f; + Agent.isStopped = false; + } } diff --git a/Assets/Scripts/Common/GameManager.cs b/Assets/Scripts/Common/GameManager.cs index a7f88c4b..6a1ef48a 100644 --- a/Assets/Scripts/Common/GameManager.cs +++ b/Assets/Scripts/Common/GameManager.cs @@ -62,7 +62,7 @@ public partial class GameManager : Singleton SceneManager.LoadScene("Game"); // 던전 Scene } - public void ChangeToMainScene() + public void ChangeToHomeScene() { SceneManager.LoadScene("Housing"); // Home Scene } diff --git a/Assets/StoreAssets/Cartoon Game Sound 2.0/s_ef_ce_mine_e.wav b/Assets/StoreAssets/Cartoon Game Sound 2.0/ShootAndBoom.wav similarity index 100% rename from Assets/StoreAssets/Cartoon Game Sound 2.0/s_ef_ce_mine_e.wav rename to Assets/StoreAssets/Cartoon Game Sound 2.0/ShootAndBoom.wav diff --git a/Assets/StoreAssets/Cartoon Game Sound 2.0/s_ef_ce_mine_e.wav.meta b/Assets/StoreAssets/Cartoon Game Sound 2.0/ShootAndBoom.wav.meta similarity index 100% rename from Assets/StoreAssets/Cartoon Game Sound 2.0/s_ef_ce_mine_e.wav.meta rename to Assets/StoreAssets/Cartoon Game Sound 2.0/ShootAndBoom.wav.meta diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index 7331c2da..6bd469f2 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -8,4 +8,7 @@ EditorBuildSettings: - enabled: 1 path: Assets/Scenes/Main.unity guid: 99c9720ab356a0642a771bea13969a05 + - enabled: 1 + path: Assets/Scenes/Housing.unity + guid: 02daaec42d605494180038d387d4a776 m_configObjects: {} diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index f877966a..9eb1b3cc 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -5,6 +5,7 @@ TagManager: serializedVersion: 2 tags: - FxTemporaire + - Enemy layers: - Default - TransparentFX @@ -16,7 +17,7 @@ TagManager: - - - - - + - Enemy - - -