반응형
SMALL
이번에 제작한 상자 아이템 구조에 대한 개인 적인 정리 글이다.
우선 EventDispathcer를 사용하여 메서드를 등록시키는 것으로 시작하여 특정 객체 (상자 또는 인벤토리 등) 가 해당 메서드를 DIspatch하는 단순한 구조로 제작을 해보았다.
우선 코드는 아래와 같다.
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
public class ChestItemGenerator : MonoBehaviour
{
[SerializeField] private GameObject WoodChest;
[SerializeField] private GameObject IronChest;
[SerializeField] private GameObject GoldChest;
[SerializeField] private GameObject DiamondChest;
public void Init()
{
EventDispatcher.Instance.AddListener<Transform, bool>(EventDispatcher.EventName.ChestItemGeneratorMakeChest,
this.MakeChset);
EventDispatcher.Instance.AddListener<Transform, string>(EventDispatcher.EventName.ChestItemGeneratorMakeItemForChest,
this.MakeItemForChest);
EventDispatcher.Instance.AddListener<string>(EventDispatcher.EventName.ChestItemGeneratorMakeItemForInventory,
this.MakeItemForInventory);
}
/// <summary>
/// 체스트를 생성합니다. ( 보스일경우 2번째 인자값 true)
/// </summary>
/// <param name="callPosition"> 상자 생성 위치</param>
/// <param name="isBoss">보스방 상자 인지 아닌지</param>
private void MakeChset(Transform callPosition , bool isBoss = false)
{
Debug.Log("맵이 상자 만들어 달래");
Debug.LogFormat("위치 : {0} , 보스방? : {1}", callPosition.position, isBoss);
var setp = InfoManager.instance.dungeonInfo.currentStepInfo;
if (!isBoss)
{
if (setp < 4)
{
var go = GameObject.Instantiate(this.WoodChest, callPosition);
go.name = go.name.Replace("(Clone)","");
go.transform.localPosition = Vector2.zero;
}
else if (setp > 3 && setp < 10)
{
var go = GameObject.Instantiate(this.IronChest, callPosition);
go.name = go.name.Replace("(Clone)","");
go.transform.localPosition = Vector2.zero;
}
else if (setp > 9)
{
var go = GameObject.Instantiate(this.GoldChest, callPosition);
go.name = go.name.Replace("(Clone)","");
go.transform.localPosition = Vector2.zero;
}
}
else
{
var go = GameObject.Instantiate(this.DiamondChest, callPosition);
go.name = go.name.Replace("(Clone)","");
go.transform.localPosition = Vector2.zero;
}
}
/// <summary>
/// 상자의 콜에 의해 아이템을 생성합니다.
/// </summary>
/// <param name="callPosition">상자의 위치</param>
/// <param name="chestName">상자의 이름 (예 : Wood_Chest)</param>
private void MakeItemForChest(Transform callPosition, string chestName)
{
Debug.Log("상자가 아이템 만들래");
Debug.LogFormat("포지션 : {0} , 이름 : {1}", callPosition.position, chestName);
if(chestName == "Wood_Chest")
{
//아이템을 만든다
}
}
/// <summary>
/// 인벤토리에서 버려진 아이템을 필드에 생성합니다.
/// </summary>
/// <param name="discaredItemName">인벤토리에서 버려진 아이템의 이름</param>
private void MakeItemForInventory(string discaredItemName)
{
Debug.Log("인벤토리가 아이템 만들래");
Debug.LogFormat("버린 이름 : {0}", discaredItemName);
var playerPos = GameObject.FindWithTag("Player").transform.position;
// 아이템 이름에 맞는 아이템을 생성한다 (아이템 이름은 Wood_Sword)
// 이 이름을 그대로 아틀라스 매니저에서 가져와서 쓰면 됩니다.
}
}
이런식으로 빈 클래스에 부착할 모노 클래스를 만들고 자신이 하는 역할은 아래 세가지로 최대한 단순하게 구성하였다.
1. 상자를 만든다
2. 아이템을 상자로 부터 이벤트를 받아 만든다.
3. 아이템을 인벤토리로 부터 이벤트를 받아 만든다.
이렇게 세가지 경우가 현재 우리 게임에서 아이템이 실제로 맵에 등장할수 있는 세가지 방법이고 추후 앞서 말한 특정 객체 (예를 들어 아이템 고블린 이라던지) 등이 추가되어 아이템을 뱉는 다 하여도 메서드 하나만 추가해 준다면 손쉽게 아이템을 전역적으로 생성해 줄수 있다.
현재 협업으로 인해 아이템을 실제로 instansiate 하는 부분은 없고 단순 상자만 생성하는 부분만 구현되어 있는데 이 부분은 추가 예정이다.
이제 남은건 각 객체들이 자신에 상황에 맞추어 어떤 타이밍에 아이템 생성을 요청할지 등을 구현하여 이벤트를 디스패치 해주면 된다.
예를 들면 인벤토리에서 아이템을 버리는 메서드를 발동할때 아래와 같이 사용할수 있다.
/// <summary>
/// 현재 인벤토리의 아이템을 버립니다.
/// </summary>
/// <param name="cellHash">버릴 cell의 heshcode</param>
/// <returns>버려진 아이템의 이름을 반환합니다.</returns>
public string DiscardEquipment(int cellHash)
{
var count = InfoManager.instance.inventoryInfo.InventoryCount;
string discardEuipmentName = null;
for (int i = 0; i < count; i++)
{
if (this.content.GetChild(i).GetHashCode() == cellHash)
{
var equipment = this.content.GetChild(i).transform.GetChild(1).GetChild(1);
var euipmentComp = equipment.GetComponent<Equipment>();
euipmentComp.UnSetEquipmentStat();
this.uiPlayerStats.UpdatePlayerStatUI();
discardEuipmentName = equipment.gameObject.name;
Destroy(this.content.GetChild(i).transform.GetChild(1).gameObject);
break;
}
}
//아이템 맵 생성 이벤트 발생 부분
EventDispatcher.Instance.Dispatch<string>(EventDispatcher.EventName.ChestItemGeneratorMakeItemForInventory,
discardEuipmentName);
this.StartCoroutine(this.SorthInventoryCells(count));
return discardEuipmentName;
}
아래는 인벤토리는 아니지만 위에 처럼 이벤트를 발생시키는 부분이다. 코드는 아래와 같다.
else if(this.txtNPCName.text == "숨겨진 아이언 상자\n체력 1개 소모")
{
// 아이템 생성 이벤트 발생 부분
EventDispatcher.Instance.Dispatch<Transform, string>(EventDispatcher.EventName.ChestItemGeneratorMakeItemForChest,
this.NPCPos, "Iron_Chest");
this.NPCPos.gameObject.GetComponent<Animator>().SetInteger("state", 1);
this.NPCPos.gameObject.GetComponent<BoxCollider2D>().enabled = false;
this.gameObject.SetActive(false);
}
반응형
LIST
'프로젝트 > 건즈앤 레이첼스' 카테고리의 다른 글
[유니티 프로젝트] 디파짓 시스템 구현 (UI 업데이트 이전) (0) | 2023.05.04 |
---|---|
[유니티 프로젝트] 크레딧 제작 ( 닷트윈 이용 & 코드 애니메이션 제어 ) (0) | 2023.05.02 |
[유니티 프로젝트] DOTween을 이용한 팝업 UI 애니메이션 (0) | 2023.05.01 |
[유니티 프로젝트] 유저 가이드 화살표 ( 포탈 화살표 ) 제작 (0) | 2023.04.30 |
[유니티 프로젝트] 타일맵 오브젝트 --> PNG 통짜 스프라이트 이미지 변경 코드 (0) | 2023.04.27 |