Chcieliśmy dodać interaktywną mapę interfejsu użytkownika, aby umożliwić użytkownikom przyswajanie informacji w stacji kosmicznej, która wyglądała i działała jakby żyła w tym świecie. Zdecydowaliśmy się zbudować mapę wewnątrz przestrzeni 3D zamiast na ekranie, który nakłada się na doświadczenie. Tego typu diegetyczna wizualizacja pozwala na większe zanurzenie w świecie, w przeciwieństwie do poczucia, że jest to całkowicie odrębne doświadczenie.
Zaprojektuj mapę
Aby zaprojektować mapę:
Stworzyliśmy mockup interfejsu użytkownika w zewnętrznej aplikacji i opracowaliśmy ogólny pomysł, jak chcieliśmy, aby wyglądała.

Eksportowaliśmy poszczególne elementy mapy jako .png i zaimportowaliśmy je do Studio.

Zbuduj mapę
Budowanie mapy wewnątrz Studio polegało na użyciu Parts i SurfaceGuis.
Dla elementów nieinteraktywnych wystarczyło dodać obiekt SurfaceGui do części.
Dla elementów interaktywnych, SurfaceGui musi być również wewnątrz kontenera StarterGui, z właściwością Adornee powiązaną z odpowiednią częścią w przestrzeni 3D. Dzięki temu można dodać zdarzenia przycisków.
Aby osiągnąć efekt paralaksy, użyliśmy trzech oddzielnych instancji ScreenGui przypisanych do trzech unikalnych Parts z różnymi wartościami X.

Następnie dodaliśmy efekt poświaty z właściwością SurfaceGui.LightInfluence. Jeśli ustawisz wartość tej właściwości na mniej niż 1, włączy to właściwość SurfaceGui.Brightness. Poprzez dostosowanie jasności możesz zwiększyć poświatę emitującą z obrazu.
Aby umożliwić użytkownikom przełączanie wyświetlania mapy, użyliśmy ProximityPrompt, który dołączyliśmy do modelu 3D. To łatwy sposób, aby pozwolić użytkownikom wchodzić w interakcję z elementami świata.

