This commit is contained in:
옥소명_playm 2026-02-10 17:04:33 +09:00
parent 52055cca14
commit 71fed169c9
16 changed files with 605 additions and 26 deletions

View File

@ -21938,6 +21938,51 @@ Transform:
m_CorrespondingSourceObject: {fileID: 4217812964197428, guid: b45e8c97110606643bd8998450da2825, type: 3}
m_PrefabInstance: {fileID: 198358347}
m_PrefabAsset: {fileID: 0}
--- !u!1 &198901432
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 198901434}
- component: {fileID: 198901433}
m_Layer: 0
m_Name: TesterManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &198901433
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 198901432}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8ec3ccb974842c946bcdce257d9ace12, type: 3}
m_Name:
m_EditorClassIdentifier:
testXPAmount: 10
--- !u!4 &198901434
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 198901432}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &198907952
PrefabInstance:
m_ObjectHideFlags: 0
@ -22148,6 +22193,39 @@ Transform:
m_CorrespondingSourceObject: {fileID: 4983517603246104, guid: 12135b7255e321645b821fe0ec7aa669, type: 3}
m_PrefabInstance: {fileID: 200110394}
m_PrefabAsset: {fileID: 0}
--- !u!1 &200768983
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 200768984}
m_Layer: 0
m_Name: '[Managers]'
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &200768984
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 200768983}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 216801511}
- {fileID: 449852328}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &200975691
PrefabInstance:
m_ObjectHideFlags: 0
@ -23713,12 +23791,12 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 216801509}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 50.813286, y: 24.132154, z: 9.441976}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_Father: {fileID: 200768984}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &218055051
PrefabInstance:
@ -48759,12 +48837,12 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 449852326}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 334.27826, y: 1029.2424, z: -2.218641}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_Father: {fileID: 200768984}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &449863017
PrefabInstance:
@ -186366,6 +186444,54 @@ Transform:
m_CorrespondingSourceObject: {fileID: 4390990991741872, guid: d9cd6db974fb330429b0c0aac97e153c, type: 3}
m_PrefabInstance: {fileID: 1758157735}
m_PrefabAsset: {fileID: 0}
--- !u!1 &1759137304
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1759137305}
- component: {fileID: 1759137306}
m_Layer: 0
m_Name: ObsessionManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1759137305
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1759137304}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1759137306
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1759137304}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b72410df3c1803e46ae351fb72d69c2e, type: 3}
m_Name:
m_EditorClassIdentifier:
currentXP: 0
currentLevel: 1
xpRequirements: 640000002c010000f401000020030000b0040000dc050000d0070000c4090000
currentRunXP: 0
--- !u!1001 &1759161619
PrefabInstance:
m_ObjectHideFlags: 0
@ -227230,6 +227356,10 @@ PrefabInstance:
propertyPath: m_Name
value: Player
objectReference: {fileID: 0}
- target: {fileID: 395629277865203624, guid: c34da37720b95c84887eda34e2d90e5b, type: 3}
propertyPath: baseMaxHealth
value: 5000
objectReference: {fileID: 0}
- target: {fileID: 647200136043690535, guid: c34da37720b95c84887eda34e2d90e5b, type: 3}
propertyPath: m_LocalPosition.x
value: 24.5
@ -227298,6 +227428,10 @@ PrefabInstance:
propertyPath: arrowPrefab
value:
objectReference: {fileID: 147436, guid: 640cca9678bf09a4799b1ab7c403edbc, type: 3}
- target: {fileID: 8965661853020836870, guid: c34da37720b95c84887eda34e2d90e5b, type: 3}
propertyPath: normalRange
value: 15
objectReference: {fileID: 0}
- target: {fileID: 8965661853020836870, guid: c34da37720b95c84887eda34e2d90e5b, type: 3}
propertyPath: weaponHitBox
value:
@ -227925,16 +228059,17 @@ SceneRoots:
- {fileID: 1992891316}
- {fileID: 2112919309}
- {fileID: 2119519052}
- {fileID: 449852328}
- {fileID: 7449230931284885269}
- {fileID: 832898906686813968}
- {fileID: 480236531}
- {fileID: 321682814584122314}
- {fileID: 1824697940}
- {fileID: 216801511}
- {fileID: 85056390}
- {fileID: 1175521096951328089}
- {fileID: 600231664}
- {fileID: 1927423250}
- {fileID: 2067270637}
- {fileID: 615584948}
- {fileID: 200768984}
- {fileID: 1759137305}
- {fileID: 198901434}

