본문 바로가기

유니티 스파르타 캠프 2주차

개인 과제 개발일지 ver.6

🔴 오늘의 내용  .

  1. 일정과 바뀐 내용  .
  2. 튜터 님의 강의(메서드)  .
  3. 개인 과제 (ver 6)  .
  4. 후기 및 내일 일정  .

1) 일정과 바뀐 내용  .

어제 계획했던 일정과는 상당히 다르게 진도를 많이 나가지 못했습니다. 최대한 열심히 했음에도 불구하고 코드를 이쁘게 고치는 것이 시간이 생각보다 오래 걸렸습니다. 그리고 외에도 과제에 필요한 기능은 다 작성하고 수정중인줄 알았으나, 데일리스크럼이라고 하여 같이 교육받는 팀원들과 얘기하는 내용을 듣고 기능 몇 개를 빼먹은 것을 확인하여 오늘 추가했습니다.

 

2) 튜터 님의 강의(메서드)  .

오늘의 강의 내용은 함수,(메서드)와 관련된 내용이었습니다. 크게 배울 내용 2가지를 골라보겠습니다.

  • ref와 out
  • 오버로딩

2)-1. ref와 out  .

이전에도 내용이 어려워서 한번 다뤘던 내용입니다. 본래 매개변수로 전달한 값은 참조형이든 값형이든, 그 값이 변한다고 하여 전달했던 본래 값이 변하진 않습니다. 그러나 ref와 out으로 보낸 값은 return을 받지 않아도 값을 변화시킬 수 있습니다. 아래에는 제가 사용한 예제코드입니다.

 switch (place)
 {
     case PlaceType.Village:
         village.StartVillage(out place, ref user);
         break;

     case PlaceType.Status:
         status.StartStatus(out place, ref user);
         //Status();

         break;
     case PlaceType.Shop:
         shop.StartShop(out place, ref user);
         //Shop();

         break;

     case PlaceType.Inventory:
         //Inventory();

         break;
     case PlaceType.Rest:
         //Rest();

         break;
     case PlaceType.Dungeon:
         //Dungeon();
         break;
 }

이 코드는 받은 값에 맞는 장소를 찾아서 그 장소에서의 함수를 실행하고 또 그 함수에 place와 user값을 주어 필요한 코드에 사용하고 그 사용된 값이 변했을 경우에도 다시 받아와서 적용한다라는 뜻입니다.

 

2)-2. 오버로딩 

오버로딩은 쉽게 같은 이름의 함수를 다른 매개변수로 받아서 사용하는 것입니다. 

public Item()
{
    itemName = (string)this.itemName;
    itemStatType = (StatType)this.itemStatType;
    itemType = (ItemType)this.itemType;
    stat = (int)this.stat;
    itemHistory = (string)this.itemHistory;
    price = (int)this.price;
    isEquip = (bool)this.isEquip;
}

public Item(Item item)
{
    itemName = (string)item.itemName;
    itemStatType = (StatType)item.itemStatType;
    itemType = (ItemType)item.itemType;
    stat = (int)item.stat;
    itemHistory = (string)item.itemHistory;
    price = (int)item.price;
    isEquip = (bool)item.isEquip;
}

public Item(string newItemName, ItemType newItemType, StatType newItemStatType, int newStat, string newItemHistory, int newprice)
{
    itemName = newItemName;
    itemType = newItemType;
    itemStatType = newItemStatType;
    stat = newStat;
    itemHistory = newItemHistory;
    price = newprice;
}

Item으로 선언된 함수 밖에 없어서 처음 보면 잘못된 코드 아닌가 싶지만 틀린 코드가 아닙니다. 위에서부터 설명을 드리자면, Item()으로 선언 시에는 기본 값을 받아오는 것이고, Item(Item item)는 어떤 아이템 값을 넣어서 생성할 때 쓰이는 코드고,
Item(~~) 코드는 자세히 보시면 isEquip 값이 없습니다. 장비를 처음 가져올 때, 당연히 착용하지 않은 장비일테니 초기 값을 False로 주고 장비를 생성할 때 쓰이는 코드입니다. 이런 식으로 같은 함수도 주는 매개변수에 따라 변화하는 개념을 오버로딩이라 합니다.

 

