ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL] 제작 관련 기능을 만들기 2
    TIL 2024. 6. 4. 21:56

    원래 딕셔너리를 쓰려다가 Insepctor 창에서 안뜬다는거 

    왜 기존 유니티 자체가 딕셔너리는 창에 안띄어주는지는 찾아내지 못했다.

     

    그러나 유니티 에셋스토어에 가면 딕셔너리를 Serialized해주는 에셋이있다.(무료)

    https://assetstore.unity.com/packages/tools/utilities/serialized-dictionary-243052

     

    Serialized Dictionary | 유틸리티 도구 | Unity Asset Store

    Use the Serialized Dictionary from ayellowpaper on your next project. Find this utility tool & more on the Unity Asset Store.

    assetstore.unity.com

     

    그러나 내가 생각하기에는 딕셔너리를 그렇게 많이 쓸것 같기도 하고

    팀 프로젝트인 만큼 팀원들과의 아무런 상의 없이 외부 에셋을 다운로드받아서 쓰는것도

    혹시 문제 생길까봐 걱정이 되어서

     

    딕셔너리를 사용하기 위해 에셋을 쓰는것 보다는 방식을 다르게 생각하여 구조체 배열을 선언해 줘서 Inspector 상에서 보여주게 했다.

    using UnityEngine;
    using System;
    
    [Serializable]//Inspector 상에서 보이고 싶다면 꼭 붙여야한다.
    public struct ResourceRequire
    {
        public ItemData resource;
        public int count;
    }
    
    [CreateAssetMenu(fileName ="Recipe", menuName ="New Recipe")]
    public class RecipeData : ItemData
    {
        [Header("ResourceRequire")]
        public ResourceRequire[] resources; 
        
    }

     

    이런 식으로 구조체를 선언하고 public 으로 선언한 구조체를 배열로 선언하게 되면

     

    원하던 정보를 저장할 수 있었다.

    원래 딕셔너리를 사용하려던 이유가 유형이 다른 두가지의 정보를 저장하고 싶었기에 구조체를 사용해서 문제를 해결할 수 있었지만, 나같은 이유가 아닌 딕셔너리만의 다른 특징이 필요한다던가 

     

    아니면 이렇게 정보를 저장해서 쓸 일이 많은데 유형이 각각 달라서 구조체를 여러개 생성해야한다면 다시 한번 어떤 방식이 효율적일지 고민해봐야할 것 같다.

     

    필요한 자원이 있는지 확인하기

    기존에 있던 Inveontory를 기반으로 추가 코드를 작성했기 때문에 정보를 받아올 때 몇가지 애를 먹었다.

     

    UICraft.cs

     public void SelectRecipe(RecipeData data)
    {
        selectedRecipe = data;
        selectImage.sprite=data.icon;
        selectedRecipeName.text = selectedRecipe.displayName;
        selectedRecipeDescription.text = selectedRecipe.description;
        selectedRecipeCount.text= string.Empty;
    
    
        for(int i=0; i<selectedRecipe.resources.Count();i++)
        {
            int _resource =0;
    
            for(int j=0; j<inventory.slots.Length;j++)//인벤토리에 해당되는 재료가 있는지 확인
            {
                if(selectedRecipe.resources[i].resource==inventory.slots[j].item)
                {
                    _resource=inventory.slots[j].quantity;
                }
            }
            selectedRecipeCount.text += $"{selectedRecipe.resources[i].resource.displayName}  {_resource} / {selectedRecipe.resources[i].count}\n";  
    
        }
    
        craftButton.SetActive(true);
    }

     

    우선 기존 인벤토리에 아이템 칸이 몇 개 까지 차있는지 알 수 있는 기능이 없었다.

    만들려면 만들수야 있겠지만 팀플인 만큼 함부로 기존에 있던 코드를 건들였다가 깃허브에 Conflict가 날까봐 건들지 않았다.

     

    아무튼 몇개 까지 차있는지 알 수 없었기 때문에 슬롯이 비어있어도 처음부터 끝까지 for문으로 훑어보고 원하는 자원을 찾아야 했다.

     

    아무튼 이제 옆에 제작법을 선택하면 이름, 제작할 때 필요한 자원의 개수와 현재 보유한 수 그리고 아이템 설명이 뜬다.

     

     

    제작해서 아이템 인벤토리에 추가하기

     

    이 코드 또한 아쉬움이 가득한데 제작법을 선택했을때 굴리는 반복문이랑 구조가 유사하다

    코드 중복이 많기도하고 반복문도 이중이라 어떻게든 최적화 시켜주고 싶었는데 할 일이 많아서 잠깐 내버려 두기로했다......

     

    UICraft.cs

        public void OnCraftButton()
        {
            int[] _currentResource = new int[selectedRecipe.resources.Count()];
    
            if(inventory.CheckInventoryNull()) return;
    
            for( int i=0; i<selectedRecipe.resources.Count();i++)
            {
    
                for(int j=0; j<inventory.slots.Length;j++)//인벤토리에 해당되는 재료가 있는지 확인
                {
                    if(selectedRecipe.resources[i].resource==inventory.slots[j].item)
                    {
                        if(inventory.slots[j].quantity<selectedRecipe.resources[i].count)
                        {
                            Debug.Log("재료 부족");//경구 문구 넣을까 말까
                            return;
                        }
                        _currentResource[i] = j;
                        break;
                    }
    
                    if(j==inventory.slots.Length-1)
                    {
                        Debug.Log("재료 없음"); 
                        return;
                    }
                }
    
            }
    
            //재료 차감
            selectedRecipeCount.text= string.Empty;
    
            for(int i =0 ; i < selectedRecipe.resources.Count(); i++)
            {
                inventory.slots[ _currentResource[i]].quantity -= selectedRecipe.resources[i].count;
    
                if(inventory.slots[ _currentResource[i]].quantity==0) inventory.slots[ _currentResource[i]].Clear();
                else inventory.slots[ _currentResource[i]].Set();
                
                selectedRecipeCount.text+= $"{selectedRecipe.resources[i].resource.displayName}  {inventory.slots[ _currentResource[i]].quantity} / {selectedRecipe.resources[i].count}\n";  
            }
    
            CharacterManager.Instance.Player.itemData=selectedRecipe;
            CharacterManager.Instance.Player.addItem?.Invoke();
            
    
            
        }

     

     

     

    구현은 잘되긴 하지만 역시 UI가 너무 안예쁘다. 여유가 되면 고쳐야할 것 같다.

     

    다음날에는 상호작용하면 해당 UI를 띄어줄 제작대를 만들고 

    다음 작업으로 플레이어 온도에 따른 상호작용을 구현해보기로 했다...

     

    'TIL' 카테고리의 다른 글

    [TIL] 자료구조  (1) 2024.06.08
    [TIL] C# Generic  (0) 2024.06.05
    [TIL] 제작 관련 기능을 만들기 1  (1) 2024.06.03
    [TIL] 게임에서 데이터 저장하기(직렬화, 역직렬화)  (0) 2024.05.31
    [TIL] 3D 프로젝트 정리  (1) 2024.05.30
Designed by Tistory.