๋ฐ˜์‘ํ˜•

๐Ÿš— Unity Car Survival Prototype — ๋ฐ์ดํ„ฐ·์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์ฐจ๋Ÿ‰ ์ƒ์กด ์ŠˆํŒ… ๋งŒ๋“ค๊ธฐ

์ž๋™์ฐจ์— ๋ฌด๊ธฐ๋ฅผ ์žฅ์ฐฉํ•ด ๋ชฐ๋ ค์˜ค๋Š” ์ ์„ ์ฒ˜์น˜ํ•˜๋ฉฐ ์Šคํ…Œ์ด์ง€๋ฅผ ๋ฒ„ํ‹ฐ๋Š” ํƒ‘๋‹ค์šด ํ”„๋กœํ† ํƒ€์ž…์ž…๋‹ˆ๋‹ค.
์‹ฑ๊ธ€ํ†ค ๋งค๋‹ˆ์ €, ๋ฌด๊ธฐ/์—…๊ทธ๋ ˆ์ด๋“œ, ์Šคํ…Œ์ด์ง€/์Šคํฐ, ๋ฆฌ์Šคํฐ, UI·์‚ฌ์šด๋“œ๊นŒ์ง€ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋กœ ๊ตฌํ˜„ํ–ˆ์–ด์š”.


๐Ÿงพ ๊ฐœ์š”

  • ์š”์•ฝ: ScriptableObject(WeaponData) + ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜(UI/์ƒํƒœ) + ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ†ค ๋งค๋‹ˆ์ €๋กœ ๋น ๋ฅด๊ฒŒ ๊ธฐ๋Šฅ์„ ๋ถ™์—ฌ ๋‚˜๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ.
  • ํ•ต์‹ฌ ์š”์†Œ: ์ž๋™ ์ฃผํ–‰(CarAI), ์ž๋™ ์‚ฌ๊ฒฉ(BaseWeapon), ์—…๊ทธ๋ ˆ์ด๋“œ(WeaponSlotsManager), Respawn, ์Šคํ…Œ์ด์ง€ ํƒ€์ด๋จธ/์Šคํฐ.
  • ๋Œ€์ƒ ๋…์ž: ์„œ๋ฐ”์ด๋ฒŒ๋ผ์ดํฌ/ํƒ‘๋‹ค์šด ํ”„๋กœํ† ํƒ€์ž…์„ ๋นจ๋ฆฌ ๋งŒ๋“ค๊ณ  ์‹ถ์€ ๋ถ„, ์•„ํ‚คํ…์ฒ˜ ์ฐธ๊ณ ๊ฐ€ ํ•„์š”ํ•œ ๋ถ„.

๐ŸŽฎ ๊ฒŒ์ž„ ์†Œ๊ฐœ

์ฐจ๋Ÿ‰์„ ์กฐ์ž‘(AI ์ฃผํ–‰)ํ•˜๋ฉฐ ์‹œ๊ฐ„์ด ์ง€๋‚ ์ˆ˜๋ก ๊ฐ•ํ•ด์ง€๋Š” ์ ์„ ์ƒ๋Œ€ํ•˜๋Š” ํƒ‘๋‹ค์šด ์ƒ์กด ์ŠˆํŒ…์ž…๋‹ˆ๋‹ค.
์ฒ˜์น˜ ๋ณด์ƒ์œผ๋กœ ๊ณจ๋“œ/๊ฒฝํ—˜์น˜๋ฅผ ๋ชจ์•„ ๋ฌด๊ธฐ๋ฅผ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ณ , ์œ„๊ธฐ ์ƒํ™ฉ์—์„œ๋Š” Respawn์œผ๋กœ ํŠธ๋ž™ ์œ„ ์ตœ๊ทผ์ ‘ ๋…ธ๋“œ์— ๋ณต๊ท€ํ•ด ํ๋ฆ„์„ ์ด์–ด๊ฐ‘๋‹ˆ๋‹ค.

  • ๋ชฉํ‘œ: ๊ฐ€๋Šฅํ•œ ์˜ค๋ž˜ ์ƒ์กดํ•˜๋ฉฐ Stage๋ฅผ ์˜ฌ๋ฆฌ๊ณ  ๋” ๊ฐ•ํ•œ ์›จ์ด๋ธŒ๋ฅผ ๋ฒ„ํ‹ฐ๊ธฐ
  • ๋ฃจํ”„: ์ฒ˜์น˜ ๋ณด์ƒ → ๊ณจ๋“œ/EXP → ์—…๊ทธ๋ ˆ์ด๋“œ ํŒจ๋„์—์„œ ๋ ˆ๋ฒจ์—…/ํ‹ฐ์–ด์—…