Na koniec, używając modułu UITweenModule w ReplicatedStorage, animowaliśmy ukrywanie i pokazywanie interfejsu użytkownika za pomocą TweenService i odrobiny logiki do ustalania stanu. Śledząc, co kliknął użytkownik, mogliśmy ukrywać i pokazywać elementy poprzez tweening różnych właściwości, takich jak alfa, położenie i rozmiar.
Moduł UITweenModulelocal TweenService = game:GetService("TweenService")local UITween = {}-- do wyblakłych obrazówfunction UITween.fadePart(object, amount, time, delay)local tweenAlpha = TweenInfo.new(time, --CzasEnum.EasingStyle.Quad, --Styl EasingEnum.EasingDirection.Out, --Kierunek Easing0, --Liczba powtórzeńfalse, --Odwrotne, jeśli prawdadelay --Czas opóźnienia)local tween = TweenService:Create(object, tweenAlpha, {Transparency = amount})tween:Play()endfunction UITween.fade(object, amount, time, delay)local tweenAlpha = TweenInfo.new(time, --CzasEnum.EasingStyle.Quad, --Styl EasingEnum.EasingDirection.Out, --Kierunek Easing0, --Liczba powtórzeńfalse, --Odwrotne, jeśli prawdadelay --Czas opóźnienia)local tween = TweenService:Create(object, tweenAlpha, {ImageTransparency = amount})tween:Play()end-- do wyblakłych obrazówfunction UITween.fadeBackground(object, amount, time, delay)local tweenAlpha = TweenInfo.new(time, --CzasEnum.EasingStyle.Quad, --Styl EasingEnum.EasingDirection.Out, --Kierunek Easing0, --Liczba powtórzeńfalse, --Odwrotne, jeśli prawdadelay --Czas opóźnienia)local tween = TweenService:Create(object, tweenAlpha, {BackgroundTransparency = amount})tween:Play()end-- do wyblakłego tekstufunction UITween.fadeText(object, amount, time, delay)local tweenAlpha = TweenInfo.new(time, --CzasEnum.EasingStyle.Quad, --Styl EasingEnum.EasingDirection.Out, --Kierunek Easing0, --Liczba powtórzeńfalse, --Odwrotne, jeśli prawdadelay --Czas opóźnienia)local tween1 = TweenService:Create(object, tweenAlpha, {TextTransparency = amount})tween1:Play()end-- do przemieszczania tekstu i obrazówfunction UITween.move(object, position, time, delay)task.wait(delay)object:TweenPosition(position, Enum.EasingDirection.Out, Enum.EasingStyle.Quint, time)end-- do zmiany rozmiarufunction UITween.size(object, size, time, delay, override, callback)local tweenSize = TweenInfo.new(time, --CzasEnum.EasingStyle.Quint, --Styl EasingEnum.EasingDirection.Out, --Kierunek Easing0, --Liczba powtórzeńfalse, --Odwrotne, jeśli prawdadelay, --Czas opóźnieniaoverride,callback)local tween = TweenService:Create(object, tweenSize, {Size = size})tween:Play()endfunction UITween.rotate(object, rotation, time, delay, override, callback)local tweenSize = TweenInfo.new(time, --CzasEnum.EasingStyle.Quint, --Styl EasingEnum.EasingDirection.Out, --Kierunek Easing0, --Liczba powtórzeńfalse, --Odwrotne, jeśli prawdadelay, --Czas opóźnieniaoverride,callback)local tween = TweenService:Create(object, tweenSize, {Rotation = rotation})tween:Play()end-- do rozmycia kamery gryfunction UITween.blur(object, amount, time)local tweenInfo = TweenInfo.new(time, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)local tween = TweenService:Create(object, tweenInfo, {Size = amount})tween:Play()end-- do rozjaśniania kamery gryfunction UITween.turnOn(object, amount, time)local tweenInfo = TweenInfo.new(time, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)local tween = TweenService:Create(object, tweenInfo, {Brightness = amount})tween:Play()endreturn UITweenZastosowanie UI Tween do obiektówlocal ReplicatedStorage = game:GetService("ReplicatedStorage")-- Dodaj moduł UITweenlocal UITween = require(ReplicatedStorage.UITweenModule)-- Znajdź GUI gracza i obiekty UIlocal playerGui = game:GetService('Players').LocalPlayer:WaitForChild('PlayerGui')local screenGuiMapUIFrame = playerGui:WaitForChild("ScreenGuiMapUIFrame").SurfaceGuilocal mapUIFrameStroke = screenGuiMapUIFrame.FrameStrokelocal mapUIFrameFill = screenGuiMapUIFrame.FrameFill-- Rozmiary używane do tweeningulocal frameSizeStart = UDim2.new(0, 0, 0, 0)local frameSizeMid = UDim2.new(1, 0, 0.05, 0)local frameSizeEnd = UDim2.new(1, 0, 1, 0)-- Przykład tweeninguUITween.fade(mapUIFrameStroke, 0, 2, 0)UITween.size(mapUIFrameStroke, frameSizeMid, 0.4, 0)UITween.fade(mapUIFrameFill, 0, 2, 0.5)UITween.size(mapUIFrameFill, frameSizeEnd, 0.4, 0.25)task.wait(0.25)UITween.size(mapUIFrameStroke, frameSizeMid, 0.4, 0)UITween.size(mapUIFrameFill, frameSizeMid, 0.4, 0.25)task.wait(0.25)UITween.size(mapUIFrameStroke, frameSizeEnd, 0.4, 0)UITween.size(mapUIFrameFill, frameSizeEnd, 0.4, 0.25)
Oto końcowy wynik interaktywnej mapy: