배지 서비스 활용하기

# 학습 과정 소개

배지를 웹에서 등록하고, `BadgeService`를 활용해 특정 오브젝트에 닿았을 때 배지를 획득하게 만들어 봅시다. 출시하지 않은 월드에서는 배지를 출시하더라도, 실제로 획득할 수 없음을 유념하세요.

# BadgeService

등록한 배지는 배지 서비스를 통해 활용할 수 있습니다. 배지를 획득한 유저에게는 획득 알림창이 8초 동안 나타나며 배지의 정보가 보입니다. 만약 여러 배지를 연속으로 획득한 경우 알림창은 획득한 순서대로 나타납니다.

# 활용 예시

다른 등급의 배지 3개를 등록하고, 특정 장소에 도착하면 배지를 얻을 수 있게 만들어봅시다.

#### 사전 준비

[배지 등록하기](/docs/?postId=656)를 따라 배지를 등록합니다.

[{"배지 정보":"배지 등급","배지 1":"노멀","배지 2":"레어","배지 3":"에픽"},{"배지 정보":"배지 이름","배지 1":"숲 마을에 도착","배지 2":"시계 탑에 도착","배지 3":"왕궁 입구 도착"},{"배지 정보":"획득 기간","배지 1":"무기한","배지 2":"무기한","배지 3":"무기한"},{"배지 정보":"배지 썸네일","배지 1":"[png](1646351123383a964ad8465424f30b49639e7ca5c4593)","배지 2":"[png](1646351139128655068f53362491b9a0f7fbcec64136c)","배지 3":"[png](1646351152274a308bfb2c7b84d1bbd0114c87a9d716d)"},{"배지 정보":"배지 설명","배지 1":"숲 마을 입구에 도착하면 받는 배지 입니다.","배지 2":"마을 중앙에 시계탑에 도착하면 받는 배지 입니다.","배지 3":"왕궁 입구에 도착하면 받는 배지 입니다."}]

#### 배지 지급하기