๐Ÿ–ผ๏ธ ํ”Œ๋ ˆ์ด ์˜์ƒ & GIF

 

โœจ Features

  • Generic Singleton: ClassName.Instance๋กœ ์ „์—ญ ์ ‘๊ทผ(์ค‘๋ณต ์ƒ์„ฑ ๋ฐฉ์ง€/์„  ์ƒ์„ฑ ๋ถˆํ•„์š”)
  • ๋ฌด๊ธฐ ์‹œ์Šคํ…œ(SO): WeaponData๋กœ ํ”ผํ•ด/์‚ฌ๊ฑฐ๋ฆฌ/๋ฐœ์‚ฌ ์†๋„/์ฟจํƒ€์ž„/ํ‹ฐ์–ด ์ •์˜ → BaseWeapon ๊ณตํ†ต ํŒŒ์ดํ”„๋ผ์ธ + CannonWeapon ํŒŒ์ƒ
  • ์—…๊ทธ๋ ˆ์ด๋“œ & ์Šฌ๋กฏ: WeaponSlotsManager๊ฐ€ ์Šฌ๋กฏ mount์— ๋ฌด๊ธฐ๋ฅผ ์Šคํฐ/๊ต์ฒดํ•˜๊ณ  ๋ ˆ๋ฒจ·ํ‹ฐ์–ด ์—… ๋กœ์ง ์ฒ˜๋ฆฌ, UpgradePanelController๋กœ UI ์—ฐ๋™
  • ์Šคํ…Œ์ด์ง€ & ์Šคํฐ: StageManager ํƒ€์ด๋จธ๋กœ Stage ์ƒ์Šน, EnemyManager๊ฐ€ NavMesh ์˜์—ญ์— ์  ์Šคํฐ(์ตœ๋Œ€ ์ƒ์กด ์ˆ˜ ์œ ์ง€)
  • Respawn ๋ฒ„ํŠผ: “๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํŠธ๋ž™ ๋…ธ๋“œ”๋กœ ์ฆ‰์‹œ ๋ณต๊ท€(์†๋„·์›จ์ดํฌ์ธํŠธ ๋ฆฌ์…‹)
  • UI/HUD: ์ฒด๋ ฅ/๊ฒฝํ—˜์น˜/๋ ˆ๋ฒจ, ๊ณจ๋“œ, ์†๋„(km/h), ์  ๋จธ๋ฆฌ ์œ„ HP ๋นŒ๋ณด๋“œ
  • ์‚ฌ์šด๋“œ: BGM + ํ’€๋ง ๊ธฐ๋ฐ˜ SFX + ์Šฌ๋ผ์ด๋”๋กœ ๋ณผ๋ฅจ ์ œ์–ด
  • ์„ผ์„œ & ์ด๋™ ์ œ์–ด: ์ „๋ฐฉ ์„ผ์„œ๋กœ ์ •์ง€/์žฌ๊ฐ€์†, ๋Ÿฐํƒ€์ž„ ํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹ ์ƒ˜ํ”Œ ์ œ๊ณต