3) 개인 과제 Ver.6

오늘 개인 과제는 2가지로 설명이 가능합니다.

  • 클래스 분할, 메서드 다양화
  • 게임 내 데이터 저장 기능

 

3)-1 클래스 분할, 메서드 다양화

public void Show()
{
    Console.WriteLine("[[스파르타 마을]]에 오신 여러분 환영합니다.");
    Console.WriteLine("이곳에서 던전으로 들어가기전 활동을 할수 있습니다.");
    Console.Write("\n");
}

public void Section()
{
    Console.WriteLine("1. [상태 보기]");
    Console.WriteLine("2. [인벤토리]");
    Console.WriteLine("3. [상점]");
    Console.WriteLine("4. [휴식처]");
    Console.WriteLine("5. [던전 입장]");
    Console.Write("\n");
}

public void Select(out PlaceType place)
{
    Console.WriteLine("원하시는 행동을 입력해주세요.");
    int check = 0;

    while (true)
    {
        Console.Write(">> ");
        check = int.Parse(Console.ReadLine());

        switch (check)
        {
            case 1:
                Console.WriteLine(">> [상태보기]를 선택하셨습니다.");
                Console.Write("\n");

                place = PlaceType.Status;
                return;

            case 2:
                Console.WriteLine(">> [인벤토리]를 선택하셨습니다.");
                Console.Write("\n");

                place = PlaceType.Inventory;
                return;

            case 3:
                Console.WriteLine(">> [상점]을 선택하셨습니다.");
                Console.Write("\n");

                place = PlaceType.Shop;
                return;

            case 4:
                Console.WriteLine(">> [휴식처]을 선택하셨습니다.");
                Console.Write("\n");

                place = PlaceType.Rest;
                return;
            case 5:
                Console.WriteLine(">> [던전입장]을 선택하셨습니다.");
                Console.Write("\n");

                place = PlaceType.Dungeon;
                return;

            default:
                Console.WriteLine("값을 다시 입력해주십시오");
                continue;
        }
    }
}

기존에 있던 하나의 함수 내에서 진행되던 코드를 클래스라는 더 넓은 의미의 코드로 빼내서 파트별로 함수를 나눈 것입니다. 크게 바뀐 것이라고 할만한 것은 아니지만, 파트 별로 나눔으로써 비슷한 느낌의 스크립트들도 양식을 만들 수가 있어서 편했습니다. 지금 다시금 드는 생각이지만, 대부분의 양식이 비슷하기에 interface 클래스를 활용하여 Show, Section, Select의 부문으로 나눌 수도 있을 거 같습니다.

또한 기존에는 클래스를 나누는 방법을 몰라 한 클래스에서 모든 작업을 통해 600줄, 800줄이 한 클래스에 잡혔었는데 분할을 통해 코드가 길어야 150줄 이내에 끝내도록 할 수 있었습니다. 실제로 보면 코드의 양은 더 많아진 것이지만, 유지 보수 및 가독성 측면에서 더 좋아졌다고 생각합니다. 

 

3.2 게임 내 데이터 저장 기능

오늘 약 2시간을 잡아먹은 귀신입니다. 실제로는 그닥 어려운 코드가 아니였지만 재밌는 2가지 이유가 있었습니다.

문제 1: 데이터가 저장이 되지 않았습니다.

해결방법 : Json을 활용한 데이터 저장방법을 사용하고자 했는데 대부분의 예제들이 int, string만을 사용하는 예제들이 많아 저장되지 않는 이유가 클래스에 있다고 판단했습니다. 그렇기에 제가 선택한 방법은 클래스에 있는 내용 중 int와 string의 부분만을 하나하나 다 저장하는 방법을 활용했고 결과적으로는 저장이 되었습니다.  모르겠으면 일단 기능이라도 성공시키십쇼.

문제 2: 데이터가 저장과 불러오기 과정에서 문제가 없다고 진행되었지만, 값이 변질되었습니다.

해결방법 : 아직도 살짝 어리둥절한 느낌인데 프로퍼티의 문제였습니다. 프로퍼티의 경우, get, set을 설정하지 않으면 기존 메서드 앞에 붙는 접근 제한자가 제한 범위를 정하는 줄 알았는데, get이나 set 둘 중 하나라도 작성을 할 경우에 나머지 하나는 private 또는 protected와 같이 접근 제한이 됩니다... 코드를 하나씩 써보는 느낌으로 작성하면서 프로퍼티를 한 두개씩 작성을 하지 않았던 거 같은데 그걸로 인해 데이터가 제대로 저장과 불러오기가 진행되지 않았던 겁니다. 프로퍼티를 수정하니 List도 제대로 작동이 되었습니다. 

static void SaveData(ref GameLogic gameLogic)
{
    string FilePath = "./ItemData.json"; // 파일경로설정
    string FilePathPlayer = "./PlayerData.json";
    Console.WriteLine($"{FilePath}에 저장됨");
    try
    {
        var testList = new List<Item>();
        for(int i=0; i<gameLogic.user.inventory.Item.Count; i++)
        {
            testList.Add(new Item(gameLogic.user.inventory.Item[i]));
        }
        var jsonSerializeList = JsonConvert.SerializeObject(testList);
        var testListPlayer = new Player
        {
            name = gameLogic.user.name,
            job = gameLogic.user.job,
            level = gameLogic.user.level,
            exp = gameLogic.user.exp,
            curHp = gameLogic.user.curHp,
            curAtk = gameLogic.user.curAtk,
            curDef = gameLogic.user.curDef,
            maxHp = gameLogic.user.maxHp,
            maxAtk = gameLogic.user.maxAtk,
            maxDef = gameLogic.user.maxDef,
            haveGold = gameLogic.user.haveGold
        };
        var jsonSerializeListPlayer = JsonConvert.SerializeObject(testListPlayer);
        //string json = JsonConvert.SerializeObject(player, Newtonsoft.Json.Formatting.Indented);
        File.WriteAllText(FilePathPlayer, jsonSerializeListPlayer);
        File.WriteAllText(FilePath, jsonSerializeList);
        
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error saving data: {ex.Message}");
    }
}

static void LoadData(ref GameLogic gameLogic)
{
    string FilePath = "./ItemData.json";
    string FilePathPlayer = "./PlayerData.json"; // 데이터 저장한 파일 경로 설정
    Console.WriteLine($"{FilePath}에서 불러오기 시도");
    try
    {
        if (File.Exists(FilePath))
        {
            string json = File.ReadAllText(FilePath);
            string json2 = File.ReadAllText(FilePathPlayer);
            List<Item> jsonDeserializeList = JsonConvert.DeserializeObject<List<Item>>(json);
            var jsonDeserializeList2 = JsonConvert.DeserializeObject<Player>(json2);

            gameLogic.user = jsonDeserializeList2;
            for (int i = 0; i < jsonDeserializeList.Count; i++)
            {
                gameLogic.user.inventory.Item.Add(new Item(jsonDeserializeList[i]));
            }
            
        }
        else
        {
            // 파일 미 존재 시 기본 데이터 설정
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error Load data: {ex.Message}");
        // JsonConver 오류 발생 시 기본 데이터 설정 
    }
}

 

4) 후기 및 다음 일정

오늘은 아쉽게도 내용이 그리 많지 않습니다. 코드를 정리하는데 생각보다도 시간을 많이 할애했고 또한 생각하는 시간도 길었습니다. 어떻게보면, 저는 기획보다도 개발을 먼저 했기에 기능적으로는 완성이 되었을지언정 게임을 만드는 면에서는 엇나가고 있었던 것이라고 볼 수도 있을 거 같습니다. 

다음은 개인 과제의 제출의 날입니다. 오늘 작성한 코드를 마무리짓고 시간이 남는다면 코드 기능은 추후 피드백을 주신다고 하여, 게임답게 좀 디자인을 신경써볼 생각입니다. 외에도 현재는 던전에 들어가면 바로 클리어되는 기능인데 시간이 남는다면 간단한 전투라도 구현해볼 수 있을 거 같습니다.