개발일지/팀GC Defence

2021/10/27 상점구현

박준희 2021. 10. 27. 19:51

새로 개발하는 디펜스 게임의 상점을 구현

 

조건

  • 스테이지 깰때마다 상점에 파는 아이템이 달라짐
  • 무기 종류 5개, 등급 5개
  • 등급에 따라 다른 확률 적용
  • 중복 상관없음
  • 상점 아이템 출력 개수 6개

 

 

1. 무기 등급에 따른 확률 테이블 제작 및 파싱 클래스 제작

json파일

shop_weapon_grade_percentage.json

[{"raw":100,"grade":0,"grade_name":"흔한","percentage":40},
    {"raw":101,"grade":1,"grade_name":"안흔함","percentage":30},
    {"raw":102,"grade":2,"grade_name":"희귀","percentage":20},
    {"raw":103,"grade":3,"grade_name":"고유","percentage":8},
    {"raw":104,"grade":4,"grade_name":"전설","percentage":2}]

item_weapon.json

[{"raw":1000,"item_name":"지팡이1","item_description":"흔한 지팡이","kind_of_money":0,"price":100,"item_type":0,"attack_power":10,"critical_attack_power":10,"critical_chance":10,"speed_of_attack":10,"item_grade":0,"weapon_type":0},
  {"raw":1001,"item_name":"지팡이2","item_description":"안흔한 지팡이","kind_of_money":0,"price":200,"item_type":0,"attack_power":11,"critical_attack_power":11,"critical_chance":11,"speed_of_attack":11,"item_grade":1,"weapon_type":0},
  {"raw":1002,"item_name":"지팡이3","item_description":"희귀 지팡이","kind_of_money":0,"price":300,"item_type":0,"attack_power":12,"critical_attack_power":12,"critical_chance":12,"speed_of_attack":12,"item_grade":2,"weapon_type":0},
  {"raw":1003,"item_name":"지팡이4","item_description":"고유 지팡이","kind_of_money":0,"price":400,"item_type":0,"attack_power":13,"critical_attack_power":13,"critical_chance":13,"speed_of_attack":13,"item_grade":3,"weapon_type":0},
  {"raw":1004,"item_name":"지팡이5","item_description":"전설 지팡이","kind_of_money":0,"price":500,"item_type":0,"attack_power":14,"critical_attack_power":14,"critical_chance":14,"speed_of_attack":14,"item_grade":4,"weapon_type":0},
  {"raw":1005,"item_name":"활1","item_description":"흔한 활","kind_of_money":0,"price":100,"item_type":0,"attack_power":10,"critical_attack_power":10,"critical_chance":10,"speed_of_attack":10,"item_grade":0,"weapon_type":1},
  {"raw":1006,"item_name":"활2","item_description":"안흔한 활","kind_of_money":0,"price":200,"item_type":0,"attack_power":11,"critical_attack_power":11,"critical_chance":11,"speed_of_attack":11,"item_grade":1,"weapon_type":1},
  {"raw":1007,"item_name":"활3","item_description":"희귀 활","kind_of_money":0,"price":300,"item_type":0,"attack_power":12,"critical_attack_power":12,"critical_chance":12,"speed_of_attack":12,"item_grade":2,"weapon_type":1},
  {"raw":1008,"item_name":"활4","item_description":"고유 활","kind_of_money":0,"price":400,"item_type":0,"attack_power":13,"critical_attack_power":13,"critical_chance":13,"speed_of_attack":13,"item_grade":3,"weapon_type":1},
  {"raw":1009,"item_name":"활5","item_description":"전설 활","kind_of_money":0,"price":500,"item_type":0,"attack_power":14,"critical_attack_power":14,"critical_chance":14,"speed_of_attack":14,"item_grade":4,"weapon_type":1},
  {"raw":1010,"item_name":"창1","item_description":"흔한 창","kind_of_money":0,"price":100,"item_type":0,"attack_power":10,"critical_attack_power":10,"critical_chance":10,"speed_of_attack":10,"item_grade":0,"weapon_type":2},
  {"raw":1011,"item_name":"창2","item_description":"안흔한 창","kind_of_money":0,"price":200,"item_type":0,"attack_power":11,"critical_attack_power":11,"critical_chance":11,"speed_of_attack":11,"item_grade":1,"weapon_type":2},
  {"raw":1012,"item_name":"창3","item_description":"희귀 창","kind_of_money":0,"price":300,"item_type":0,"attack_power":12,"critical_attack_power":12,"critical_chance":12,"speed_of_attack":12,"item_grade":2,"weapon_type":2},
  {"raw":1013,"item_name":"창4","item_description":"고유 창","kind_of_money":0,"price":400,"item_type":0,"attack_power":13,"critical_attack_power":13,"critical_chance":13,"speed_of_attack":13,"item_grade":3,"weapon_type":2},
  {"raw":1014,"item_name":"창5","item_description":"전설 창","kind_of_money":0,"price":500,"item_type":0,"attack_power":14,"critical_attack_power":14,"critical_chance":14,"speed_of_attack":14,"item_grade":4,"weapon_type":2},
  {"raw":1015,"item_name":"성수1","item_description":"흔한 성수","kind_of_money":0,"price":100,"item_type":0,"attack_power":10,"critical_attack_power":10,"critical_chance":10,"speed_of_attack":10,"item_grade":0,"weapon_type":3},
  {"raw":1016,"item_name":"성수2","item_description":"안흔한 성수","kind_of_money":0,"price":200,"item_type":0,"attack_power":11,"critical_attack_power":11,"critical_chance":11,"speed_of_attack":11,"item_grade":1,"weapon_type":3},
  {"raw":1017,"item_name":"성수3","item_description":"희귀 성수","kind_of_money":0,"price":300,"item_type":0,"attack_power":12,"critical_attack_power":12,"critical_chance":12,"speed_of_attack":12,"item_grade":2,"weapon_type":3},
  {"raw":1018,"item_name":"성수4","item_description":"고유 성수","kind_of_money":0,"price":400,"item_type":0,"attack_power":13,"critical_attack_power":13,"critical_chance":13,"speed_of_attack":13,"item_grade":3,"weapon_type":3},
  {"raw":1019,"item_name":"성수5","item_description":"전설 성수","kind_of_money":0,"price":500,"item_type":0,"attack_power":14,"critical_attack_power":14,"critical_chance":14,"speed_of_attack":14,"item_grade":4,"weapon_type":3},
  {"raw":1020,"item_name":"검1","item_description":"흔한 검","kind_of_money":0,"price":100,"item_type":0,"attack_power":10,"critical_attack_power":10,"critical_chance":10,"speed_of_attack":10,"item_grade":0,"weapon_type":4},
  {"raw":1021,"item_name":"검2","item_description":"안흔한 검","kind_of_money":0,"price":200,"item_type":0,"attack_power":11,"critical_attack_power":11,"critical_chance":11,"speed_of_attack":11,"item_grade":1,"weapon_type":4},
  {"raw":1022,"item_name":"검3","item_description":"희귀 검","kind_of_money":0,"price":300,"item_type":0,"attack_power":12,"critical_attack_power":12,"critical_chance":12,"speed_of_attack":12,"item_grade":2,"weapon_type":4},
  {"raw":1023,"item_name":"검4","item_description":"고유 검","kind_of_money":0,"price":400,"item_type":0,"attack_power":13,"critical_attack_power":13,"critical_chance":13,"speed_of_attack":13,"item_grade":3,"weapon_type":4},
  {"raw":1024,"item_name":"검5","item_description":"전설 검","kind_of_money":0,"price":500,"item_type":0,"attack_power":14,"critical_attack_power":14,"critical_chance":14,"speed_of_attack":14,"item_grade":4,"weapon_type":4}]

 