๐Ÿ“ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ(์š”์•ฝ)

 
02. Scripts
โ”œโ”€ Base
โ”‚  โ”œโ”€ BaseCondition.cs
โ”‚  โ”œโ”€ BaseWeapon.cs
โ”‚  โ””โ”€ Singleton.cs
โ”œโ”€ Camera
โ”‚  โ””โ”€ FollowCamera.cs
โ”œโ”€ Controller
โ”‚  โ””โ”€ UpgradePanelController.cs
โ”œโ”€ Enemy
โ”‚  โ”œโ”€ AI
โ”‚  โ”‚  โ””โ”€ EnemyAI.cs
โ”‚  โ”œโ”€ Attack
โ”‚  โ”‚  โ”œโ”€ EnemyAttack.cs
โ”‚  โ”‚  โ””โ”€ EnemyCondition.cs
โ”‚  โ””โ”€ Interface
โ”‚     โ””โ”€ IDamageable.cs
โ”œโ”€ Manager
โ”‚  โ”œโ”€ Enemy
โ”‚  โ”‚  โ””โ”€ EnemyManager.cs
โ”‚  โ”œโ”€ Player
โ”‚  โ”‚  โ”œโ”€ PlayerManager.cs
โ”‚  โ”‚  โ””โ”€ RespawnManager.cs
โ”‚  โ”œโ”€ SkillManager.cs
โ”‚  โ”œโ”€ CurrencyManager.cs
โ”‚  โ”œโ”€ Weapon
โ”‚  โ”‚  โ””โ”€ WeaponSlotsManager.cs
โ”‚  โ”œโ”€ GameManager.cs
โ”‚  โ”œโ”€ SoundManager.cs
โ”‚  โ””โ”€ StageManager.cs
โ”œโ”€ Player
โ”‚  โ”œโ”€ Skill
โ”‚  โ”‚  โ”œโ”€ AttackController.cs (partial)
โ”‚  โ”‚  โ”œโ”€ AttackController.Heal.cs (partial)
โ”‚  โ”‚  โ””โ”€ AttackController.SpinAttack.cs (partial)
โ”‚  โ”œโ”€ CarAI.cs
โ”‚  โ””โ”€ PlayerCondition.cs
โ”œโ”€ Scriptable
โ”‚  โ””โ”€ WeaponData.cs
โ”œโ”€ UI
โ”‚  โ”œโ”€ Enemy
โ”‚  โ”‚  โ””โ”€ EnemyHealthUI.cs
โ”‚  โ”œโ”€ Player
โ”‚  โ”‚  โ”œโ”€ CarSpeedUI.cs
โ”‚  โ”‚  โ””โ”€ GoldUI.cs
โ”‚  โ””โ”€ UIConditionBinder.cs
โ”œโ”€ Util
โ”‚  โ”œโ”€ controllingCarAI.cs
โ”‚  โ””โ”€ SensorManager.cs
โ””โ”€ Weapon
   โ”œโ”€ Projectile
   โ”‚  โ””โ”€ SimpleProjectile.cs
   โ””โ”€ CannonWeapon.cs

๐Ÿงฑ ์„ค๊ณ„/๋””์ž์ธ ํŒจํ„ด

  • Singleton(์ œ๋„ค๋ฆญ): ๋งค๋‹ˆ์ € ์ „์—ญ ์ ‘๊ทผ/์ค‘๋ณต ์ƒ์„ฑ ๋ฐฉ์ง€
  • Observer(์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜): PlayerCondition ์ด๋ฒคํŠธ → UI๊ฐ€ ๊ตฌ๋…ํ•ด ์ฆ‰์‹œ ๊ฐฑ์‹ 
  • Strategy(๋ฌด๊ธฐ ํ™•์žฅ): BaseWeapon ๊ณตํ†ต ํŒŒ์ดํ”„๋ผ์ธ + ํŒŒ์ƒ ๋ฌด๊ธฐ
  • Interface(๊ฒฐํ•ฉ๋„↓): IDamageable๋กœ ํ”ผํ•ด ์ฒ˜๋ฆฌ๋ฅผ ํ†ต์ผ
  • Partial Class: AttackController๋ฅผ Spin/Heal๋กœ ๋ถ„๋ฆฌํ•ด ๊ด€์‹ฌ์‚ฌ ์ •๋ฆฌ
  • Data-Driven & Composition: ScriptableObject·์ปดํฌ๋„ŒํŠธ ์กฐํ•ฉ ์ค‘์‹ฌ ์„ค๊ณ„

