Chapter 11-3. 포션 제조 : 포션 제조 대기열, 독립적인 쿨타임

Date:     Updated:

카테고리:

태그:

인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

포션 제조 : 포션 제조 대기열

image

이렇게 CREATE 버튼을 누르면 해당 포션이 밑에 대기열에 올라오게 되며, 생성이 다 될때까지의 게이지를 보여주는 슬라이더가 활성화된다. 포션 생성이 완료되면 포션 아이템이 생성되고 대기열은 한 자리씩 앞으로 땡겨오게 된다. 이미 포션 제작 중인게 있으면 생성할 포션은 대기열 뒤에 자리잡게 된다. 그냥 Queue 큐와 똑같은 원리!

🚀 포션 제조 대기열 UI

슬라이더

image

포션이 제작 중일 때의 쿨타임을 슬라이더로 표시할 것이다. 슬라이더 UI 처음 만들 떄 생기는 동그란 손잡이 부분이 Handle Slide Area인데 이 부분은 미관을 위해 없애주었다.

image

슬라이더의 value가 100% 채워져도 오른쪽에 이렇게 공간이 남는 이유는 Fill Area의 Right 패딩값 때문이다. 슬라이더가 채워지는 그 오브젝트는 Fill Area의 자식인 Fill인데, Fill Area의 Rect Transform 에서 Right 패딩값이 커서 생기는 문제였다.

image

Fill Area의 Right 패딩 값을 줄여주니 해결 됨.

슬라이더는 포션 제조중일 때만 활성화할 것이라서 평소엔 비활성화 해둔다.

대기열 큐

image

  • 빈 오브젝트 Queue
    • 대기열 큐의 4 개의 자리를 의미하는 각각의 4 개 이미지

image

슬라이더와 4 개의 대기열 이미지는 평소 비활성화. 포션이 제조 중일 때만 활성화할 것이다.


🚀 포션 제조 대기열 동작시키기

📜ArchemyTable

    private bool isOpen = false;
    private bool isCrafting = false; // 아이템의 제작 시작 여부 (ture면 제작 中)

    private Queue<ArchemyItem> archemyItemQueue = new Queue<ArchemyItem>(); // 연금 테이블 아이템 제작 대기열 큐
    private ArchemyItem currentCraftingItem;  // 현재 제작 중인 연금 아이템(큐의 첫 번째 원소)

    private float craftingTime;  // 제작 시간
    private float currentCraftingTime; // 실제 갱신되는 시간. craftingTime 가 되기까지 갱신됨

    [SerializeField] private Slider slider_gauge; // 슬라이더 게이지
    [SerializeField] private GameObject go_Liquid; // 동작 시키면 액체 등장(포션 제작 중이면 등장)
    [SerializeField] private Image[] image_CraftingItems; // 대기열 슬롯에 있는 아이템 이미지들
    [SerializeField] private Transform tf_BaseUI; // 연금 아이템 베이스 UI
    [SerializeField] private Transform tf_PotionAppearPos; // 포션이 생성될 위치
  • 실제 대기 큐 👉 크기 3 을 넘지 않게 할 것이다.
  • UI 이미지로서의 대기 큐 👉 4 개의 이미지를 사용하지만 가장 왼쪽 하나는 현재 제작 중인 포션의 이미지를 나타낼 것이고 나머지 3 개는 현재 큐의 원소로 있는 대기 중인 포션들로 쓸 것이다.

image