View File

@ -2009,7 +2009,7 @@ MonoBehaviour:
- {fileID: 0}
- {fileID: 0}
- {fileID: 0}
dropChance: 30
dropChance: 100
attackAnimations:
- ghoul_attack
Monster_Walk: ghoul_walk

View File

@ -1,14 +0,0 @@
fileFormatVersion: 2
guid: 3d7c4217783978e4abe6496ac71eee94
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 57772
packageName: Epic Toon FX
packageVersion: 1.81
assetPath: Assets/Epic Toon FX/Upgrade/ETFX URP Upgrade (2020.3.45f1).unitypackage
uploadId: 567564

View File

@ -7,13 +7,18 @@ public class PlayerHealth : MonoBehaviour, IDamageable
[Header("=== 참조 ===")]
[SerializeField] private Stats stats;
[SerializeField] private Animator animator;
[SerializeField] private PlayerAttack attackScript; // ⭐ 공격 상태 리셋을 위해 추가
[SerializeField] private PlayerAttack attackScript;
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 🔗 보스 패턴 스크립트 연결 (Inspector에서 할당)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Header("🔗 보스 패턴 연결")]
public BossPatternPhases bossPattern;
public bool IsDead { get; private set; }
public bool isHit { get; private set; }
public bool isInvincible; // 대시 중 무적 플래그
// ⭐ 기존 OnHit 이벤트와 아래 OnHit() 함수의 이름 충돌을 피하기 위해 이름을 OnHitEvent로 변경함
public event Action OnHitEvent, OnDead;
public event Action<float, float> OnHealthChanged;
@ -30,7 +35,6 @@ public class PlayerHealth : MonoBehaviour, IDamageable
Debug.Log($"<color=cyan>[UI Sync]</color> 초기 체력 설정 완료: {_currentHealth}/{stats.MaxHealth}");
}
if (animator == null) animator = GetComponent<Animator>();
// 만약 인스펙터에서 할당 안했다면 자동으로 찾아옴
if (attackScript == null) attackScript = GetComponent<PlayerAttack>();
}
@ -43,13 +47,27 @@ public class PlayerHealth : MonoBehaviour, IDamageable
}
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ⭐ 데미지를 받는 함수
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
public void TakeDamage(float amount)
{
// 무적이거나 이미 죽었으면 데미지 무시
if (isInvincible || IsDead) return;
_currentHealth = Mathf.Max(0, _currentHealth - amount);
OnHealthChanged?.Invoke(_currentHealth, stats.MaxHealth);
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 🔗 NEW: 보스 패턴 시스템에 "피격당함"을 알림
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if (bossPattern != null)
{
// BossPatternPhases 스크립트의 OnPlayerHit() 함수 호출
// 이 함수 안에서 "패턴 진행 중인지" 체크하고 XP 감점 처리
bossPattern.OnPlayerHit();
}
// ⭐ 피격 시 트리거 및 상태 리셋 함수 호출
OnHit();
@ -60,7 +78,7 @@ public class PlayerHealth : MonoBehaviour, IDamageable
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ⭐ [추가] 피격 시 공격 상태 리셋 (핵심!)
// ⭐ 피격 시 공격 상태 리셋
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
public void OnHit()
{
@ -94,12 +112,21 @@ public class PlayerHealth : MonoBehaviour, IDamageable
public void OnHitEnd() { isHit = false; }
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ⭐ 사망 처리
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
private void Die()
{
IsDead = true;
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
OnDead?.Invoke();
// ★ ★ ★ NEW: 사망 시 임시 XP를 영구 XP로 전환 ★ ★ ★
if (ObsessionSystem.instance != null)
{
ObsessionSystem.instance.OnDeathConvertXP();
}
}
public void Heal(float amount)

View File

@ -1,5 +1,6 @@
fileFormatVersion: 2
guid: 5f14e783a5ba44a45a317ffae28af4e7
guid: c10a35178a7c421419b7729f335527ce
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:

View File

@ -0,0 +1,123 @@
using UnityEngine;
public class BossPatternPhases : MonoBehaviour
{
// [Header]는 유니티 Inspector 창에서 폴더처럼 보이게 해줌
[Header("🔧 패턴 설정")]
[SerializeField] private int totalPhases = 3; // 전체 패턴 구간 수 (Inspector에서 조절 가능)
[Header("💎 XP 설정")]
[SerializeField] private int phaseClearXP = 10; // 한 구간 통과 시 주는 XP
[SerializeField] private int fullClearBonus = 30; // 모든 구간 통과 시 보너스 XP
[SerializeField] private int hitPenalty = -5; // 피격 시 감점 XP (0으로 하면 감점 없음)
// [SerializeField]는 인스펙터에서 실시간으로 볼 수 있게 해줌
[Header("🚩 상태 확인용")]
[SerializeField] private int currentPhase = 0; // 현재 진행 중인 구간 (0: 시작 전)
[SerializeField] private bool isPatternActive = false; // 패턴이 진행 중인지
[SerializeField] private bool wasHitThisPhase = false; // 이번 구간 중 피격당했는지
// ★ 초기화
private void Start()
{
ResetPattern();
}
// ★ 패턴 전체 리셋 (새로운 패턴 시작 시 호출)
public void ResetPattern()
{
currentPhase = 0;
wasHitThisPhase = false;
isPatternActive = false;
Debug.Log("[보스] 패턴 초기화 완료!");
}
// ★ 패턴 시작 (보스 AI에서 호출)
public void StartPattern()
{
if (currentPhase >= totalPhases)
{
Debug.Log("이미 모든 패턴을 완료했어요!");
return;
}
isPatternActive = true;
wasHitThisPhase = false;
Debug.Log($"🔔 [페이즈 {currentPhase + 1}] 시작! 회피하세요!");
// ★ ★ ★ 여기서 보스의 애니메이션/이펙트 시작하면 됨 ★ ★ ★
}
// ★ 플레이어가 피격당했을 때 호출 (PlayerHealth에서 연결)
public void OnPlayerHit()
{
if (!isPatternActive) return;
wasHitThisPhase = true;
Debug.Log($"💥 [페이즈 {currentPhase + 1}] 중 피격당함! (XP 감점)");
// 피격 시 감점 처리 (필요하면)
if (hitPenalty != 0 && ObsessionSystem.instance != null)
{
ObsessionSystem.instance.AddRunXP(hitPenalty);
}
}
// ★ 현재 구간을 성공적으로 통과했을 때 호출 (보스 AI에서 호출)
public void ClearCurrentPhase()
{
if (!isPatternActive) return;
// 피격당했는지 확인
if (wasHitThisPhase)
{
Debug.Log($"❌ [페이즈 {currentPhase + 1}] 실패... 다음 구간 진행");
}
else
{
// ★ 성공 시 XP 지급
if (ObsessionSystem.instance != null)
{
ObsessionSystem.instance.AddRunXP(phaseClearXP);
Debug.Log($"✅ [페이즈 {currentPhase + 1}] 성공! +{phaseClearXP}XP");
}
}
// 다음 구간으로
currentPhase++;
wasHitThisPhase = false;
// 모든 구간을 완료했는가?
if (currentPhase >= totalPhases)
{
Debug.Log("🎉 모든 패턴 완료!");
FullClearBonus();
isPatternActive = false;
}
}
// ★ 모든 구간 통과 시 보너스
private void FullClearBonus()
{
if (ObsessionSystem.instance != null)
{
ObsessionSystem.instance.AddRunXP(fullClearBonus);
Debug.Log($"🌟 전체 패턴 클리어 보너스 +{fullClearBonus}XP!");
}
}
// ★ 디버그용: 현재 상태를 콘솔에 출력
private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
Debug.Log($"[패턴 상태] 현재 구간: {currentPhase + 1}/{totalPhases}, 활성: {isPatternActive}");
}
}
// BossPatternPhases.cs에 추가
public bool IsPatternActive()
{
return isPatternActive;
}
}