๐Ÿงฐ ์‚ฌ์šฉ ๊ธฐ์ˆ  & ์‹œ์Šคํ…œ

  • NavMesh: CarAI ์›จ์ดํฌ์ธํŠธ ์Šค๋ƒ…, EnemyManager ์Šคํฐ ์ƒ˜ํ”Œ๋ง
  • WheelCollider + Rigidbody: GetWorldPose๋กœ ๋ฉ”์‹œ ๋™๊ธฐํ™”, ๋ชจํ„ฐ/๋ธŒ๋ ˆ์ดํฌ/์กฐํ–ฅ ์ œ์–ด
  • Catmull-Rom Spline: ํŠธ๋ž™ ๋…ธ๋“œ ์‚ฌ์ด ๋ถ€๋“œ๋Ÿฌ์šด ๊ฒฝ๋กœ ์ƒ์„ฑ(๋ฃจํ”„/์ƒ˜ํ”Œ ์ˆ˜ ์˜ต์…˜)
  • Physics Overlap/Trigger: Spin(OverlapSphere), ํˆฌ์‚ฌ์ฒด/๊ทผ์ ‘ ์ถฉ๋Œ → IDamageable
  • TMP + UGUI: HUD/ํŒจ๋„ ๊ตฌ์„ฑ

๐Ÿš— ํ•ต์‹ฌ ๋™์ž‘ ์š”์•ฝ

  • CarAI: trackNodes → ์Šคํ”Œ๋ผ์ธ ์›จ์ดํฌ์ธํŠธ ์ƒ์„ฑ → ๋ฐ”ํ€ด/์กฐํ–ฅ/๊ฐ€์† ๊ฐฑ์‹ , carFront ๊ธฐ์ค€ ๋„๋‹ฌ ํŒ์ •, CurrentSpeedKmh ์ œ๊ณต
  • Respawn: ํ˜„์žฌ ์œ„์น˜(๊ฐ€๋Šฅํ•˜๋ฉด carFront) ๊ธฐ์ค€ ์ตœ๊ทผ์ ‘ ๋…ธ๋“œ ํƒ์ƒ‰ → CarAI.TeleportToNode() → ์†๋„·๊ฐ์†๋„ ์ดˆ๊ธฐํ™” + ์›จ์ดํฌ์ธํŠธ ๋ฆฌ์…‹
  • ๋ฌด๊ธฐ/์—…๊ทธ๋ ˆ์ด๋“œ: ์Šฌ๋กฏ mount์— ํ”„๋ฆฌํŒน ์Šคํฐ, WeaponData๋กœ ๋ ˆ๋ฒจ์—…/ํ‹ฐ์–ด์—…, UI ๋ฐ˜์˜
  • ์Šคํ…Œ์ด์ง€/์Šคํฐ: ํƒ€์ด๋จธ๋กœ Stage ์ƒ์Šน, NavMesh ์˜์—ญ ๋‚ด ์ตœ๋Œ€ ์ƒ์กด ์ˆ˜ ์œ ์ง€
  • UI: ํ”Œ๋ ˆ์ด์–ด HUD + ์  HP ๋นŒ๋ณด๋“œ

๐Ÿ•น ํ”Œ๋ ˆ์ด ๋ฐฉ๋ฒ•

  1. ์‹œ์ž‘: ํ”Œ๋ ˆ์ดํ•˜๋ฉด StageManager๊ฐ€ ํƒ€์ด๋จธ๋ฅผ ๋Œ๋ฆฌ๋ฉฐ Stage๊ฐ€ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ƒ์Šน
  2. ์ด๋™: CarAI๊ฐ€ trackNodes๋ฅผ ๋”ฐ๋ผ ์ฃผํ–‰(๋ฃจํ”„/๋žœ๋ค/์ปค์Šคํ…€ ๊ฒฝ๋กœ). ์ „๋ฐฉ ์„ผ์„œ ์ ‘์ด‰ ์‹œ ์ผ์‹œ ์ •์ง€ ํ›„ ์žฌ์ถœ๋ฐœ
  3. ์ „ํˆฌ: WeaponSlotsManager๊ฐ€ ์Šฌ๋กฏ mount์— ๋ฌด๊ธฐ ์Šคํฐ → BaseWeapon ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ์ž๋™ ์กฐ์ค€·๋ฐœ์‚ฌ
  4. ์„ฑ์žฅ: ์ฒ˜์น˜ ๋ณด์ƒ์œผ๋กœ ๊ณจ๋“œ/EXP ํš๋“ → ์—…๊ทธ๋ ˆ์ด๋“œ ํŒจ๋„์—์„œ ๋ ˆ๋ฒจ์—…/ํ‹ฐ์–ด์—…
  5. ๋ณต๊ตฌ: ๊ธธ ์ดํƒˆ ์‹œ Respawn์œผ๋กœ ์ตœ๊ทผ์ ‘ ํŠธ๋ž™ ๋…ธ๋“œ ๋ณต๊ท€

