Unity 심화 팀 프로젝트 - 1

이준호·2024년 1월 2일
0
post-thumbnail

📌 Unity 게임 개발 심화 - 팀 프로젝트



📌 팀 프로젝트 기획

  • 생존, RPG, 로그라이크

  • 무작위 던전에서 던전의 끝을 향해 클리어하기.

  • 배고픔과 같은 게이지가 있어 각 방에서 식량이나 자원을 모아 생존해야 함.

  • 게임 한 판 할 때마다 특정 자원이나 재화를 모아 영구적인 강화를 할 수 있음.

  • 죽으면 다시 처음부터 시작하는 던전에 갇힌 플레이어가, 던전을 탈출하기 위해 단서를 모으는데,
    단서를 모으면 플레이어의 능력치가 강화됨과 더불어 적이나 아이템 등 컨텐츠도 늘어남.

➔ 최소기능 (나열)

  • 던전 => 던전형식 (보스 잡을시 클리어)
    던전 (탑 형식?(올라가거나 내려가는 형식), (랜덤 맵 분포(나뭇가지, 큐브 처럼 분포))
    사망시 던전 초기화 랜덤(구조가 바뀜)
    보스방은 "열쇠"로

  • 능력치 => 능력치 (HP(라이프), Damage, 쿨타임(카운트), Hungry, 존재력)

  • 원거리/근거리 둘 중 아이템에 따라 달라짐 (상황에 따라 무기 교체)(원거리는 화살등 탄약이 필요)

  • 제작 => 제작은 해당 제작하고 싶은 아이템을 클릭하면 "제작 하시겠습니까?" 창이 뜨고 쟤료가 충분하다면 확인으로 아이템 제작.

  • 스탯 => (공격력, 치명타 확률, 이속)스탯
    예) 레벨업 하면 체력, 배고픔 Full
    레벨에 따른 몬스터한테 가해지는 데미지가 다름
    적과 플레이어 레벨 차이에 따라 경험치 등 보너스

  • 스킬쪽 => 스킬 포인트(스킬 해금), 스킬북 (Keep)
    존재력으로 스킬 사용

  • 생존 => Hungry, 존재력 관리 ,
    0되면 사망
    Hungry는 음식을 먹어 회복, 존재력은 몬스터를 죽여 회복
    음식은 조리 안하고 바로 먹으면 디버프에 걸림(회복은 되긴 함) (나무를 캐서 모닥불로 조리)
    모닥불 (음식 조리가능, 존재력 천천히 떨어짐)

  • 아이템 => 드랍, 제작
    제작은 쟤료만 있다면 클릭으로 제작 (레시피 북)

  • 확장성 고려






➔ 코드 컨벤션

줄 바꿈 규칙

  • 키워드나 함수, 클래스를 정의하는 등 새 괄호를 열 때는 줄바꿈을 해요.
private void GetValue() {
		// NO!
}

private void GetValue()
{
		// OK!
}

접근 제한자 명시

  • 접근 제한자를 분명하게 구분하고 이를 명시해요.
void Awake() { }          // NO!
private void Awake() { }  // OK!

필드/프로퍼티

  • 지나친 전역 변수 사용은 되도록 지양해요.
  • 필요한 필드는 되도록 private으로, 외부에서 접근해야 하는 경우 프로퍼티로 관리해요.
public int count;               // NO!
public int Count { get; set;}   // OK!

public float Hp {               // OK!
    get => _hp;
    set {
        _hp = value;
        // ...
    }
}
private float _hp;              // OK!

명명 규칙

  • private, protected 필드는 ‘_’를 붙이고, 프로퍼티는 대문자로 시작해요.
  • 매개변수나 로컬 변수 등은 그대로 써요.
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!

주석

  • 주석은 최대한 간단명료하게 작성해주세요.
  • 메서드의 주석은 /// Summary를 이용해주세요.

region 지시문 사용

  • 비슷한 속성의 코드들은 region 지시문을 통해 구분해주세요. 가독성이 크게 증가합니다!
#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

기타 규칙

  • 인터페이스는 I로 시작합니다.
public interface IAttackable { }
  • 코루틴은 Co로 시작하고, 코루틴 필드는 co로 시작합니다.
private Coroutine _coAttack;
private Coroutine CoAttack() { }
  • 이벤트나 콜백의 경우, 어떤 상황에 관한 것인지 명시해줍니다.





➔ 깃 컨벤션

