Unity 엔진 공부/project1
project1 개발일지 - 3 [몬스터 스탯 설계]
EJH
2025. 7. 14. 19:27
반응형
스탯 시스템 설계 및 몬스터 데이터 연동
목표
플레이어, NPC, 몬스터 등 다양한 오브젝트가 공유할 수 있는 스탯 시스템을 설계하고, 몬스터 데이터를 JSON 기반으로 관리 및 코드에 연동하는 것이 이번 작업의 핵심이다.
1. 스탯 상속 구조 설계
- 플레이어, 몬스터, NPC 등 다양한 오브젝트가 공통적으로 가지는 전투/생존 관련 스탯을 공유하되, 객체마다 다른 스탯은 개별로 확장할 수 있게 하기 위함.
BaseStat
(모든 체력 관련 오브젝트가 공통으로 가지는 스탯)
- id
- hp
- maxHp
- attackDamage
- armor
- speed
- attackSpeed
- attackRange
Player
- maxJumpCount
- jumpPower
- exp
- gold
- reviveCount
- hpRegen
- skillCooldowns
NPC
- detectRange
Monster
- detectRange
- rewardExp
- rewardGold
상속 관계도
BaseStat
├── StaticObject (e.g. wall)
└── DynamicObject
├── Player
├── NPC
└── Monster
위와 같은 상속 관계도를 이용해 필요한 스탯을 추가하는 식으로 사용한다.
2. 몬스터 기획 및 데이터화
- 몬스터 특성과 전투력을 미리 설계해두고, 이를 기반으로 전투 밸런스를 조율하며 구현할 수 있게 하려는 목적
- 감지거리, 어그로 해제, 투사체 타입, 공격방식 등 구체적 스탯이 설계되어 AI 로직 구현 방향이 명확해짐
- 기획자/디자이너와 공통 언어로 소통 가능
3. JSON 기반 외부 데이터 관리
- 몬스터 수치 데이터를 코드에서 분리하여 유연하게 수정할 수 있도록 하기 위해 json 사용
{
"stats": [
{
"monsterName": "mogi",
"monsterId": 1,
"detectRange": 60,
"attackRange": 40,
"aggroReleaseDistance": 90,
"speed": 6,
"maxHp": 24,
"armor": 0,
"attackDamage": 4,
"attackSpeed": 0.4,
"rewardExp": 50,
"rewardGold": 10
},
{
"monsterName": "gaori",
"monsterId": 2,
"detectRange": 40,
"attackRange": 20,
"aggroReleaseDistance": 60,
"speed": 5,
"maxHp": 40,
"armor": 1,
"attackDamage": 7,
"attackSpeed": 0.3,
"rewardExp": 50,
"rewardGold": 10
},
{
"monsterName": "dragon",
"monsterId": 101,
"detectRange": 20,
"attackRange": 10,
"aggroReleaseDistance": 30,
"speed": 10,
"maxHp": 100,
"armor": 1,
"attackDamage": 7,
"attackSpeed": 0.3,
"rewardExp": 50,
"rewardGold": 10
}
]
}
4. 스탯 시스템 코드 연동 (예: NPCStat.cs)
- json 데이터를 가져와 동기화 한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NPCStat : Stat
{
[SerializeField] public int _monsterId;
public int _rewardExp;
public int _rewardGold;
public float _detectRange;
private void Start()
{
SetStat(_monsterId);
}
public void SetStat(int id)
{
Dictionary<int, Data.MonsterStat> dict = Managers.Data.MonsterStatDict;
Data.MonsterStat stat = dict[id];
_monsterId = stat.monsterId;
_hp = stat.maxHp;
_maxHp = stat.maxHp;
_attackDamage = stat.attackDamage;
_armor = stat.armor;
_speed = stat.speed;
_attackRange = stat.attackRange;
_attackSpeed = stat.attackSpeed;
_detectRange = stat.detectRange;
_rewardExp = stat.rewardExp;
_rewardGold = stat.rewardGold;
}
public int MonsterId { get { return _monsterId; } set { _monsterId = value; } }
public int RewardExp { get { return _rewardExp; } set { _rewardExp = value; } }
public int RewardGold { get { return _rewardGold; } set { _rewardGold = value; } }
public float DetectRange { get { return _detectRange; } set { _detectRange = value; } }
//Todo 테스트용 나중에 삭제
private void Update()
{
if(Input.GetKeyDown(KeyCode.P)) {
_hp -= 5;
if (_hp <= 0)
{
OnDead();
}
}
}
protected override void OnDead(Stat attacker = null)
{
base.OnDead(attacker);
GetComponent<BaseNPC>().Die();
}
}
json 파일과 스탯 동기화 확인완료
마무리
- 다양한 객체가 공통 스탯을 상속 구조로 유연하게 사용할 수 있게 되었음
- 몬스터 정보는 JSON으로 관리되어 게임 밸런스 수정이 쉬움
- 코드에서는 ID 기반으로 스탯 자동 초기화
- 향후 아이템/버프/디버프 연동 시에도 이 구조가 재사용 가능함
반응형