๊ธฐ๋ณธ ํ๋ฆ„์€ AI ์ฃผํ–‰ + ์ž๋™ ์‚ฌ๊ฒฉ. ์ž…๋ ฅํ˜• ์กฐ์ž‘์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์œผ๋ฉด ๋ณ„๋„ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์‰ฝ๊ฒŒ ํ™•์žฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.


๐Ÿงช ์”ฌ ์„ธํŒ… ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • ์‹ฑ๊ธ€ํ†ค ๋งค๋‹ˆ์ € ๋ฐฐ์น˜: Game/Stage/Enemy/Sound/Currency/Skill/WeaponSlots/PlayerManager
  • ์ฐจ๋Ÿ‰: CarAI + ๋ฐ”ํ€ด(์ฝœ๋ผ์ด๋”/๋ฉ”์‹œ) + carFront ์ง€์ •, trackNodes ๋“ฑ๋ก
  • ๋ฌด๊ธฐ: WeaponData ์ƒ์„ฑ → ์Šฌ๋กฏ mount์— ์—ฐ๊ฒฐ(์‹œ์ž‘ ์‹œ ์ž๋™ ์Šคํฐ)
  • UI: ์Šฌ๋ผ์ด๋”/ํ…์ŠคํŠธ๋ฅผ ์ธ์ŠคํŽ™ํ„ฐ๋กœ ๋ฐ”์ธ๋”ฉ
  • Respawn ๋ฒ„ํŠผ: RespawnManager.RespawnToNearestTrackNode() OnClick
  • NavMesh: ์Šคํฐ ์˜์—ญ/ํŠธ๋ž™ ์ฃผ๋ณ€ ๋ฒ ์ดํฌ

๐Ÿงฏ Troubleshooting (Deep Dive)

์™œ ๋ฐœ์ƒํ–ˆ๋Š”๊ฐ€ → ์–ด๋–ป๊ฒŒ ๊ณ ์ณค๋Š”๊ฐ€ → ์žฌ๋ฐœ ๋ฐฉ์ง€๊นŒ์ง€ ์‹ค์ œ๋กœ ๊ฒช์—ˆ๋˜ ์ด์Šˆ ์ค‘์‹ฌ์œผ๋กœ ์ •๋ฆฌ.

1) ์ƒ์„ฑ์ž/ํ•„๋“œ ์ดˆ๊ธฐํ™”์—์„œ FindObjectsOfType/Singleton.Instance ํ˜ธ์ถœ

ํ˜„์ƒ
UIConditionBinder๊ฐ€ ์ƒ์„ฑ์ž/ํ•„๋“œ ์ดˆ๊ธฐํ™” ํƒ€์ด๋ฐ์— Singleton.Instance๋ฅผ ์ฐธ์กฐํ•˜๋ฉด์„œ UnityException ๋ฐœ์ƒ.

์›์ธ(Why)
MonoBehaviour๋Š” ์ƒ์„ฑ์ž/ํ•„๋“œ ์ดˆ๊ธฐํ™” ์‹œ์ ์— ์”ฌ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ค€๋น„๋˜์ง€ ์•Š์Œ. ์ด ํƒ€์ด๋ฐ์˜ FindObjectsOfType/Instance ์ ‘๊ทผ์€ ๊ธˆ๊ธฐ.

ํ•ด๊ฒฐ(How)

  • ์ฐธ์กฐ ํš๋“์€ Awake/Start, ์ด๋ฒคํŠธ ๊ตฌ๋…์€ OnEnable, ํ•ด์ œ๋Š” OnDisable.
  • ๊ฐ€๋Šฅํ•˜๋ฉด [SerializeField] ํ›„ ์ธ์ŠคํŽ™ํ„ฐ์—์„œ ์ˆ˜๋™ ๋ฐ”์ธ๋”ฉ.

์žฌ๋ฐœ ๋ฐฉ์ง€(Prevent)

  • ํŒ€ ๊ทœ์น™: “ํ•„๋“œ ์ดˆ๊ธฐํ™”/์ƒ์„ฑ์ž์—์„œ Singleton.Instance ๊ธˆ์ง€”
  • ์ฝ”๋“œ๋ฆฌ๋ทฐ ์ฒดํฌ ํ•ญ๋ชฉ์— ์ถ”๊ฐ€.