go_Liquid의 경우 이것이다. 포션이 제조중이면 연금 테이블 위에 있는 이 go_Liquid 액체 오브젝트가 활성화 되게 할 것이고 포션 제조 중이 아니면 비활성화 해 빈 액체인 상태로 보이게 하는 효과를 줄 것이다. 평소엔 비활성화.

    void Update()
    {
        if (!isFinish())
        {
            Crafting();
        }
        if (isOpen)
            if (Input.GetKeyDown(KeyCode.Escape))
                CloseWindow();
    }

    private bool isFinish()
    {
        if(archemyItemQueue.Count == 0 && !isCrafting)
        {
            go_Liquid.SetActive(false);
            slider_gauge.gameObject.SetActive(false);
            return true;
        }
        else
        {
            go_Liquid.SetActive(true);
            slider_gauge.gameObject.SetActive(true);
            return false;
        }
    }

    private void Crafting()
    {
        if (!isCrafting && archemyItemQueue.Count != 0)
            DequeueItem();

        if (isCrafting) // DequeItem 을 통해 isCrafting = true 즉 제작 중이된 후
        {
            currentCraftingTime += Time.deltaTime;
            slider_gauge.value = currentCraftingTime;

            if (currentCraftingTime >= craftingTime)
                ProductionComplete();
        }
    }

    private void DequeueItem()
    {
        isCrafting = true; // 대기열에서 뺏으니 제작 시작
        currentCraftingItem = archemyItemQueue.Dequeue();

        craftingTime = currentCraftingItem.itemCraftingTime;
        currentCraftingTime = 0;
        slider_gauge.maxValue = craftingTime;

        CraftingImageChange();
    }

    private void CraftingImageChange()
    {
        image_CraftingItems[0].gameObject.SetActive(true); // 첫 번재 대기열 이미지는 무조건 보여져야 함. 제작 중이니까

        for (int i = 0; i < archemyItemQueue.Count + 1; i++) // 이미지는 그대로 남아있으니까 +1 (위에서 Dequeue 하기 전 상태)
        {
            image_CraftingItems[i].sprite = image_CraftingItems[i + 1].sprite;  // 이미지 하나씩 땡겨오기
            
            if (i + 1 == archemyItemQueue.Count + 1)
                image_CraftingItems[i + 1].gameObject.SetActive(false);
        }
    }

    public void Buttonclick(int _buttonNum)
    {
        if (archemyItemQueue.Count < 3)
        {
            archemyItemQueue.Enqueue(archemyItems[_buttonNum]);
            
            image_CraftingItems[archemyItemQueue.Count].gameObject.SetActive(true);
            image_CraftingItems[archemyItemQueue.Count].sprite = archemyItems[_buttonNum].itemImage;
        }
    }

    private void ProductionComplete()
    {
        isCrafting = false;
        image_CraftingItems[0].gameObject.SetActive(false);

        Instantiate(currentCraftingItem.go_ItemPrefab, tf_PotionAppearPos.position, Quaternion.identity);
    }

    public bool GetIsOpen()
    {
        return isOpen;
    }
  • Update
    • !isFinish() 제조해야할 포션이 하나라도 있을 때만 Crafting() 포션을 제작한다.
  • isFinish
    • 포션 제조 대기열 큐에 아무것도 없고 현재 제작중도 아니라면 더 이상 포션 제조 안해도 되므로, 즉 연금테이블이 할 일은 다 끝났으므로 ture를 리턴한다. 액체도 비활하고 슬라이더도 비활하고!
    • 포션 제조 대기열 큐에 하나라도 있거나 현재 제작중이라면 포션 제조를 해야 한다. false를 리턴해서 업데이트 문에서 Crafting() 될 수 있도록 한다. 액체와 슬라이더를 활성화한다.
  • Crafting
    • 현재 제조 중인건 아닌데 and 대기열 큐에 있는 포션 갯수가 0 이 아니라면
      • 👉 다음 포션 아이템을 제조해야 하므로 대기 큐에 있는 포션들 한 칸씩 땡겨야 한다. DequeueItem()
    • 현재 제조 중이라면
      • (DequeueItem() 끝나서 한 칸씩 땡겨오기 완료 하고 지금 제작해야 할 포션의 제작 시간도 craftingTime에 저장이 된 상태고 isCrafting = true 된 후임)
      • 👉 제조 시작! 포션 쿨타임 돌려야 함
        • currentCraftingTime을 1 프레임씩 업데이트. 시간 갱신.
        • 슬라이더 게이지 업데이트
        • 시간이 craftingTime에 다다랐다면 포션 아이템 오브젝트를 생성해야 한다. ProductionComplete()
  • DequeueItem
    • 다음 포션 아이템을 제조해야 하므로 대기 큐에 있는 포션들 한 칸씩 땡긴다. 그리고나서 이제 제작해야할 포션 아이템 데이터를 받아 온다.
      • isCrafting = true (이제 제작 시작)
      • 이제 제작해야할 포션 아이템의 데이터를 받아온다.
        • currentCraftingItem 이제 제작 해야할 아이템 (대기 큐에서 Dequeue())
        • craftingTime 이제 제작 해야할 아이템의 총 쿨타임
        • currentCraftingTime 이제 시간 갱신해야 하므로 0 으로 초기화
        • 슬라이더의 최대 값은 craftingTime
      • 대기열 큐의 이미지를 한 칸씩 땡겨와야 한다.
        • 👉 CraftingImageChange
  • CraftingImageChange
    • 대기열 큐의 이미지를 한 칸씩 앞으로 땡겨 온다. 현재 대기열에 있는 아이템이 2 개라면 대기열 이미지 4개 중 3개만 활성화 해야 한다.(나머지 하나는 현재 제작중인 이미지)
      • 첫 번째 이미지는 무조건 보여져야 한다. 제작 중인 이미지를 나타내므로!
      • C# 상에서의 대기열 Queue 에선 아이템을 뺏지만 UI 이미지 상으로는 아직 안뺏다! 그러므로 for문을 archemyItemQueue.Count + 1 전 까지 돌아야 한다. 그러면서 이미지 하나씩 한칸 앞으로 땡겨오기
      • Dequeue 되어 1 줄은 맨 뒷자리 이미지는 비활성화 한다.
  • Buttonclick
    • 포션 아이템은 대기열 큐 크기가 3 미만인 경우에만 생성되야 한다. 따라서 3 을 넘으면 CREATE 버튼을 눌러도 아무 반응이 없도록!!
      • 대기열 큐 크기가 3 미만이면 큐에 해당 포션 아이템을 삽입한다.
      • 삽입한 아이템이 자리하는 그 자리의 이미지를 활성화하고 Sprite 도 할당해준다.
  • ProductionComplete
    • 제작이 끝났으니 포션 프리팹으로 포션 아이템을 생성한다.
      • isCrafting = false
      • 첫 번째 이미지 비활성화 (제작 중임을 나타내는 이미지)
      • 포션 생성

image

  • 빨간 포션의 제작 시간은 4 초
  • 4 개의 이미지를 iamge_CraftingItems에 할당


📜ActionController

    private void ArchemyInfoAppear()
    {
        if (!hitInfo.transform.GetComponent<ArchemyTable>().GetIsOpen())
        {
            Reset();
            lookArchemyTable = true;
            actionText.gameObject.SetActive(true);
            actionText.text = "연금 테이블 조작 " + "<color=yellow>" + "(E)" + "</color>";
        }
    }

액션 텍스트가 계속 보여서 포션 제작 UI 가 떠 있을 땐 액션텍스트가 보이지 않도록 수정



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 3 카테고리 내 다른 글 보러가기

댓글 남기기