최종 프로젝트 시작 기획세부(?), 구조잡기
저번 팀플땐 바쁘다고 TIL 밀려썼는데 이번엔 또 하루 마감할 때 쓴다. 원래 이랬는데 좀 낯설다. 미루는거에 벌써 익숙해져 버린건가? 아무튼 나름 기획이 세워졌고 내가 맡은 역할은 인벤토리다. 생각해보면 이번 캠프 생활 중에서 인벤토리 개인 과제는 있었지만 이렇게 본격적으로 한 적은 없었다. 나름 또 이번 게임에서는 중요한 부분이라 잘 해내고 싶다. 드래그 앤 드랍은 해본 적 없었는데 오늘 처음 해보게 되었다. 이 부분에 대해 좀 적어보려한다.
오늘 한 일
드래그 기능을 사용하기 위해 IBeginDragHandler, IDragHandler, IEndDragHandler를 상속받았다.
public void OnBeginDrag(PointerEventData eventData)
{
// 드래그 전 부모 저장
originalParent = transform.parent;
// 최상위 캔버스로 이동
transform.SetParent(parentCanvas.transform, true);
// Raycast 통과시키도록 설정 (Drop 가능하게)
canvasGroup.blocksRaycasts = false;
}
원래 있던 부모 슬롯 위치를 기억해 두었다가 드래그해서 잘못된 곳에 드롭하면 원래 자리로 돌아오게 originalParent 변수를 만든다.
parentCanvas를 새 부모로 설정해 화면 어디든 자유롭게 이동할 수 있게 한다.
blocksRaycasts = false로 설정하면 드래그 중인 아이콘이 Raycast를 막지 않아 OnDrop 이벤트가 전달된다.
public void OnDrag(PointerEventData eventData)
{
// 마우스 위치로 직접 이동
transform.position = eventData.position;
}
드래그 할 때 매 프레임 마다 아이템을 마우스 위치로 옮겨준다.
public void OnEndDrag(PointerEventData eventData)
{
// Raycast 다시 걸리도록 복구
canvasGroup.blocksRaycasts = true;
// 슬롯 위에 드롭되지 않았다면 원위치 복귀
// (SlotDropHandler 가 처리해서 부모가 변경되었다면 그대로 유지)
if (transform.parent == parentCanvas.transform)
{
transform.SetParent(originalParent, false);
//위치 조정
var rt = GetComponent<RectTransform>();
rt.anchoredPosition = Vector2.zero;
}
}
드래그가 끝나면 blockRaycasts를 원래대로 되돌린다.
만약 드롭 대상에 붙어있지 않고 최고 부모에 남아있다면(이상한 곳에서 드랍했다면) 원래 위치(originalParent)로 되돌리고 이 때 이상한 곳에 이미지가 있지 않게 anchoredPosition = Vector2.zero로 슬롯 중앙에 배치한다.
우리 게임에서는 인벤토리 슬롯에는 모든 아이템을,
스킬 슬롯에는 스킬북만,
룬 슬롯에는 룬만 들어갈 수 있도록 기획되었다.
이 스크립트에서는 드롭을 담당하므로 드롭이 가능한 슬롯에 부착하며 IDropHandler를 상속받는다.
public class SlotDropHandler : MonoBehaviour, IDropHandler
{
public SlotType slotType;
public ItemType acceptItemType; // Skill/Rune 슬롯일 때만 사용
public void OnDrop(PointerEventData eventData)
{
//먼저 드래그된 오브젝트가 DraggableItem인지 확인
var dragged = eventData.pointerDrag?.GetComponent<DraggableItem>();
if (dragged == null) return;
//빈 슬롯이 아니면 아무 동작도 하지 않음
//슬롯 하나에 아이템 하나만 갖고있게 하기 위함
if (GetComponentInChildren<DraggableItem>() != null)
return;
//슬롯 별 허용 아이템
switch (slotType)
{
case SlotType.Inventory:
// 인벤토리 슬롯은 모든 ItemType 허용
break;
case SlotType.Skill:
if (dragged.itemData.itemType != ItemType.SkillBook)
return; // 스킬북이 아니면 리턴
break;
case SlotType.Rune:
if (dragged.itemData.itemType != ItemType.Rune)
return; // 룬이 아니면 리턴
break;
}
//아이템의 부모를 이 슬롯으로
dragged.transform.SetParent(transform, false);
//위치, 스케일 초기화
var rt = dragged.GetComponent<RectTransform>();
rt.anchoredPosition = Vector2.zero;
rt.localScale = Vector3.one;
}
GetComponentInChildren<DraggableItem>()이 코드로 이미 드롭하려는 슬롯에 아이템이 있다면 드롭을 하지 못하게 했다.오늘은 스킬북은 스킬 슬롯, 인벤토리에만 드랍 가능하게 / 룬은 룬 슬롯, 인벤토리에만 드랍 가능하게 했다. 흠... 한 이틀이면 대강 완성될거로 예상하고 있는데 과연?? 팀원들이 각자 빠르게 잘 하고 있어서 나도 열심히 따라가 보려고 한다.
내일은 스킬 합성, 룬 슬롯 칸 늘어나게, 룬은 한 번 넣으면 못 빼게, 필터링 기능 이렇게 네 가지를 해 볼까 한다. 그럼 수요일은 활성화된 스킬과 스킬 슬롯 연동, 스킬 제거하면 룬도 같이 제거, 스킬 다시 활성화하면 룬도 같이 활성화, 원래 있던 룬에 새 룬을 끼우면 기존 룬은 파괴를 구현해야 한다. 할게 많군!!! 내일은 꼭 저 네 가지를 해내야 한다!