파싱클래스

RawData.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RawData
{
    public string raw;
}

 

JsonItem.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class JsonItem : RawData
{
    public string item_name;
    public string item_description;
    public int kind_of_money;
    public int price;
    public int item_type;
}

public class JsonWeapon : JsonItem
{
    public float attack_power;
    public float critical_attack_power;
    public float critical_chance;
    public float speed_of_attack;
    public int item_grade;
    public int weapon_type;
}


public class JsonShopWeaponGradePercentage : RawData
{
    public int grade;
    public string grade_name;
    public float percentage;
}

 

2. json파일을 읽고 메모리상에 가지고 있을 데이터 매니저 제작

DataManager.cs

using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class DataManager
{
    public static readonly DataManager Instance = new DataManager();
    private List<RawData> list = new List<RawData>();

    public void LoadData<T>(string path) where T : RawData
    {
        var json = this.ReadFile(path).text;
        var arr = JsonConvert.DeserializeObject<T[]>(json);
        if (arr != null)
        {
            this.list.AddRange(arr);
        }
    }
    private TextAsset ReadFile(string path)
    {
        var json = Resources.Load<TextAsset>(path);
        return json;
    }


    public IEnumerable<T> GetDatas<T>()
    {
        return this.list.OfType<T>();
    }

    public T GetData<T>(string id) where T : RawData
    {
        var data = this.list.FindAll(x => x != null && x.GetType().Equals(typeof(T)));

        foreach (RawData rawData in data)
        {
            if (rawData.raw == id)
            {
                return (T)rawData;
            }
        }
        return null;
    }
}

 