View File

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

View File

@ -0,0 +1,19 @@
using UnityEngine;
public class BossRoomTrigger : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
// ★ 보스 방에 처음 들어가면 보너스 XP
if (ObsessionSystem.instance != null)
{
ObsessionSystem.instance.AddRunXP(50); // 보스 도달 보너스
Debug.Log("보스 방 도달! +50XP 보너스 획득!");
}
Destroy(this); // 한 번만 주고 제거
}
}
}

View File

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

View File

@ -0,0 +1,118 @@
using UnityEngine;
public class ObsessionSystem : MonoBehaviour
{
public static ObsessionSystem instance;
[SerializeField] private int currentXP = 0; // ★ 영구 XP (저장되는 진짜 진행도)
[SerializeField] private int currentLevel = 1;
[SerializeField] private int[] xpRequirements = { 100, 300, 500, 800, 1200 };
// ★ ★ ★ NEW: 이번 런에서 쌓은 임시 XP ★ ★ ★
[SerializeField] private int currentRunXP = 0; // 이 값은 게임 껐다 키면 사라져요!
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
LoadData();
Debug.Log($"[집착 시스템] 시작! 현재 레벨: {currentLevel}, XP: {currentXP}");
// ★ ★ ★ NEW: 새 런 시작할 때 임시 XP는 0으로 초기화 ★ ★ ★
currentRunXP = 0;
Debug.Log($"[새 런 시작] 이번 런에 쌓을 임시 XP: 0");
}
// ★ ★ ★ NEW: 플레이 중 실시간으로 임시 XP 추가 ★ ★ ★
public void AddRunXP(int amount)
{
currentRunXP += amount;
Debug.Log($"[런 XP 획득] +{amount}XP (이번 런 총: {currentRunXP})");
}
// ★ ★ ★ NEW: 사망 시 임시 XP를 영구 XP로 변환 ★ ★ ★
public void OnDeathConvertXP()
{
Debug.Log($"[사망] 이번 런 성과: {currentRunXP}XP를 영구 XP로 전환!");
// 임시 XP를 영구 XP에 추가
AddXP(currentRunXP);
// 임시 XP는 초기화 (다음 런을 위해)
currentRunXP = 0;
}
// 기존 AddXP 함수 (이제는 사망할 때만 호출될 거예요)
public void AddXP(int amount)
{
currentXP += amount;
Debug.Log($"[영구 XP 획득] +{amount}XP (현재: {currentXP})");
CheckLevelUp();
SaveData();
}
private void CheckLevelUp()
{
if (currentLevel - 1 < xpRequirements.Length)
{
int requiredXP = xpRequirements[currentLevel - 1];
if (currentXP >= requiredXP)
{
currentLevel++;
Debug.Log($"🎉 [레벨업!] 레벨 {currentLevel - 1} → {currentLevel}");
UnlockRewards(currentLevel);
}
}
}
private void UnlockRewards(int level)
{
// 보상 코드는 기존과 동일
}
private void SaveData()
{
PlayerPrefs.SetInt("ObsessionLevel", currentLevel);
PlayerPrefs.SetInt("ObsessionXP", currentXP);
PlayerPrefs.Save();
}
private void LoadData()
{
currentLevel = PlayerPrefs.GetInt("ObsessionLevel", 1);
currentXP = PlayerPrefs.GetInt("ObsessionXP", 0);
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 🧪 테스트용: 현재 상태를 읽는 함수들
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 현재 런 XP 확인
public int GetCurrentRunXP()
{
return currentRunXP;
}
// 현재 영구 XP 확인
public int GetCurrentXP()
{
return currentXP;
}
// 현재 레벨 확인
public int GetCurrentLevel()
{
return currentLevel;
}
}