2) PlayerManager.carTransform ๋ฏธํ• ๋‹น์œผ๋กœ Respawn ๋ฒ„ํŠผ NullReference/UnassignedReference

ํ˜„์ƒ
๋ฒ„ํŠผ ํด๋ฆญ ์‹œ RespawnManager๊ฐ€ carTransform ์ ‘๊ทผํ•˜๋‹ค ์˜ˆ์™ธ.

์›์ธ

  • PlayerManager.Awake ์‹คํ–‰ ์ˆœ์„œ ์ง€์—ฐ, ๋˜๋Š” ์ธ์ŠคํŽ™ํ„ฐ ๋ฏธ๋ฐ”์ธ๋”ฉ.
  • ์”ฌ ํ™œ์„ฑ/๋น„ํ™œ์„ฑ ์ˆœ์„œ์— ๋”ฐ๋ฅธ ํƒ€์ด๋ฐ ์ด์Šˆ.

ํ•ด๊ฒฐ

  • RespawnManager.ResolveRefs(): PlayerManager → ์”ฌ ๊ฒ€์ƒ‰ → car.transform ์ˆœ์œผ๋กœ ์ž์ฒด ๋ณต๊ตฌ ๋กœ์ง ์ถ”๊ฐ€.
  • Script Execution Order๋กœ PlayerManager.Awake ์„ ํ–‰.

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ํ•ต์‹ฌ ์ฐธ์กฐ๋Š” ์ธ์ŠคํŽ™ํ„ฐ ๋ช…์‹œ ๋ฐ”์ธ๋”ฉ ์šฐ์„ .
  • ๋Ÿฐํƒ€์ž„์—์„œ๋„ ํ•œ ๋ฒˆ ๋” ๋„ ๊ฐ€๋“œ.

3) UI OnEnable์—์„œ ์ฆ‰์‹œ SFX → SoundManager NRE

ํ˜„์ƒ
UpgradePanelController.OnEnable() ๋‚ด PlaySfx() ํ˜ธ์ถœ ์‹œ NRE.

์›์ธ
์‚ฌ์šด๋“œ ํ’€/์˜ค๋””์˜ค์†Œ์Šค๊ฐ€ ์•„์ง ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ํƒ€์ด๋ฐ์— ํ˜ธ์ถœ.

ํ•ด๊ฒฐ

 
// UI ์ธก if (SoundManager.Instance && SoundManager.Instance.IsReady) SoundManager.Instance.PlaySfx(SoundManager.SfxId.Upgrade); // ๋˜๋Š” Start / WaitForEndOfFrame๋กœ ์ง€์—ฐ
  • SoundManager.Awake()์—์„œ ํ’€ ํ™•์‹คํžˆ ์ดˆ๊ธฐํ™”.

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ๊ฐ€์ด๋“œ: “UI์˜ OnEnable์—์„œ ์ฆ‰์‹œ ์˜ค๋””์˜ค ์žฌ์ƒ ๊ธˆ์ง€”
  • ์”ฌ ๋ถ€ํŒ… ์ˆœ์„œ ๋ฌธ์„œํ™”.

4) BaseCondition ๋ณดํ˜ธ๋œ ํ•„๋“œ ์ ‘๊ทผ(CS0122)

ํ˜„์ƒ
EnemyHealthUI์—์„œ BaseCondition.health/maxHealth ์ง์ ‘ ์ ‘๊ทผ ์‹œ ์ ‘๊ทผ ์ œํ•œ์ž ์—๋Ÿฌ.

์›์ธ
์บก์Аํ™” ์œ„๋ฐ˜: ์™ธ๋ถ€ UI๊ฐ€ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ์ง์ ‘ ์ฝ์œผ๋ ค ํ•จ.

ํ•ด๊ฒฐ

  • Public ํ”„๋กœํผํ‹ฐ/์ด๋ฒคํŠธ๋กœ ๋…ธ์ถœ(Health, Health01, ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ).
  • UI๋Š” ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•ด ์Šฌ๋ผ์ด๋”๋งŒ ์—…๋ฐ์ดํŠธ.

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ๊ทœ์น™: “UI๋Š” ์ด๋ฒคํŠธ/ํ”„๋กœํผํ‹ฐ๋งŒ ์‚ฌ์šฉ”.