특정 장소를 지나가는 플레이어에게 배지를 지급해봅시다. [gif](16656410005845099c2a04df946bc8a0c540aedeb76e8)

  1. 플레이어 캐릭터가 배지를 획득할 장소 역할을 할 오브젝트를 골라 월드에 배치합니다. [png](1665631051376747462ce6e7946dd9287caebe3462ee5)

  2. 오브젝트에 TriggerComponent를 추가합니다.

  3. Workspace - MyDesk에 새로운 SendBadgeInfo 컴포넌트를 생성하고, 배지를 획득하는 장소 오브젝트에 추가합니다. [png](16661642796074bf718f61bf849b99b9abace8e97342e)

  4. 스크립트 에디터를 열어 SendBadgeInfo 컴포넌트에 배지 ID를 확인하기 위한 프로퍼티를 추가합니다.
         
         @Component
         script BadgeInformation extends Component
         property string BadgeInfo = ""
         end
         



    
    
    5. **Badge Viewer**에서 **Copy Badge ID**를 선택하고, 해당 배지를 얻을 수 있는 엔티티의 **SendBadgeInfo** 컴포넌트의 **BadgeInfo** 프로퍼티에 복사한 ID를 붙여 넣습니다.
    [png](16681380690416a3f4b1fc0c147caa8ec9cf7e3c29c02)
    
    6. 새로운 **PlayerGetBadge 컴포넌트**를 생성하고 **DefaultPlayer**에 추가합니다.  배지를 수여 받을 유저가 배지가 없는지 확인하고, 배지를 수여할 수 있게 `BadgeService`를 활용해 아래와 같이 작성합니다.
    [gif](1665631087798d08c54dcac3a413ca25de89824cfc59d)
    
        ```lua
    @Component
    script TriggerBadgeAwarder extends Component
        @ExecSpace("ServerOnly")
        method void GetBadge(string BadgeID)
        local awardingUserId = self.Entity.PlayerComponent.UserId
        if _BadgeService:AwardBadgeAndWait(awardingUserId, badgeId) then
            self:SendEvent(awardingUserId)
        end        
        end
    
        @ExecSpace("ClientOnly")
        method void SendEvent(any _arg)
        local badgeOpenBtn = _EntityService:GetEntityByPath("/ui/DefaultGroup/BadgeOpenBtn")
        local event = GetBadge()
        badgeOpenBtn:SendEvent(event)
        end
    
        @ExecSpace("ServerOnly")
        @EventSender("Self")
        handler HandleTriggerEnterEvent(TriggerEnterEvent event)
        --------------- Native Event Sender Info ----------------
        -- Sender: TriggerComponent
        -- Space: Server, Client
        ---------------------------------------------------------
    
        -- Parameters
        local TriggerBodyEntity = event.TriggerBodyEntity
        ---------------------------------------------------------
    
        if TriggerBodyEntity.SendBadgeInfo then
            self:GetBadge(TriggerBodyEntity.SendBadgeInfo.BadgeInfo)
        end
        end
    end
    

  7. 시작을 눌러 오브젝트에 부딪혔을 때 배지 획득 연출 창이 뜨는지 확인합니다.

> Tip. 배지는 획득 조건을 달성한 유저에게만 지급되어야 하므로 멀티플레이 테스트로 조건이 맞는 유저만 배지를 획득하는지 확인이 반드시 필요합니다.




#### 배지 확인 버튼 만들기

배지 획득 확인창을 여는 버튼을 만들고, 버튼을 누르면 '배지보기'에서 '닫기'로 바뀌게 만들어봅시다. [gif](16656390246259091762835cb4ecf871dff47bf226bc9)

  1. UI 에디터 - DefaultGroup - BadgeOpenBtn 버튼을 배치합니다. [png](166563113640549e397515a4e40c6b655e7b47579de3f)

  2. 프로퍼티 에디터에서 TextComponent를 추가하고, Text에 배지 보기를 입력합니다.

  3. 새로운 BadgeOpenBtn 컴포넌트를 생성하고, BadgeOpenBtn에 추가합니다.

  4. 버튼을 클릭할 때 발생하는 ButtonClickEvent를 받아서 BadgeLayer 엔티티의 Enable을 설정하고, 버튼의 Text를 바꿀 수 있도록 아래와 같이 작성합니다.
         
         @Component
         script BadgeLayerToggler extends Component
         @EventSender("Self")
         handler HandleButtonClickEvent(ButtonClickEvent event)
         --------------- Native Event Sender Info ----------------
         -- Sender: ButtonComponent
         -- Space: Client
         ---------------------------------------------------------
         
         -- Parameters
         -- local Entity = event.Entity
         ---------------------------------------------------------
         
         local BadgeLayerPanel = _EntityService:GetEntityByPath("/ui/BadgeLayer")
         
         if BadgeLayerPanel.Enable == false then
             BadgeLayerPanel:SetEnable(true)
             self.Entity.TextComponent.Text = "닫기"
         else
             BadgeLayerPanel:SetEnable(false)
             self.Entity.TextComponent.Text = "배지 보기"
         end
         end
         end
         



    
    
    5. 버튼을 누르면 배지보기가 닫기로 바뀌는지 확인합니다.
    
    #### 배지 확인창 UI 만들기
    1. **UI 에디터 - BadgeLayer**를 추가합니다.
    2. 이미지와 텍스트를 활용해 배지 정보를 확인할 수 있는 창을 만듭니다.
    [png](1665631306060d1951767a9be4695ac57542a369e7af1)
    
        >**Tip**
        > BadgeSlot_01 하위에 다른 UI 엔티티를 넣어두어야 합니다.
    
    3. **BadgeViewer**에서 **숲 마을에 도착** 배지를 선택하고, 콘텍스트 메뉴를 열어 **Copy Badge Thumbnail RUID**을 선택합니다.
    [png](16681384258846f8b89ff41024fc79129bd44f8d45828)
    
    4. 배지 이미지를 보여줄 이미지 엔티티를 선택하고, **SpriteGUIRendererComponent의 ImageRUID**에 RUID를 붙여 넣습니다.
    [png](1665632185530c700ddc5625f484994f1c06880cbc08b)
    
    #### 배지 획득 확인창에 배지 정보 가져오기
    1. 새로운 **BadgeSlot 컴포넌트**를 생성하고 **BadgeSlot_01**에 추가합니다.
    [png](16656324011016d410ea46d8b488285c79a14cf05ccec)
    2. 획득한 배지의 이름, 소유 정보, 설명을 가져올 수 있도록 프로퍼티를 추가합니다.
    
        ```lua
    @Component
    script BadgeQuery extends Component
        property string BadgeId = "" -- 조회할 배지 ID
        property any BadgeTitle = nil -- 배지 이름
        property any Hasbadge = nil -- 배지 소유 정보
        property any BadgDesc = nil -- 배지 설명
    end
    
    
    
    > **Tip**
    > Property의 TextComponent는  버튼을 눌러 TextComponent를 선택합니다.
    > [png](1665639334907a1cca5eef1e04d67adad71c5632d75cc)
    

  3. `GetBadgeInfoAsync()`를 활용해 배지 정보를 조회하고, 창이 열렸을 때 배지 관련 정보가 TextComponent에서 보이도록 아래와 같이 작성합니다.
         
         @Component
         script BadgeInfoDisplay extends Component
         @ExecSpace("ClientOnly")
         method void OnBeginPlay()
                 self.BadgeTitle = self.Entity:GetChildByName("BadgeTitle").TextComponent
                 self.HasBadge = self.Entity:GetChildByName("HasBadge").TextComponent
                 self.BadgeDesc = self.Entity:GetChildByName("BadgeDesc").TextComponent
         
                 self:BadgeCheck()
         
                 local EventHandler = _EntityService:GetEntityByPath("/ui/DefaultGroup/BadgeOpenBtn")
         
         --         EventHandler:ConnectEvent(GetBadge, function()
         --             self:BadgeCheck()   
         --         end)
         -- [Commented: MLUA requires @EventSender + handler pattern]
         end
         
         @ExecSpace("ClientOnly")
         method void BadgeCheck()
         local callBack = function(badgeId, badgeInfo)
             if badgeInfo ~= nil then
                 self.BadgeTitle.Text = badgeInfo.Name
                 self.BadgeDesc.Text = badgeInfo.Description
             end
         end
         
         _BadgeService:GetBadgeInfoAsync(self.BadgeId, callBack)
         
         local localUserID = _UserService.LocalPlayer.Name
         
         if _BadgeService:UserHasBadgeAndWait(localUserID, self.BadgeId) then
             self.HasBadge.Text = "보유 중"
         else
             self.HasBadge.Text = "미보유"
         end
         end
         end
         



    
    
    5. **Badge Viewer**에서 **숲 마을에 도착** 배지를 선택하고, 콘텍스트 메뉴를 열어 **Copy Badge ID**를 선택합니다.
    [png](1668138166968773a133ceb174a90a9e80d9d5e6db835)
    
    6. **BadgeSlot_01** 프로퍼티 창에서 **BadgeSlot - BadgeId**에 복사한 ID를 붙여 넣습니다.
    6. 위의 스크립트에서 작성한 이벤트를 만들기 위해 **MyDesk - Create Script - Create EventType**를 선택해 새로운 **GetBadge** 이벤트를 만듭니다.
    [png](1665632709258ffdbc73fd6d84d45a2ff7c48dde1f0e9)
    
    7. 시작을 눌러 배지를 획득한 후 배지 상태가 변경되는지 확인합니다.