커밋은 기능별로 구현이 되면 꼭 커밋하고 알려주셔야 합니다.


Develop Branch

  • 모든 작업은 Main이 아닌 Develop이라는 보조 Branch를 생성하여 해당 브랜치의 하위에서 작업
  • 제품이 완성 되었을 때만 Main에 Merge

Branch 생성 기준

ex ) LJH-GameManager-InitGame

이름-Class-기능

  • 브랜치는 각 클래스 또는 더 작은 범위로 하여 해당 메서드 기능이 문제 없이 작동하면 커밋하여 프로젝트를 지속적으로 최신화 해야합니다.

Commit, PR, Merge

  • 해당 작업을 수행 하실때는 꼭 팀원 전체에 공유가 되어야합니다.
  • 해당 메세지를 받으신 팀원분들 전원은 꼭 브랜치를 최신화 해주셔야 합니다.

Commit Message

  • Summary를 꼭 작성해주시기 바랍니다.
  • Message는 해당 커밋에서 바뀐것 아니면, 해당 커밋을 받는 팀원들이 참고해야하는 참고사항을 꼭 기입해주세요

Summary [Head]

[💫 Feature] : 새로운 클래스 작성

[🐞 BugFix] : 기존 코드의 버그를 수정

[➕ Add] : 기존 기능에 추가적인 확장 기능을 제공

[👨🏻‍🚒 HOTFIX] : 심각하거나 즉각 해결해야 하는 내용이 있을때












📌 BT 선정 이유 / AI

평소 AI 쪽을 한번 공부해 보고 싶어서 몬스터의 공격이나 회피 등의 AI를 맡게 되었다.

➔ Why Behaviour Tree?

"유한 상태 머신 FSM (Finite State Machine)"을 강의에서 배웠기에 사용하려고 더 알아보았는데 강의를 보면서 공부할 때도 느꼈지만, FSM은 규모가 커지면 커질수록 한계가 생기고 코드면에서 유지 보수가 힘들다는 것을 느꼈다.

그래서 더 좋은 방법이 무엇이 있을까? 고민하며 찾아본 결과 "행동 트리 BT (Behaviour Tree)"에 대해 알게 되었고 공부를 하다 보니 점점 빠져들게 되었다.

공부를 하면 해볼수록 놀랍고 설레는 마음이었다. 복잡한 AI의 과정이 그림으로 표현되어 유기적으로 마치 살아있는 생명체처럼 움직일 수 있게 하고 실제로 그것을 기반해서 코드를 짜는 것이 너무 재밌어 보였다. 이 전 글들을 보면 BT에 대해 계속 공부를 해서, 실제로 개인 과제에서 간단한 예제를 참고해 만들었는데 매우 흥미롭고 재미있었다.

확실히 나중에 행동을 추가하거나 빼려고 할 때 유지 보수적인 측면이나 시인성에서 훨씬 더 좋은 방법으로 실제 내가 느꼈기고 좀 더 복잡하고 다양한 행동 로직을 작성하고 싶어 BT를 선정한 이유가 되었다.

➔ 근거리와 원거리 적 구상

공통

  • 기본 동작 순찰 (or 제자리로 복귀)

  • 인식 범위 / 공격 범위 (OverlapCircleAll)

  • 몬스터가 피격 당하면 추적 거리가 증가

근거리(타입)

노멀을 제외한 타입은 "특수 스킬"이 존재 (쿨타임 or 인식 범위 최초 1회)

  • 노멀 : 플레이어에게 계속 붙어서 공격

  • 탱커 : 돌진 (특수 기술)(순간 무적 판정)

  • 암살 : 암살 인식 범위 안으로 들어오면 플레이어 뒤로 순간이동 후 공격 (특수 스킬)(치명타)

원거리(타입)

데드존(인식, 공격 이외에 또하나의 범위)에 따라 달라지는 공격 방식

  • 노멀 : 제자리에서 계속 공격

  • 척후 : 데드존 안에 들어오면 도망치면서 공격

  • 저격 : 데드존 내에 들어오면 안전거리 확보 까지 계속 도망












📌 Monster Behaviour Tree

➔ Near Monster BT

➔ Far Monster BT












📌 앞으로 계획

  • 몬스터가 피격 시 추적거리 증가 (범위를 벗어나면 초기화 할 것인지? 타이머로 초기화 할 것인지?)

  • 트리 구조를 토대로 코드 작성. 버그 수정

profile
No Easy Day

0개의 댓글