Post

[UNITY]중간점검 보고서

[UNITY]중간점검 보고서

목차

  1. 프로젝트 개요
  2. 개발 시스템 구성

    2.1 플레이어 시스템

    2.2 스탯 시스템

    2.3 레벨업 및 경험치

    2.4 퀘스트 시스템

    2.5 인벤토리 및 아이템

    2.6 상점 시스템

    2.7 강화 시스템

    2.8 버프 시스템

    2.9 포탈 및 씬 전환

    2.10 몬스터 자동 리젠

    2.11 세이브 및 로드 시스템

    2.12 크리티컬 시스템

  3. 코드 리뷰

    3.1 구조 설계

    3.2 기능 구현

    3.3 개선 사항

  4. 결론 및 향후 개발 계획

1. 프로젝트 개요

이 프로젝트는 Unity를 기반으로 제작된 로그라이크 스타일의 2D 게임으로, 전투, 강화, 퀘스트, 인벤토리, 스탯, 포탈 이동, 세이브 및 로드 등의 시스템을 통합하여 제작되었다.

플레이어는 키보드를 이용해 다양한 스킬과 상호작용을 통해 성장하고, 적을 처치하며 게임을 진행한다.


2. 개발 시스템 구성

2.1 플레이어 시스템

  • 이동, 점프, 대시, 공격 및 스킬 사용이 가능하다.
  • 애니메이션 기반의 콤보 공격과 스킬 공격은 애니메이션 이벤트와 히트박스를 통해 구현된다.
  • Player.cs에서 대부분의 로직이 통합되어 있으며, 스킬 사용 시 잔상 이펙트, 카메라 흔들림, 초상화 연출도 구현되어 있다.

https://github.com/user-attachments/assets/29f3bd72-ff18-4a0d-81e3-c20ffc937d1a

https://github.com/user-attachments/assets/e4621f35-e4d0-4b4c-a281-b2b1bdfddfc9

2.2 스탯 시스템

  • PlayerStat.cs를 통해 HP, MP, 힘, 덱스, 치명타 등의 스탯을 관리한다.
  • 장비나 레벨업을 통해 스탯이 증가하며, StatUI.cs에서 UI로 표시된다.
    • S 키를 통해 스탯 패널을 토글할 수 있다.

Image

STAT UI창

2.3 레벨업 및 경험치

  • 적을 처치하면 경험치를 획득하며, 일정량 이상 모이면 자동으로 레벨업한다.
  • 경험치 공식은 성장 계수 기반이며, PlayerLevel.cs에 구현되어 있다.
  • 레벨업 시 스탯 보너스가 자동으로 적용된다.

Image

레벨업시 추가 스텟 지정

2.4 퀘스트 시스템

  • NPC와 상호작용하면 퀘스트 수락 및 진행이 가능하다.
  • 퀘스트는 QuestData라는 ScriptableObject 기반으로 관리되며, QuestManager에서 상태를 추적한다.
  • 조건을 만족하면 자동으로 완료 처리되고, 골드와 경험치를 보상으로 받을 수 있다.

2.5 인벤토리 및 아이템

  • 아이템은 ScriptableObject 기반의 ItemData로 정의되어 있으며, 포션, 장비, 퀘스트 아이템 등으로 나뉜다.
  • 인벤토리는 슬롯 기반 UI로 구성되어 있으며, 상점에서 구매 시 자동으로 인벤토리에 추가된다.

Image

INVENTORY 구현

Image

물약 획득 전

Image

인벤토리 UI 세팅부분

Image

획득 후

2.6 상점 시스템

  • NPC 대화 중 상점을 열 수 있으며, 상점 창과 인벤토리가 동시에 열리는 구조다.
  • 골드가 부족하면 구매가 불가능하고, 성공 시 인벤토리에 아이템이 추가된다.
  • UI는 ShopManagerShopItemSlot으로 구성되어 있으며, 각 슬롯은 동적으로 생성된다.

대화창

대화창

상점 열렸을떄의 동적할당 사진

상점 열렸을떄의 동적할당 사진

Image

선택지

2.7 강화 시스템

  • 각 장비 부위를 강화할 수 있으며, 강화 확률과 비용이 존재한다.
  • 강화 성공 시 스탯에 반영되고, 실패 시 골드만 차감된다.
  • 강화 UI는 UpgradePanelToggleUpgradeUI로 구현되어 있다.

Image

Image

Image

Image

Image

강화성공시 스텟 변화

2.8 버프 시스템

  • F1~F5 키를 통해 공격력, 이동속도 등의 버프를 부여할 수 있다.
  • 현재는 하나의 버프만 활성화 가능하며, 새로운 버프를 사용하면 기존 버프는 해제된다.
  • 버프 아이콘과 타이머는 UI 상단에 표시된다.

https://github.com/user-attachments/assets/e7b809d4-44eb-4121-87ef-d4d206221b61

https://github.com/user-attachments/assets/43ba4717-0b0c-47da-8881-9fa37b897540

