게임에서 뽑기 시스템은 플레이어의 몰입도를 극대화하는 핵심 메커니즘 중 하나입니다.
이번 글에서는 Unity에서 2단계 확률 기반 가챠 시스템을 설계하고 구현하는 방법을 소개합니다.


시스템 개요

이 가챠 시스템은 다음과 같은 구조로 구성됩니다:

  1. 1단계: 제작 방식(일반, 고급, 특수 등)을 확률에 따라 결정
  2. 2단계: 선택된 제작 방식에 따라 세부 결과(동일 오퍼레이터, 상위 등급 등)를 다시 확률 기반으로 결정

이 방식은 단계별로 결과를 분기할 수 있어, 일반적인 단일 룰 방식보다 확장성과 다양성이 뛰어납니다.


예시 데이터 구조

실제 프로젝트와 헷갈리지 않도록 예시용 테이블로 구성하였습니다.

🔹 1단계: 제작 타입 선택 테이블

Key category weight desc
20001 normal 70 일반 제작
20002 advanced 20 고급 제작
20003 special 10 특수 제작

🔹 2단계: 세부 결과 분기 테이블

Key category resultType weight desc
30001 20001 same_operator 15 동일 오퍼레이터 등장
30002 20001 higher_tier 25 상위 등급 등장
30003 20001 material_difference 60 재료 조합 변화
30004 20002 same_operator 20 동일 오퍼레이터 등장
30005 20002 higher_tier 30 상위 등급 등장
30006 20002 material_difference 50 재료 조합 변화
30007 20003 special_case 100 특수 제작 고정 결과

코드 구현 (작동 흐름 설명 포함)

🔸 데이터 구조 정의

public enum ProductionType { normal, advanced, special }
public enum ResultType { same_operator, higher_tier, material_difference, special_case }

[System.Serializable]
public class ProductionEntry
{
    public int key;
    public ProductionType category;
    public float weight;
    public string desc;
}

[System.Serializable]
public class ResultEntry
{
    public int key;
    public int productionKey;
    public ResultType resultType;
    public float weight;
    public string desc;
}

 

 

  • 제작 방식과 결과 분기를 각각 별도의 클래스로 관리
  • enum을 사용해 가독성과 유지보수성 확보

🔸 1단계 가챠: 제작 방식 선택

public int GetRandomProductionKey(ProductionType category)
{
    var filtered = productionTable.Where(e => e.category == category).ToList();
    float totalWeight = filtered.Sum(e => e.weight);
    float rand = Random.Range(0, totalWeight);
    float cumulative = 0f;

    foreach (var entry in filtered)
    {
        cumulative += entry.weight;
        if (rand <= cumulative)
            return entry.key;
    }

    return -1;
}

 

 

  • category에 해당하는 제작 방식 리스트에서
  • 가중치 기반으로 하나의 제작 ID(key)를 무작위로 선택합니다.
  • 예시:
    • rand가 85일 경우:
      • 첫 항목(70)보다 크므로 패스
      • 두 번째 항목(70+20=90)이 되면 85 <= 90 이 항목이 뽑힘

🔸 2단계 가챠: 결과 분기 결정

public ResultEntry GetRandomResult(int productionKey)
{
    var filtered = resultTable.Where(e => e.productionKey == productionKey).ToList();
    float totalWeight = filtered.Sum(e => e.weight);
    float rand = Random.Range(0, totalWeight);
    float cumulative = 0f;

    foreach (var entry in filtered)
    {
        cumulative += entry.weight;
        if (rand <= cumulative)
            return entry;
    }

    return null;
}

 

 

  • 1단계에서 선택된 제작 ID에 따라 다시 세부 결과를 가중치 기반으로 무작위 선택합니다.

🔸 전체 실행 흐름

public void ExecuteGacha(ProductionType category)
{
    int productionKey = GetRandomProductionKey(category);
    var result = GetRandomResult(productionKey);

    Debug.Log($"제작 방식: {category}, 선택된 제작 ID: {productionKey}");
    Debug.Log($"결과: {result.resultType} (key: {result.key})");
}

 


마무리

이 포스트에서는 Unity에서 2단계 확률 기반 가챠 시스템을 설계하고 구현하는 과정을 다뤘습니다.
단순한 뽑기 시스템을 넘어서 구조적이며 확장 가능한 설계 방식을 도입하면, 운영 편의성과 밸런싱 조정 모두에 유리한 기반을 마련할 수 있습니다.

현재는 Inspector에서 수동으로 설정한 테이블을 사용하고 있지만,
다음 단계에서는 JSON 기반의 외부 테이블을 불러와 가챠 데이터를 동적으로 구성할 계획입니다. 이를 통해 실제 서비스 환경에서도 실시간 데이터 수정이 가능하도록 만들 예정입니다.

+ Recent posts