3. 게임 시작 시 DataManager의 list에 json데이터를 추가

App.cs

    public void LoadJsonData()
    {
        DataManager.Instance.LoadData<JsonWeapon>("JsonData/item_weapon");        
        DataManager.Instance.LoadData<JsonShopWeaponGradePercentage>("JsonData/shop_weapon_grade_percentage");
    }

 

4. 로비에서 상점목록 로드

Lobby.cs

public void ShopLoading()
    {
        var prefab = Resources.Load<GameObject>("Prefabs/shopItem");

        var percentages = DataManager.Instance.GetDatas<JsonShopWeaponGradePercentage>();
        List<float> listPercentages = new List<float>();
        foreach(var per in percentages)
        {
            listPercentages.Add(per.percentage);
        }

        //6개 아이템만 표시
        for (int i = 0; i < 6; i++)
        {
            var go = Instantiate(prefab);
            var shopItem = go.GetComponent<ShopItem>();
            //데이터 매니저에서JsonWeapon타입만 취득
            var listWeaponItems = DataManager.Instance.GetDatas<JsonWeapon>();
            //shop_weapon_grade_percentage.json파일의 확률을 적용
            var grade = Choose(listPercentages.ToArray());
            //무기 종류가 5개이므로 동일한 확률로 랜덤 적용
            var weaponType = Random.Range(0, 5);


            foreach(var item in listWeaponItems)
            {
                if(item.item_grade == grade && item.weapon_type == weaponType)
                {
                    shopItem.Init(item);
                    shopItem.transform.SetParent(shopWeapon.transform);
                    break;
                }
            }
            
        }

       
    }

    public float Choose(float[] probs)
    {

        float total = 0;

        foreach (float elem in probs)
        {
            total += elem;
        }

        float randomPoint = Random.value * total;

        for (int i = 0; i < probs.Length; i++)
        {
            if (randomPoint < probs[i])
            {
                return i;
            }
            else
            {
                randomPoint -= probs[i];
            }
        }
        return probs.Length - 1;
    }

 

 

 

확률이 다른 항목 선택 참고

https://docs.unity3d.com/kr/2019.4/Manual/RandomNumbers.html

 

랜덤 게임플레이 요소 추가 - Unity 매뉴얼

여러 게임에서 임의로 선택되는 항목 및 값은 중요합니다. 이 섹션에서는 Unity에 내장된 랜덤 함수를 사용하여 일반적인 게임 역학을 구현하는 방법에 대해 알아봅니다.

docs.unity3d.com