2.9 포탈 및 씬 전환

  • 포탈에 접촉 시 해당 포탈의 ID에 따라 씬이 전환된다.
  • 포탈 이동 시 PlayerPrefs를 이용해 스폰 지점을 저장하며, 다음 씬에서 자동 복원된다.
  • PortalManager.csPortalTrigger.cs로 구현되어 있

Image

이동 전

Image

시작시 스폰위치 지정

Image

이동 후

Image

스포너의 위치

2.10 자동 리젠 시스템

  • 게임의 몬스터는 특정 SpawnPoint 위치를 기준으로 자동으로 생성되며, 일정 시간 간격 **으로 부족한 수량만큼 보충되는 방식으로 리젠된다.
  • 이 시스템은 리소스 낭비 없이 지속적인 몬스터 배치 유지를 목적으로 설계되었으며, 일정 범위 내 랜덤 위치에 적을 생성할 수 있도록 구현되었다.

https://github.com/user-attachments/assets/b602a1ae-4c81-4a71-b8fd-954ea6786c41

자동리젠 동영상

Image 젠 이전

Image

젠 이후

2.11 세이브 및 로드 시스템

  • ESC 메뉴를 통해 게임 상태 저장 및 불러오기가 가능하다.
  • 저장 항목: 씬 이름, 플레이어 위치, 레벨, 경험치 등
  • 향후 인벤토리, 퀘스트 상태 저장도 확장 가능

https://github.com/user-attachments/assets/f3e9c9c5-706d-4e9a-ab57-e216a0cf01f2

2.12 크리티컬 시스템 (데미지*1.8)

  • PlayerStat.critical: 치명타 확률 (%)
  • PlayerStat.GetCriticalMultiplier(): 크리티컬 발생 시 데미지 배율

https://github.com/user-attachments/assets/15c8082f-0333-4b5f-95ba-476102fd34a9


코드 리뷰 (세부 분석 및 확장 가능성 포함)


1. Player.cs (플레이어 행동 통합 스크립트)

주요 특징

  • Update()에 이동, 점프, 대시, 스킬, 애니메이션이 모두 들어 있음
  • 스킬은 Q, W로 분기되어 있으며 각각 별도 쿨타임, MP 체크를 진행
  • CameraShake, AfterImage, Animator Trigger를 통합적으로 사용하여 연출 강화

특이점

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (Input.GetKeyDown(KeyCode.Q)) {
    bool enoughMana = StatMana.instance.currentMP >= specialSkillCost;
    bool cooldownReady = Time.time >= lastSkillTime + SkillCooldown;

    if (enoughMana && cooldownReady) {
        StatMana.instance.UseMana(specialSkillCost);
        anim.SetTrigger(specialTriggerName);
        lastSkillTime = Time.time;
        StartCoroutine(StartSkillAfterImages());
        rb.AddForce(Vector2.up * 20f, ForceMode2D.Impulse);
    }
}

  • 애니메이션과 물리 반응, 마나 시스템을 자연스럽게 엮어 연출이 좋음
  • 스킬 구조가 상수 기반이므로, 향후 스킬 데이터를 ScriptableObject로 분리하면 SkillData.cs 기반의 스킬 시스템 확장 가능

확장성 제안

1
2
3
4
5
6
7
8
9
10
[CreateAssetMenu(menuName = "Skill/SkillData")]
public class SkillData : ScriptableObject {
    public string skillName;
    public int manaCost;
    public float cooldown;
    public float forceY;
    public AnimationClip anim;
}

  • 스킬 선택 및 업그레이드가 가능한 시스템으로 전환 가능
  • PlayerSkillManager에서 키 매핑이나 슬롯 시스템 도입도 가능

2. BuffManager.cs

주요 특징

  • 하나의 버프만 유지 가능
  • 새 버프 사용 시 기존 버프 제거 후 새로운 버프 적용

특이점

1
2
3
4
5
6
if (currentBuffRoutine != null)
    StopCoroutine(currentBuffRoutine);
if (currentUI != null)
    Destroy(currentUI);

  • 단일 버프만 처리 가능하며, CoroutineUI 모두 하나씩만 유지
  • UI는 buffUIPrefab 인스턴스를 동적으로 생성

개선 및 확장 구조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Dictionary<BuffType, Coroutine> activeBuffs = new();
Dictionary<BuffType, GameObject> activeUIs = new();

public void ApplyBuff(BuffType type, float duration, float value) {
    if (activeBuffs.ContainsKey(type)) {
        StopCoroutine(activeBuffs[type]);
        Destroy(activeUIs[type]);
    }

    Coroutine routine = StartCoroutine(BuffRoutine(type, duration, value));
    GameObject ui = Instantiate(buffUIPrefab, buffUIParent);

    activeBuffs[type] = routine;
    activeUIs[type] = ui;
}

  • BuffType별로 동시 유지 가능 → 다중 버프 처리 가능
  • 이 구조는 나중에 디버프나 상태이상도 함께 처리할 수 있음

