생존, RPG, 로그라이크
무작위 던전에서 던전의 끝을 향해 클리어하기.
배고픔과 같은 게이지가 있어 각 방에서 식량이나 자원을 모아 생존해야 함.
게임 한 판 할 때마다 특정 자원이나 재화를 모아 영구적인 강화를 할 수 있음.
죽으면 다시 처음부터 시작하는 던전에 갇힌 플레이어가, 던전을 탈출하기 위해 단서를 모으는데,
단서를 모으면 플레이어의 능력치가 강화됨과 더불어 적이나 아이템 등 컨텐츠도 늘어남.
던전 => 던전형식 (보스 잡을시 클리어)
던전 (탑 형식?(올라가거나 내려가는 형식), (랜덤 맵 분포(나뭇가지, 큐브 처럼 분포))
사망시 던전 초기화 랜덤(구조가 바뀜)
보스방은 "열쇠"로
능력치 => 능력치 (HP(라이프), Damage, 쿨타임(카운트), Hungry, 존재력)
원거리/근거리 둘 중 아이템에 따라 달라짐 (상황에 따라 무기 교체)(원거리는 화살등 탄약이 필요)
제작 => 제작은 해당 제작하고 싶은 아이템을 클릭하면 "제작 하시겠습니까?" 창이 뜨고 쟤료가 충분하다면 확인으로 아이템 제작.
스탯 => (공격력, 치명타 확률, 이속)스탯
예) 레벨업 하면 체력, 배고픔 Full
레벨에 따른 몬스터한테 가해지는 데미지가 다름
적과 플레이어 레벨 차이에 따라 경험치 등 보너스
스킬쪽 => 스킬 포인트(스킬 해금), 스킬북 (Keep)
존재력으로 스킬 사용
생존 => Hungry, 존재력 관리 ,
0되면 사망
Hungry는 음식을 먹어 회복, 존재력은 몬스터를 죽여 회복
음식은 조리 안하고 바로 먹으면 디버프에 걸림(회복은 되긴 함) (나무를 캐서 모닥불로 조리)
모닥불 (음식 조리가능, 존재력 천천히 떨어짐)
아이템 => 드랍, 제작
제작은 쟤료만 있다면 클릭으로 제작 (레시피 북)
확장성 고려
private void GetValue() {
// NO!
}
private void GetValue()
{
// OK!
}
void Awake() { } // NO!
private void Awake() { } // OK!
public int count; // NO!
public int Count { get; set;} // OK!
public float Hp { // OK!
get => _hp;
set {
_hp = value;
// ...
}
}
private float _hp; // OK!
private int count; // NO!
private int _count; // OK!
public int count { get; set; } // NO!
public int Count { get; set; } // OK!
public int GetCount(List<int> _list) { } // NO!
public int GetCount(List<int> list) { } // OK!
private void Awake()
{
int _count = 1;
// NO!
}
private void Awake()
{
int count = 1;
// OK!
}
private int _idx; // NO!
private int _index; // OK!
private int Count() { } // NO!
private int GetCount() { } // OK!
private int GetCountEnemyInScreen() { } // OK!
private SpriteRenderer _sr; // NO! (이렇게 축약하기로 모두와 약속했다면 OK입니다)
private SpriteRenderer _spriteRenderer // OK!
#region Properties
public int Count { get; set; }
public int Level { get; set; }
#endregion
#region Fields
// Collections.
private List<int> _numberList;
// Components.
private SpriteRenderer _spriteRenderer;
private BoxCollider2D _boxCollider2D;
// Events.
public event Action OnChangedResource;
#endregion
#region MonoBehaviours
private void Awake() { }
private void Update() { }
#endregion
#region Init / Set
public void Initialize() { }
public void SetInfo() { }
#endregion
#region ...
// ...
#endregion
public interface IAttackable { }
private Coroutine _coAttack;
private Coroutine CoAttack() { }
ex ) LJH-GameManager-InitGame
이름-Class-기능
[💫 Feature] : 새로운 클래스 작성
[🐞 BugFix] : 기존 코드의 버그를 수정
[➕ Add] : 기존 기능에 추가적인 확장 기능을 제공
[👨🏻🚒 HOTFIX] : 심각하거나 즉각 해결해야 하는 내용이 있을때
평소 AI 쪽을 한번 공부해 보고 싶어서 몬스터의 공격이나 회피 등의 AI를 맡게 되었다.
"유한 상태 머신 FSM (Finite State Machine)"을 강의에서 배웠기에 사용하려고 더 알아보았는데 강의를 보면서 공부할 때도 느꼈지만, FSM은 규모가 커지면 커질수록 한계가 생기고 코드면에서 유지 보수가 힘들다는 것을 느꼈다.
그래서 더 좋은 방법이 무엇이 있을까? 고민하며 찾아본 결과 "행동 트리 BT (Behaviour Tree)"에 대해 알게 되었고 공부를 하다 보니 점점 빠져들게 되었다.
공부를 하면 해볼수록 놀랍고 설레는 마음이었다. 복잡한 AI의 과정이 그림으로 표현되어 유기적으로 마치 살아있는 생명체처럼 움직일 수 있게 하고 실제로 그것을 기반해서 코드를 짜는 것이 너무 재밌어 보였다. 이 전 글들을 보면 BT에 대해 계속 공부를 해서, 실제로 개인 과제에서 간단한 예제를 참고해 만들었는데 매우 흥미롭고 재미있었다.
확실히 나중에 행동을 추가하거나 빼려고 할 때 유지 보수적인 측면이나 시인성에서 훨씬 더 좋은 방법으로 실제 내가 느꼈기고 좀 더 복잡하고 다양한 행동 로직을 작성하고 싶어 BT를 선정한 이유가 되었다.
기본 동작 순찰 (or 제자리로 복귀)
인식 범위 / 공격 범위 (OverlapCircleAll)
몬스터가 피격 당하면 추적 거리가 증가
노멀을 제외한 타입은 "특수 스킬"이 존재 (쿨타임 or 인식 범위 최초 1회)
노멀 : 플레이어에게 계속 붙어서 공격
탱커 : 돌진 (특수 기술)(순간 무적 판정)
암살 : 암살 인식 범위 안으로 들어오면 플레이어 뒤로 순간이동 후 공격 (특수 스킬)(치명타)
데드존(인식, 공격 이외에 또하나의 범위)에 따라 달라지는 공격 방식
노멀 : 제자리에서 계속 공격
척후 : 데드존 안에 들어오면 도망치면서 공격
저격 : 데드존 내에 들어오면 안전거리 확보 까지 계속 도망
몬스터가 피격 시 추적거리 증가 (범위를 벗어나면 초기화 할 것인지? 타이머로 초기화 할 것인지?)
트리 구조를 토대로 코드 작성. 버그 수정