View File

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

View File

@ -0,0 +1,97 @@
using UnityEngine;
public class ObsessionTester : MonoBehaviour
{
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 🧪 이 스크립트는 테스트용입니다!
// 키보드로 XP 시스템을 테스트할 수 있어요.
// 나중에 보스가 완성되면 이 스크립트는 삭제해도 됩니다.
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Header("🔧 테스트 설정")]
[SerializeField] private int testXPAmount = 10; // 테스트로 줄 XP 양
private void Start()
{
Debug.Log("========================================");
Debug.Log("🧪 [테스트 모드] 키보드 조작법:");
Debug.Log(" [1] 런 XP +10 (보스 맞추기 시뮬레이션)");
Debug.Log(" [2] 런 XP +50 (보스 도달 시뮬레이션)");
Debug.Log(" [3] 런 XP -5 (패턴 중 피격 시뮬레이션)");
Debug.Log(" [4] 사망 시뮬레이션 (XP 전환)");
Debug.Log(" [5] 현재 상태 확인");
Debug.Log(" [0] 저장 데이터 초기화 (처음부터 다시)");
Debug.Log("========================================");
}
private void Update()
{
// ObsessionSystem이 없으면 테스트 불가
if (ObsessionSystem.instance == null)
{
if (Input.anyKeyDown)
{
Debug.LogError("❌ ObsessionSystem이 씬에 없어요! GameManager 오브젝트에 추가하세요.");
}
return;
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// [1] 보스 맞추기 시뮬레이션 (+10 XP)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if (Input.GetKeyDown(KeyCode.Alpha1))
{
ObsessionSystem.instance.AddRunXP(10);
Debug.Log("🎯 [테스트] 보스 맞추기! +10 런 XP");
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// [2] 보스 도달 시뮬레이션 (+50 XP)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if (Input.GetKeyDown(KeyCode.Alpha2))
{
ObsessionSystem.instance.AddRunXP(50);
Debug.Log("🚪 [테스트] 보스 방 도달! +50 런 XP");
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// [3] 패턴 중 피격 시뮬레이션 (-5 XP)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if (Input.GetKeyDown(KeyCode.Alpha3))
{
ObsessionSystem.instance.AddRunXP(-5);
Debug.Log("💥 [테스트] 패턴 중 피격! -5 런 XP");
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// [4] 사망 시뮬레이션 (런 XP → 영구 XP 전환)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if (Input.GetKeyDown(KeyCode.Alpha4))
{
Debug.Log("💀 [테스트] 사망! 런 XP를 영구 XP로 전환...");
ObsessionSystem.instance.OnDeathConvertXP();
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// [5] 현재 상태 확인
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if (Input.GetKeyDown(KeyCode.Alpha5))
{
Debug.Log("========================================");
Debug.Log("📊 [현재 상태]");
Debug.Log($" 런 XP: {ObsessionSystem.instance.GetCurrentRunXP()}");
Debug.Log($" 영구 XP: {ObsessionSystem.instance.GetCurrentXP()}");
Debug.Log($" 레벨: {ObsessionSystem.instance.GetCurrentLevel()}");
Debug.Log("========================================");
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// [0] 저장 데이터 초기화 (처음부터 다시)
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
if (Input.GetKeyDown(KeyCode.Alpha0))
{
PlayerPrefs.DeleteAll();
Debug.Log("🗑️ [테스트] 모든 저장 데이터 삭제! 게임을 다시 시작하세요.");
}
}
}

View File

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

View File

@ -0,0 +1,14 @@
using UnityEngine;
public class RoomClear : MonoBehaviour
{
public void ClearRoom()
{
// ★ 방을 무사히 클리어하면
if (ObsessionSystem.instance != null)
{
ObsessionSystem.instance.AddRunXP(20);
Debug.Log("방 클리어! +20XP");
}
}
}

View File

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

View File

@ -9,6 +9,10 @@ public abstract class CardData : ScriptableObject
{
public Sprite icon;
// ⭐ 추가: 이 카드가 나타나기 위해 필요한 '복수의 집착' 레벨
// 기본값을 1로 설정하면 처음부터 등장합니다.
public int requiredObsessionLevel = 1;
// UI 표시용
public abstract string GetText();