5) ๋นŒ๋ณด๋“œ HP UI ๋–จ๋ฆผ/๋’ค์ง‘ํž˜

ํ˜„์ƒ
์นด๋ฉ”๋ผ ํšŒ์ „ ์‹œ HP ์Šฌ๋ผ์ด๋”๊ฐ€ ์ˆœ๊ฐ„์ ์œผ๋กœ ๋’ค์ง‘ํžˆ๊ฑฐ๋‚˜ ํ”๋“ค๋ฆผ.

์›์ธ
Update ์ˆœ์„œ/์ถ• ์ฒ˜๋ฆฌ ๋ฏธํก, LookAt์ด Z์ถ•๊นŒ์ง€ ๋’ค์ง‘์Œ.

ํ•ด๊ฒฐ

void LateUpdate() {
    var cam = Camera.main.transform;
    Vector3 dir = cam.position - transform.position; dir.y = 0f; // ์ˆ˜ํ‰๋งŒ
    if (dir.sqrMagnitude > 0.0001f)
        transform.rotation = Quaternion.LookRotation(dir);
}

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ์›”๋“œ ์ŠคํŽ˜์ด์Šค UI๋Š” LateUpdate์—์„œ ์œ„์น˜/๋ฐฉํ–ฅ ๊ฐฑ์‹  ๊ณ ์ •.

6) ํˆฌ์‚ฌ์ฒด ์ž„ํŒฉํŠธ ํ›„ TrailRenderer/ํŒŒํ‹ฐํด ๋ˆ„์ˆ˜

ํ˜„์ƒ
์ถฉ๋Œ ์งํ›„ ๋ณธ์ฒด ํŒŒ๊ดด ์‹œ Trail/VFX๊ฐ€ ๊ฐ™์ด ์‚ฌ๋ผ์ง€๊ฑฐ๋‚˜, ๋ฐ˜๋Œ€๋กœ ๊ณ ์•„ ์˜ค๋ธŒ์ ํŠธ๋กœ ๋‚จ์Œ.

์›์ธ
Trail์ด ๋ณธ์ฒด์— ๋ถ™์€ ์ฑ„ ํŒŒ๊ดด๋˜๊ฑฐ๋‚˜, ๋ณ„๋„ ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฏธ๊ด€๋ฆฌ.

ํ•ด๊ฒฐ

  • ์ถฉ๋Œ ์‹œ Trail์„ detach → ๋ณ„๋„ ํƒ€์ด๋จธ๋กœ ์ œ๊ฑฐ.
  • Impact VFX๋Š” ํ’€๋ง ๋˜๋Š” Destroy(go, duration)๋กœ ์ •๋ฆฌ.

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ๋ณธ์ฒด/ํŠธ๋ ˆ์ผ/์ž„ํŒฉํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด ๋ถ„๋ฆฌ ์›์น™.

7) NavMesh ์Šคํฐ ์ง€์ ์ด ๋ฒฝ/๊ฒฝ๊ณ„ ๋ฐ–์œผ๋กœ ์ƒ˜ํ”Œ๋ง

ํ˜„์ƒ
์ ์ด ๋ฒฝ ๋‚ด๋ถ€/๊ฒฝ๊ณ„ ๋ฐ–์—์„œ ๋“ฑ์žฅํ•˜๊ฑฐ๋‚˜ ์ถ”๋ฝ.

์›์ธ
NavMesh.SamplePosition ๋ฐ˜๊ฒฝ ๊ณผ์†Œ, areaMask ๋ฏธ์„ค์ •.

ํ•ด๊ฒฐ

  • ํ›„๋ณด ์ง€์ ์—์„œ SamplePosition(point, out hit, **radius**, **areaMask**)๋กœ ์—ฌ์œ  ๋ฐ˜๊ฒฝ ์ œ๊ณต.
  • allowedAreaNames๋กœ ๋งˆ์Šคํฌ ๋ช…์‹œ.

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ์Šคํฐ ์˜์—ญ Gizmo/BoxCollider ์‹œ๊ฐํ™”, ๋ฐ˜๊ฒฝ/๋งˆ์Šคํฌ ํ”„๋ฆฌ์…‹ ์œ ์ง€.

8) WheelCollider ์‹œ๊ฐ/๋ฌผ๋ฆฌ ๋ถˆ์ผ์น˜(ํА/๋ฐ•ํž˜)