3. Hitbox.cs / Enemy.cs / DamageTextSpawner.cs

주요 특징

  • 전투는 Hitbox → IDamageable → Enemy.cs 흐름으로 연결됨
  • 데미지 처리, 회피, 방어, 크리티컬 처리 포함

특이점

1
2
3
4
5
6
7
bool isEvaded = playerAccuracy < evade;
if (isEvaded) {
    DamageTextSpawner.I.SpawnText("Miss", transform.position + Vector3.up * 1.2f);
    return;
}

  • 회피를 단순 비교로 처리함 → 이후 랜덤화공식 기반 확률로 확장 가능
  • 데미지, 치명타, 방어력이 잘 분리되어 있음

확장 가능성

  • DamageInfo 구조체 도입
1
2
3
4
5
6
7
8
public struct DamageInfo {
    public int amount;
    public bool isCrit;
    public bool isMiss;
    public Vector2 knockback;
}

  • 이후 다양한 공격 유형(화염, 빙결, 중독 등) 확장 시 유용

4. QuestManager.cs + Quest.cs + QuestUIUpdater.cs

특징

  • 퀘스트는 QuestData(SO) → Quest(instance)로 매핑
  • 퀘스트는 진행형과 완료형 2가지 상태만 처리
  • 모든 퀘스트 진행은 문자열 기반 targetName 비교

특이점

1
2
3
4
5
6
if (target == data.targetName) {
    currentAmount++;
    if (currentAmount >= data.requiredAmount) Complete();
}

  • target 문자열 기반이라 타이포에 취약
  • target을 GameObject의 이름으로만 사용함 → ID 기반 비교가 더 안전

확장 제안

1
2
3
4
5
6
7
[System.Serializable]
public class QuestTarget {
    public string id;
    public int requiredAmount;
}

  • List<QuestTarget>을 활용해 다중 목표 퀘스트 구성 가능
  • 퀘스트 타입이 단일 enum 기반이라 확장시 interface IQuestCondition 패턴 도입 가능

5. UpgradePanelToggle.cs + UpgradeUI.cs

주요 특징

  • U 키로 강화 UI 토글
  • 부위별 아이템을 선택 → 강화 버튼 클릭 → 강화 확률 계산 → 성공/실패 처리

특이점

1
2
3
4
5
6
7
float successRate = currentItem.GetSuccessRate();
float roll = Random.value;
if (roll < successRate) {
    currentItem.level++;
}

  • 강화 확률을 직접적으로 Random.value로 처리
  • 강화 수치나 확률이 ItemData에 전부 포함되어 있음

개선 제안

  • UpgradeRuleData 같은 규칙 데이터 분리
  • UI 강화 결과에 따른 효과음, 연출 추가

6. GameSaveManager.cs

주요 특징

  • PlayerPrefs를 활용한 저장
  • 현재 씬, 위치, 레벨, 경험치 저장

특이점

1
2
3
4
PlayerPrefs.SetFloat("PlayerX", player.position.x);
PlayerPrefs.SetInt("PlayerLevel", PlayerLevel.instance.currentLevel);

  • 매우 빠르게 구현 가능한 구조지만, 저장 항목 추가 시 확장성이 떨어짐

확장 가능성

1
2
3
4
5
6
7
8
9
10
11
[System.Serializable]
public class SaveData {
    public string scene;
    public Vector3 playerPos;
    public int level;
    public float exp;
    public List<string> completedQuests;
    public List<ItemSaveData> inventory;
}

  • JSON으로 직렬화해서 Application.persistentDataPath에 저장하면 유연하게 확장 가능

7. ShopManager.cs

특징

  • 상점은 동적으로 슬롯을 생성 (Instantiate)
  • 골드 확인 후 구매 → 인벤토리 추가

특이점

1
2
3
4
5
6
7
8
9
foreach (Transform child in itemSlotParent)
    Destroy(child.gameObject);

foreach (var item in shopItems) {
    GameObject slot = Instantiate(itemSlotPrefab, itemSlotParent);
    shopSlot.Setup(item);
}

  • 매번 새로 만들기 때문에 성능적으로 부담 가능성 있음 → 오브젝트 풀링이 필요함

확장성

  • ObjectPool<ShopItemSlot>을 도입해 슬롯을 재사용하는 방식으로 전환 가능
  • 판매 시스템, 장비 비교 기능까지 확장 가능

마무리 정리

영역평가확장 방향
플레이어 전투안정적 구조스킬 데이터를 ScriptableObject로 분리
버프 시스템단일 버프만 가능다중 버프 구조(Dict 기반)로 확장
퀘스트간단한 조건 처리다중 목표/조건 클래스화
강화명확한 흐름확률/레벨별 규칙 분리 및 연출 추가
세이브빠른 구현JSON 기반으로 구조화 확장
상점기능적 완성풀링, 판매, 장비비교 등 기능 확장
This post is licensed under CC BY 4.0 by the author.