728x90
※ 작성자도 MSW 초보자이므로 코드가 비효율적이거나 기술 구현이 많이 부족합니다!😅
구현 영상
동작 설명
- 게임에 처음 접속하는 플레이어(뉴비)일 경우, 인트로를 실행합니다.
- StartMap에서 IntroMap으로 플레이어 이동시킵니다.
- 플레이어를 자동 이동 시키며, 스토리에 대한 이해를 도울 대사를 대화창을 통해 주인공의 혼잣말 형식으로 보여줍니다.
- 인트로가 끝나면 StartMap으로 다시 이동시킵니다.
- 중간에 Skip 버튼 누를 시 인트로 기능이 중지됩니다.(자동 이동이 멈추고 대화창 꺼지며 StartMap으로 이동하게 됩니다.)
- 뉴비가 아니라면 접속 시 인트로가 실행되지 않습니다.
- 테스트 데이터를 초기화하고 다시 접속하면 뉴비로 인식되어 인트로 실행되는 것을 확인할 수 있습니다.
개선이 필요한 부분
- 자동 이동 시에 player 아바타가 자연스럽게 걸어가는 애니메이션을 하게 만들고 싶은데 실패..
- 대화창에 npc처럼 player Portrait로 쓸만한 이미지가 있으면 좋겠는데 이건 불가능할 듯
대화창을 나타내 줄 InfroUIGroup 추가
이 기능은 MapleStory Worlds-DEVELOPER의 Docs를 참고하여 만들었습니다.
Docs와 다른 점
'데이터 테이블 추가' 부분에서 데이터 테이블의 컬럼을 text 하나로 구성했습니다.
위의 docs와 다르게 인트로 구현 부분은 여러 명의 주체가 대화를 나누는 것이 아닌 주인공 혼잣말이라는 점, 주인공은 마땅히 사용할 수 있는 portrait가 없다는 점에서 name, portrait 컬럼 없이 text 컬럼만 생성했습니다.
이에 따라 데이터 테이블에서 정보를 가져와 대화창에 띄워주는 부분에서 코드 차이가 있습니다.
728x90
DefaultPlayer에 IntroComponent 추가
모든 코드 블록 첫 줄에 해당 코드가 어느 컴포넌트인지 쓰여 있습니다. 꼭 해당 코드가 어느 컴포넌트에 존재하는 코드인지 확인해주세요!
--IntroComponent Property
--@ BeginProperty
--@ SyncDirection=All
string isNP = ""true""
--@ EndProperty
--@ BeginProperty
--@ SyncDirection=None
any introTalkData = "nil"
--@ EndProperty
--@ BeginProperty
--@ SyncDirection=None
Entity uiNameEntity = "nil"
--@ EndProperty
--@ BeginProperty
--@ SyncDirection=None
Entity uiMessageEntity = "nil"
--@ EndProperty
--@ BeginProperty
--@ SyncDirection=None
Entity uiTalkPanel = "nil"
--@ EndProperty
--@ BeginProperty
--@ SyncDirection=None
Entity uiPortraitEntity = "nil"
--@ EndProperty
--@ BeginProperty
--@ SyncDirection=None
string startMap = """"
--@ EndProperty
게임에 처음 접속한 플레이어만 인트로 재생
--IntroComponent
--@ BeginMethod
--@ MethodExecSpace=ServerOnly
void isNewPlayer()
{
local userId = self.Entity.Name
local userDS = _DataStorageService:GetUserDataStorage(userId)
--userDS에서 isNewPlayer를 key값으로 가지는 value 가져오기 위한 CallBack 함수
local getCallBack = function(errorcode, key, value)
--해당 key 값이 없으면 value에 nil이 들어감(뉴비란 소리이므로 value에 true 넣어줌
if value == nil then value = "true" end
if key == "isNewPlayer" then
self.isNP = value
end
end
--한 번 접속한 플레이어이므로 isNewPlayer에 false 넣어주기 위한 CallBack 함수
local setCallBack = function(errorcode, key)
self.isNP = "false"
end
userDS:GetAsync("isNewPlayer", getCallBack)
--wait을 해주지 않으면 DataStorage를 가져오기 전에 뒤에 코드 실행됨(타이밍 이슈 발생)
wait(1)
--뉴비면 튜토리얼 실행
if self.isNP == "true" then
log("튜토리얼 실행")
--튜토리얼 실행 함수
self:playIntro()
--DataStorage에 뉴비가 아니라는 데이터 넣어줌
userDS:SetAsync("isNewPlayer", "false", setCallBack)
wait(3)
end
}
--@ EndMethod
인트로 재생
--IntroComponent
--@ BeginMethod
--@ MethodExecSpace=Client
void playIntro()
{
--IntroMap으로 이동(시작맵이 IntroMap이라면 없어도 됨)
self:teleportToIntroMap()
--wait이 없으면 맵 이동 후 캐릭터가 타일 위에 내려앉기 전에 움직이기 시작함.
--(공중부양한 채로 움직이게 됨)
wait(1)
--대사 데이터 table 불러오기
self.introTalkData = _DataService:GetTable("IntroTalk")
--대사창 ui entity들 불러오기
self.uiNameEntity = _EntityService:GetEntityByPath("/ui/IntroTalkGroup/TalkPanel/Name")
self.uiMessageEntity = _EntityService:GetEntityByPath("/ui/IntroTalkGroup/TalkPanel/Text")
self.uiTalkPanel = _EntityService:GetEntityByPath("/ui/IntroTalkGroup/TalkPanel")
self.uiPortraitEntity = _EntityService:GetEntityByPath("/ui/IntroTalkGroup/TalkPanel/Portrait")
--플레이어 이름 대사창에 띄우기
local name = _UserService.LocalPlayer.NameTagComponent.Name
self.uiNameEntity.TextComponent.Text = name
--플레이어가 오른쪽을 보게 함
self.Entity.PlayerControllerComponent.LookDirectionX = 1
--자동이동
self.Entity.IntroAutomaticMovementComponent.Enable = true
self.uiTalkPanel.Enable = true
--대화창 초상화 띄우는 entity
--플레이어의 초상화는 따로 없으므로 enable=false로 해둠
self.uiPortraitEntity.Enable = false
--대화를 3개만 지정해두어서 3까지만
for count = 1, 3 do
--dataset에 넣어둔 대사 하나씩 불러오기
--GetCall 아님. GetC'e'll임.(주의)
local message = self.introTalkData:GetCell(count, 1)
--불러온 대사 대화창에 띄우기
self.uiMessageEntity.TextComponent.Text = message
--대사 하나당 4초씩 보여주기
wait(4)
--대사 끝났으면
if count == 3 then
--대화창 끄고
self.uiTalkPanel.Enable = false
--자동이동 멈추고
self.Entity.IntroAutomaticMovementComponent.Enable = false
--플레이어가 다시 기본으로 왼쪽을 보게 함
self.Entity.PlayerControllerComponent.LookDirectionX = -1
--시작 맵으로 이동
self:teleportToStartMap()
end
end
}
--@ EndMethod
--@ BeginMethod
--@ MethodExecSpace=All
void teleportToStartMap()
{
--처음 시작했던 맵으로 이동
--Vertor3에 이동하고 싶은 좌표 넣기
_TeleportService:TeleportToMapPosition(_UserService.LocalPlayer, Vector3(-6.473167, -0.4881773, 1), self.startMap)
}
--@ EndMethod
--@ BeginMethod
--@ MethodExecSpace=All
void teleportToIntroMap()
{
--시작 맵 저장 후, 인트로맵으로 이동
--Vertor3에 이동하고 싶은 좌표 넣기
self.startMap = self.Entity.CurrentMapName
_TeleportService:TeleportToMapPosition(_UserService.LocalPlayer, Vector3(-6.618879, -0.5888717, 1), "IntroMap")
}
--@ EndMethod
DefaultPlayer에 IntroAutomaticMovementComponent 추가
자동 이동
--IntroAutomaticMovementComponent
--@ BeginMethod
--@ MethodExecSpace=ServerOnly
void OnUpdate(number delta)
{
local deltaX = 1
local pos = self.Entity.TransformComponent.Position
pos.x = pos.x + deltaX * delta
local deltaPos = Vector2(pos.x, pos.y)
self.Entity.MovementComponent:SetPosition(deltaPos)
}
--@ EndMethod
참고 문서
MapleStory Worlds-DEVELOPER Docs의 엔티티 이동
스킵 버튼 추가
위와 같이 되도록 UI 버튼 생성
UI IntroTalkGroup 부모-자식 관계
스킵 버튼 활성화
--IntroComponent
--@ BeginEntityEventHandler
--@ Scope=All
--@ Target=entity:4a02f0a7-c93c-4547-9a5f-66c0fb53dbf3
--@ EventName=ButtonClickEvent
HandleButtonClickEvent
{
-- Parameters
local Entity = event.Entity
--------------------------------------------------------
log("Skip")
self.uiTalkPanel.Enable = false
--자동 이동 멈춤
self.Entity.IntroAutomaticMovementComponent.Enable = false
--플레이어가 다시 기본으로 왼쪽 보게 함
self.Entity.PlayerControllerComponent.LookDirectionX = -1
--시작 맵으로 이동
self:teleportToStartMap()
}
--@ EndEntityEventHandler
728x90