ํ˜„์ƒ
์†๋„๊ฐ€ ์˜ค๋ฅด๊ฑฐ๋‚˜ ๊ฒฝ์‚ฌ๋ฉด์—์„œ ๋ฐ”ํ€ด ๋ฉ”์‹œ๊ฐ€ ๋œจ๊ฑฐ๋‚˜ ์„€์‹œ๊ฐ€ ํŠ„๋‹ค.

์›์ธ
๋ฉ”์‹œ ๋™๊ธฐํ™”๊ฐ€ Update์—์„œ ์ด๋ค„์ง, ๋ฌผ๋ฆฌ ํƒ€์ž„์Šคํ…/๋ณด๊ฐ„ ๋ถˆ์ผ์น˜.

ํ•ด๊ฒฐ

  • FixedUpdate์—์„œ GetWorldPose(out pos, out rot)๋กœ ๋ฉ”์‹œ ๋™๊ธฐํ™”.
  • Rigidbody Interpolate ์‚ฌ์šฉ, Fixed Timestep(๊ถŒ์žฅ 0.02s) ์ ๊ฒ€.

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ์ฐจ๋Ÿ‰ ๋น„์ฃผ์–ผ ๋™๊ธฐํ™”๋Š” ํ•ญ์ƒ FixedUpdate.

9) ์ด๋ฒคํŠธ ์ค‘๋ณต ๊ตฌ๋… → UI ๋‘ ๋ฐฐ ๊ฐฑ์‹ 

ํ˜„์ƒ
์”ฌ ์žฌ๋กœ๋“œ/ํŒจ๋„ ํ† ๊ธ€ ํ›„ HP/๊ณจ๋“œ ํ…์ŠคํŠธ๊ฐ€ ์ค‘๋ณต ์—…๋ฐ์ดํŠธ.

์›์ธ
OnEnable์—์„œ AddListener๋งŒ ํ•˜๊ณ  OnDisable ํ•ด์ œ ๋ˆ„๋ฝ.

ํ•ด๊ฒฐ

  • ๋ชจ๋“  ๊ตฌ๋…์€ OnEnable ↔ OnDisable ํŽ˜์–ด ๊ด€๋ฆฌ.
  • ํ•„์š” ์‹œ ๊ตฌ๋… ์ „ RemoveListener๋กœ 1์ฐจ ์ฒญ์†Œ.

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ๋ฆฌ๋ทฐ ์ฒดํฌ๋ฆฌ์ŠคํŠธ: “์ด๋ฒคํŠธ ๊ตฌ๋… ํ•ด์ œํ–ˆ๋‚˜?”

10) Stage ํƒ€์ด๋จธ ๋“œ๋ฆฌํ”„ํŠธ/ํญ์ฃผ

ํ˜„์ƒ
์‹œ๊ฐ„์ด ์ง€๋‚ ์ˆ˜๋ก Stage ์†๋„๊ฐ€ ๋นจ๋ผ์ง€๊ฑฐ๋‚˜ UI๊ฐ€ ๋ฐ€๋ฆผ.

์›์ธ
Time.time ๊ธฐ๋ฐ˜ ๋ฐ˜๋ณต์ด ์ •์ง€/ํ”„๋ ˆ์ž„ ๋“œ๋กญ์— ์˜ํ–ฅ, ์ฝ”๋ฃจํ‹ด ์ค‘๋ณต ์‹คํ–‰.

ํ•ด๊ฒฐ

  • ๋‹จ์ผ ์ฝ”๋ฃจํ‹ด ๊ฐ€๋“œ(isRunning) + WaitForSeconds.
  • ์ผ์‹œ์ •์ง€ ๋Œ€์‘ ํ•„์š” ์‹œ unscaledDeltaTime ๋ˆ„์ .

์žฌ๋ฐœ ๋ฐฉ์ง€

  • ๋ชจ๋“  ๋ฃจํ”„/ํƒ€์ด๋จธ์— ์ค‘๋ณต ์‹คํ–‰ ๊ฐ€๋“œ + ์ •์ง€/์žฌ๊ฐœ ์‹œ๋‚˜๋ฆฌ์˜ค ์ ๊ฒ€.
๋ฐ˜์‘ํ˜•