이미지 드래그 하기
우리가 흔히 rpg 게임에서 보면 아이템, 스킬 등의 아이콘을 드래그 할 수 있다. 드래그 했을 경우 아이템이 반투명하게 딸려오게되고 특정 행동을 할 수 있게된다.
우리가 할 최종 목표는 아이템이나 스킬등을 드래그해서 큇슬롯에 등록하고 사용해보도록 하자.
일단 먼저 이미지를 드래그하기 위한 이벤트를 바인드 해주어야한다.
_icon.gameObject.BindEvent((e) =>
{
if (itemData == null) return;
dragObj = Managers.Resource.Instantiate("UI/UI_DragObj");
dragIcon = Util.FindChild(dragObj, "Icon");
if (dragIcon == null) return;
dragIcon.GetComponent<Image>().sprite = _icon.sprite;
}, Define.UIEvent.DragEnter);
_icon.gameObject.BindEvent((e) =>
{
if (itemData == null) return;
if (dragObj == null) return;
dragIcon.transform.position = e.position;
}, Define.UIEvent.Drag);
_icon.gameObject.BindEvent((e) =>
{
if (itemData == null) return;
if (dragObj == null) return;
Managers.Resource.Destroy(dragObj);
string name = e.pointerCurrentRaycast.gameObject.name;
if (name == null) return;
}, Define.UIEvent.DragEnd);
이건 아이템에서 드래그할 때이고 이는 스킬과 동일하게 작동한다.
아이템 드래그를 시작했을 때 DragObj인 Canvas를 스폰한다. 스폰된 DragObj에서 이미지 스프라이트를 내가 현재 드래그한 스프라이트로 바꿔준다. 이때 이미 투명도는 약 80%정도로 설정해 둔 상태이다. 드래그가 끝났을 때 DragObj를 삭제해준다.
퀵슬롯 등록하기
_icon.gameObject.BindEvent((e) =>
{
if (itemData == null) return;
if (dragObj == null) return;
Managers.Resource.Destroy(dragObj);
string name = e.pointerCurrentRaycast.gameObject.name;
if (name == null) return;
if(itemData.itemType == ItemType.Consumable && name != null)
(Managers.UI.SceneUI as UI_GameScene).RequestQuickSlotUI(name, TemplateId, false);
}, Define.UIEvent.DragEnd);
드래그가 끝났을 때, 원하는 동작을 넣으면 된다. 내가 원하는 동작은 아이템 드래그해서 마우스를 큇슬롯 영역에 넣고 동작이 끝났을 때 그 위치에 등록하고 인벤창이 아닌 큇슬롯에서 바로 아이템을 사용하는 것이다.
물론 장비가 아닌 Comsumable 아이템만 동작하게 if문을 걸어두었다.
QuickSlot이 있는 UI에 RequsetQuickSlot를 날려 등록해보자.
public Dictionary<string, int> QuickSlotSkill = new();
public Dictionary<string, int> QuickSlotItem = new();
public void RequestQuickSlotUI(string pos, int templateId, bool isSkill)
{
switch (pos)
{
case "QuickSlotIconImageQ":
if(isSkill)
RegisterQuickSlot("Q", templateId, true);
break;
case "QuickSlotIconImageW":
if(isSkill)
RegisterQuickSlot("W", templateId, true);
break;
case "QuickSlotIconImageE":
if(isSkill)
RegisterQuickSlot("E", templateId, true);
break;
case "QuickSlotIconImageR":
if(isSkill)
RegisterQuickSlot("R", templateId, true);
break;
case "QuickSlotIconImage1":
if(!isSkill)
RegisterQuickSlot("1", templateId, false);
break;
case "QuickSlotIconImage2":
if(!isSkill)
RegisterQuickSlot("2", templateId, false);
break;
case "QuickSlotIconImage3":
if(!isSkill)
RegisterQuickSlot("3", templateId, false);
break;
case "QuickSlotIconImage4":
if(!isSkill)
RegisterQuickSlot("4", templateId, false);
break;
default:
return;
}
}
public void RegisterQuickSlot(string keyName, int templateId, bool isSkill)
{
var quickSlot = isSkill ? QuickSlotSkill : QuickSlotItem;
if (quickSlot.TryGetValue(keyName, out int curTemplateId) && curTemplateId == templateId)
return;
quickSlot[keyName] = templateId;
var keysToRemove = quickSlot
.Where(slot => slot.Key != keyName && slot.Value == templateId)
.Select(slot => slot.Key)
.ToList();
foreach (var key in keysToRemove)
{
quickSlot.Remove(key);
}
DrawQuickSlot();
}
public void DrawQuickSlot()
{
{
Sprite nullSprite = Managers.Resource.Load<Sprite>("UI/Content/Mini_background");
GetImage((int)Images.QuickSlotIconImageQ).sprite = nullSprite;
GetImage((int)Images.QuickSlotIconImageW).sprite = nullSprite;
GetImage((int)Images.QuickSlotIconImageE).sprite = nullSprite;
GetImage((int)Images.QuickSlotIconImageR).sprite = nullSprite;
GetImage((int)Images.QuickSlotIconImage1).sprite = nullSprite;
GetImage((int)Images.QuickSlotIconImage2).sprite = nullSprite;
GetImage((int)Images.QuickSlotIconImage3).sprite = nullSprite;
GetImage((int)Images.QuickSlotIconImage4).sprite = nullSprite;
GetText((int)Texts.QuickSlotNumText1).text = "";
GetText((int)Texts.QuickSlotNumText2).text = "";
GetText((int)Texts.QuickSlotNumText3).text = "";
GetText((int)Texts.QuickSlotNumText4).text = "";
}
foreach (var Slot in QuickSlotSkill)
{
if (Managers.Data.SkillDict.TryGetValue(Slot.Value, out Skill skill) == false) return;
Sprite sprite = Managers.Resource.Load<Sprite>($"Textures/Skill/{skill.name}");
switch (Slot.Key)
{
case "Q":
GetImage((int)Images.QuickSlotIconImageQ).sprite = sprite;
break;
case "W":
GetImage((int)Images.QuickSlotIconImageW).sprite = sprite;
break;
case "E":
GetImage((int)Images.QuickSlotIconImageE).sprite = sprite;
break;
case "R":
GetImage((int)Images.QuickSlotIconImageR).sprite = sprite;
break;
}
}
foreach (var Slot in QuickSlotItem)
{
if (Managers.Data.ItemDict.TryGetValue(Slot.Value, out ItemData itemData) == false) return;
Sprite sprite = Managers.Resource.Load<Sprite>(itemData.iconPath);
int itemCount = Managers.Inven.FindItemCount(Slot.Value);
switch (Slot.Key)
{
case "1":
GetImage((int)Images.QuickSlotIconImage1).sprite = sprite;
GetText((int)Texts.QuickSlotNumText1).text = itemCount.ToString();
break;
case "2":
GetImage((int)Images.QuickSlotIconImage2).sprite = sprite;
GetText((int)Texts.QuickSlotNumText2).text = itemCount.ToString();
break;
case "3":
GetImage((int)Images.QuickSlotIconImage3).sprite = sprite;
GetText((int)Texts.QuickSlotNumText3).text = itemCount.ToString();
break;
case "4":
GetImage((int)Images.QuickSlotIconImage4).sprite = sprite;
GetText((int)Texts.QuickSlotNumText4).text = itemCount.ToString();
break;
}
}
}
코드가 조금 복잡할 수 있는데 Request에서는 내가 등록한 위치를 확인하고 등록하는 과정이고 그렇게 위치가 확정되면 Register 부분에서는 C#에서만 쓰는 코드들이 많아 보기 힘들 수 있지만 결론적으로 하는 동작은 다음과 같다.
- 스킬인지 아이템인지에 따라 QuickSlot 불러오기
- 불러온 QuickSlot에 내가 원하는 templateId를 덮어쓰기
- 그리고 QuickSlot에 중복된 templateId가 있는지 확인하기. 있다면 전부 삭제
로 구성되어 있다.
마지막으로 Draw를 통해서 등록된 큇슬롯을 UI 이미지에 뿌려주기만 하면된다.
큇슬록 사용하기
if (Input.GetKeyDown(KeyCode.Q))
{
if (curRightWeapon == null) return;
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeSkillQuickSlot("Q");
}
else if (Input.GetKeyDown(KeyCode.W))
{
if (curRightWeapon == null) return;
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeSkillQuickSlot("W");
}
else if (Input.GetKeyDown(KeyCode.E))
{
if (curRightWeapon == null) return;
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeSkillQuickSlot("E");
}
else if (Input.GetKeyDown(KeyCode.R))
{
if (curRightWeapon == null) return;
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeSkillQuickSlot("R");
}
else if (Input.GetKeyDown(KeyCode.Alpha1))
{
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeItemQuickSlot("1");
}
else if (Input.GetKeyDown(KeyCode.Alpha2))
{
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeItemQuickSlot("2");
}
else if (Input.GetKeyDown(KeyCode.Alpha3))
{
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeItemQuickSlot("3");
}
else if (Input.GetKeyDown(KeyCode.Alpha4))
{
if (State != CreatureState.Idle || State == CreatureState.Moving || State == CreatureState.Skill || State == CreatureState.Dead || State == CreatureState.Wait) return;
UI_GameScene gameSceneUI = Managers.UI.SceneUI as UI_GameScene;
gameSceneUI.InvokeItemQuickSlot("4");
}
MyPlayerController에서 키 입력을 감지한다. 어떤 큇슬롯을 눌렀는지 확인하기 위함이다.
public void InvokeSkillQuickSlot(string keyName)
{
if (QuickSlotSkill.TryGetValue(keyName, out int templateId) == false)
return;
if (Managers.Data.SkillDict.TryGetValue(templateId, out Skill skill) == false)
return;
_myPlayer.QuickAction(skill);
DrawQuickSlot();
}
public void InvokeItemQuickSlot(string keyName)
{
if (QuickSlotItem.TryGetValue(keyName, out int templateId) == false)
return;
Item quickItem = Managers.Inven.Find(item => item.TemplateId == templateId && item.ItemType == ItemType.Consumable);
if (quickItem == null)
return;
C_UseItem useItemPacket = new C_UseItem();
useItemPacket.ItemDbId = quickItem.ItemDbId;
useItemPacket.Count = 1;
Managers.Network.Send(useItemPacket);
DrawQuickSlot();
}
이제 사용하는 코드느 다음과 같다. 스킬의 경우 이미 예전부터 사용중인 QuickAction을 재 사용했고 아이템의 경우 아이템 사용패킷을 만들어 보내주는 역할을 했다.
구현 영상
당연히 게임이 종료됐을 때 큇슬롯의 위치를 기억하기위해 서버로 패킷을 보내 저장하는 과정도 존재한다. 이는 생략한다.
'Unity > 온라인 RPG' 카테고리의 다른 글
[Unity 3D] 상점 Npc - 아이템 구매, 판매하기 (0) | 2024.07.04 |
---|---|
[Unity 3D] 아이템 인벤창에서 옮기기 (0) | 2024.06.21 |
[Unity 3D] 스탯 포인트 사용하기 (0) | 2024.06.11 |
[Unity 3D] 획득한 아이템 착용하기 (1) | 2024.06.11 |
[Unity 3D] 아이템 드랍 및 획득 (0) | 2024.05.29 |