Podstawowe grywalizacje systemy

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

Poniższe systemy były podstawą w tworzeniu gameplay'u, który chcieliśmy dla Tajemnicy Duvall Drive .

Menedżer państwa gry

GameStateManager / GameStateClient jest prawdopodobnie najbardziej skomplikowanym systemem w doświadczeniu, ponieważ zajmuje się:

  • Począwszy graczy w lobby, rozpoczynając liczdownik teleportacji grupy do głównej gry, i teleportacji graczy na zarezerwowane serwery.
  • Klonowanie uszkodzonych pokoi, przesyłanie ich równolegle i teleportowanie graczy do i z określonego przydzielonego CFrame koordynatu.
  • Łapanie i umieszczanie mechanizmów uszczelnień.
  • Zablokowanie i odblokowanie drzwi.
  • Początkowa inicjatyzacja teleportacji do foyer i gra w końcowej scenie.

Zaimplementowaliśmy go jako prostą maszynę stanu (funkcję aktualizacji), a stanami są w DemoConfig (ensemblem GameStates). Niektóre stanowe deal with initial lobby / reserved server teleportować się, while others deal with finding a mission, triggering the puzzle, and solving the mission. Note that in addition to seals, we tried to not have mission-specific code in the GameStateManager.

GameStates jest w większości przypadków serwerem, ale gdy klient musi zrobić coś, na przykład pokazać licznik, zasady lub wyłączyć pauzę UI, serwer i klient (GameStateClient) komunikują się za pośrednictwem zdalnego wydarzenia zwanego GameStateEvent. W większości przypadków wartość parametru ma typ "wpisywać" (Config.GameEvents) jako pierwszy parametr, a następnie dane włas

Stany gry w teleportacji

Istnieje grupa 3 stany gry, które wykonują trzy unikalne cutscenen, które ukrywają teleportację do zniszczonego pokoju: Warm

Podczas gdy serwer przetwarza zapis, wtedy InFlight uruchdza się, utrzymując nieco pulsujący ciemny ekran. Gdy zarówn

Podobny zestaw cutscen z Warmup, InFlight i Cooldown następuje, gdy teleportujemy gracza do normalnego stanu pokoju, TeleportWarmupBack, TeleportInFlightBack i TeleportCooldownBack

Stany gry w oświetleniu i atmosferze

Wiedzieliśmy, że chcemy, aby każ

Zablokowanie drzwi - stan gry

Ch

Menedżer wydarzeń

EventManager pozwolił nam uruchomić "akcje" w czasie, wykorzystując klatki kluczowe, takie jak:

  • Łączenie właściwości i cech instancji.
  • Wykonanie skryptów.
  • Odtwarzanie dźwięku.
  • Kamera drga.

Idealnie używamy narzędzia z interfejsem opartym na ścieżce, ale dla tej demonstracji wpisaliśmy ręcznie klucze i nazwy właściwości. System EventManager składa się z kilku skryptów i funkcji wydarzenia, w tym:

  • EventManager - ogólna logika tworzenia i zatrzymywania wydarzeń, a także działań serwera.
  • EventManagerClient - działania strony klienta.
  • EventManagerModule - Common code dla obu serwer i strony klienta.
  • EventManagerConfig - Mały plik z kilkoma deklaracjami komend.
  • EventManagerDemo - Gdzie wszystkie rzeczywiste wydarzenia dla tej demonstracji są zdefiniowane w grze w określonym skrypcie.
  • EventManagerEvent , EventManagerFunc - zdalne wydarzenie i funkcja wiązania, aby uruchomić i zatrzymać wydarzenia z klienta lub serwera. To jest, jak inne systemy mogą ustawić, uruchomić i zatrzymać wydarzenia.

Każde wydarzenie ma nazwę, sekcję z opcjonalnymi informacjami o czasie odnowienia, funkcję do uruchomienia na początku lub na kończyć, parametry wydarzenia i sekcje z interpolantami (interpolowaniem dowolnej liczby właściwości lub atrybutów w ciągu czasu), skrypty (uruchomione rejestrowane skrypty na kluczowych klatkach) i grę w dźwięk.

Przerobienie

Interpolacja pozwala na swobodne zmienianie właściwości i atrybutów obiektu z jednej wartości na inną, zamiast skacznieć pomiędzy kluczowymi ramkami. Definiowaliśmy interpolator, aby zmienić różne efekty wizualne; na


interpolants = {
objectParam = "TextLabel",
property = "TextTransparency",
keys = {
{value = 1},
{time = .5, value = 0},
{time = 2.25, value = 0},
{time = 3, value = 1}
}
}

Podczas gdy moglibyśmy zdefiniować, która właściwość lub atrybut obiektu należy do tego, jak w następującym przykładzie kodu, chcieliśmy, abyśmy mogli ponownie używać tych samych wydarzeń na różnych "grupach obiektów", aby umożliwić działanie z płynnością na klientach i z obiektami utworzonymi podczas uruchomienia.


object = workspace.SomeFolder.SomeModel

Aby to osiągnąć, pozwoliliśmy na referencję przez imię obiektu i przekazanie imienia parametru na rozpoczynaćwydarzenia. Aby znaleźć obiekty z imieniem, pozwoliliśmy określić korzeń dla wydarzenia, który pozwala na znalezienie obiektów z imieniem "Wander" gdzieś pod workspace.


params = {
["RootObject"] = workspace.Content.Interior.Foyer["Ritual-DemoVersion"],
},
interpolants = {
objectName = "Wander",
attribute = "TimeScale",
keys = {
{value = 0.2}
}
}

Umożliwiliśmy przesuwanie parametrów do wydarzeń w sekcji parametrów, a skrypty uruchamiane na początku wydarzenia mogą zmieniać istniejące parametry lub dodawać więcej parametrów do tabeli parametrów. W następnym przykładzie mamy


params = {
isEnabled = false
},
interpolants = {
{
objectName = "FocuserGlow",
property = "Enabled",
keys = {
{valueParam = "isEnabled"}
}
}

Parametry pozwalają nam odnieść się do obiektów, które nie istnieją nawet na początku doświadczenia. Na przykład w następnym przykładzie kodu funkcja uruchomiona na początku wydarzenia stworzy obiekt, a ustawi BlackScreenObject wejścia w parametrach, aby wskazać na stworzony obiekt.


{objectParam = "BlackScreenObject",
property = "BackgroundTransparency",
keys = {
{value = 0},
{time = 19, value = 0},
{value = 1},
}}

Konfiguracja wydarzeń, instancji wydarzeń i połączenie z triggerami

Aby uruchomić wydarzenie, będziemy używać zdalnego wydarzenia z klientów lub funkcji z serwera. W następnym przykładzie przekazaliśmy kilka parametrów na RootObject i isEnabled wydarzenia. Wewnętrznie utworzono instancję opisu wydarzenia, parametry zostały rozwiązane na rzeczywistych obiektach, a funkcja zwróciła identyfikator dla instancja


local params = {
RootObject = workspace.Content.Interior.Foyer["Ritual-DemoVersion"]["SealDropoff_" .. missionName],
isEnabled = enabled
}
local eventId = eventManagerFunc:Invoke("Run", {eventName = "Ritual_Init_Dropoff", eventParams = params} )

Możemy zatrzymać uruchomienie wydarzenia, wysyłając funkcję „Stop”:


eventManagerFunc:Invoke("Stop", {eventInstId = cooldownId} )

Interpolants lub inne akcje, które są "kosmetyczne" (nie zmieniaj wymiaru symulacji dla wszystkich graczy), można wykonać na klientach, co może powodować gładkszą interpolację. W opisie wydarzenia możemy zapewnić domyślną wartość dla wszystkich akcji jako naServer = prawdziwy (bez niego domyślna jest klient). Każda akcja może go przeciągnąć poprzez ustawienie jej własnej naServer.

Aby łatwo połączyć uruchomienie wydarzenia z uruchomieniem triggera, użyliśmy funkcji pomocniczych ConnectTriggerToEvent lub ConnectSpawnedTriggerToEvent, z których ten drugi znajduje trigger według nazwy. Aby umożliwić tę samą wydarzenie, aby zostać ur

Parametry wydarzenia

Oprócz parametrów wydarzenia niestandardowych przekazanych z skryptów, inne dane, które można opcjonalnie przekazać podczas tworzenia wydarzenia, obejmują gracza, wzwanie (do zadania po zakończeniu wydarzenia), i wzwanie parametrów. Niektóre wydarzenia powinny być uruchomione tylko dla jednego gracza (zdarzenia z aktywnymi działaniami na klient), podczas gdy inne powinny

Wydarzenia mogą mieć okres regeneracji zdefiniowany przez minCooldownTime i maxCooldownTime. Min i max dostarczają zasięg do skalowania w zależności od liczby graczy, ale nie używaliśmy go w tym demonstracji. Jeś

Wywoływanie skryptów

Możemy nazwać Scripts na określonych kluczowych ramach w sekcji Skrypty . Na przykład:


scripts = {
{startTime = 2, scriptName = "EnablePlayerControls", params = {true}, onServer = false }
}

W poprzednim przykładzie EnablePlayerControls Script musiałby być zarejestrowany z modułem kierownika wydarzeń, tak jak w następujący sposób:


emModule.RegisterFunction("EnablePlayerControls", EnablePlayerControls)

Funkcja RegisterFunction musi być wezwana w skrypcie klienta dla funkcji wzywanych na klient, a w skrypcie serwera dla funkcji onServer = true. Funkcja ta sama otrzyma instancję zdarzeń i parametry, ale w tym przypadku jeden parametr zostanie przesłany z prawdziwą wartością.


local function EnablePlayerControls(eventInst, params)

Odtwarzanie dźwięku

Mamy ograniczoną pomoc dla gry w niepozycyjne audio na kluczowych ramach w sekcji Dźwięki , na przykład:


sounds = {
{startTime = 2, name = "VisTech_ethereal_voices-001"},
}

Uwaga: wezwania końcowe wydarzeń zakończą się, gdy czas trwania wydarzenia dobiegnie końca, ale działania audio mogą nadal odtwarzać się po tym czasie.

Kamera drga podczas uruchomienia

Możemy zdefiniować drżenie kamery w sekcji kameraShakes , tak jak w następujący sposób:


cameraShakes = {
{startTime = 15, shake = "small", sustainDuration = 7, targets = emConfig.ShakeTargets.allPlayers, onServer = true},
}

„targets” można zainicjować tylko dla gracza, który wywołał wydarzenie, allPlayer, lub playersInRadius do gracza, w którym wywołano wydarzenie. Użyliśmy 3-stronnego skryptu dla drgań kamery, i drgań były zapisane: eventManagerDemo.bigShake i eventManagerDemo.smallShake . sustainDuration</

Misje Logika

W sumie jest 7 misji, a tylko 6 z nich używa znaków. Większość misji ma wspólne parametry, choć niektóre tylko dla misji z znakami i teleportacją do uszkodzonych pokoi. Każda misja ma wejście w skryptie DemoConfig z ustawieniem parametrów w mapie Config.Missions :

  • MissionRoot : Katalog wszystkich niezakorumpowanych wersji obiektów.
  • Drzwi: : Drzwi do zablokowania, aż gracz podniesie pieczątkę.
  • SealName / SolvedSealName : Niezależne nazwy pieczątki i zepsucie nazw pieczątki.
  • SealPlaceName : Miejsce, w którym należy umieścić pieczątkę.
  • PlacedSealPlaceholderName : Obiekt Placeholder w miejscu, aby umieścić pieczątkę.
  • TeleportPositionsName : Nazwa katalogu z miejscemholderem, aby zdefiniować pozycje teleportu gracza i obroty, gdy się poruszasz do uszkodzonego pokoju i powrotu do normalnej obszarze. Ten sam nazwa jest używana w obu przypadkach.
  • CorruptRoomName : Nazwy głównych katalogów korzeni (w stosunku do ServerStorage) dla zepsucia pokoi. Klony zepsucia pokoi podczas misji zostaną usunięte po zakończeniu misji.
  • MissionCompleteButtonName : Przycisk oszustwa w zepsutych pokojach, aby natychmiastowo zakończyć misję. Jest to dla celów debugowania .
  • CheatKey : Ta sama cheat jak liczba lub CtrlShift[Numer] .

Niektóre z logiczki misji jest w GameStateManager skryptach, ponieważ zapieczątki i drzwi zapewniają główny przepływ gry dla większości misji, ale większość logiki misji-specific jest w MissionsLogic i MissionsLogicClient skryptach, które okreś

  • Użyj klucza na zamku - Pierwsza misja otwarcia drzwi. Ten typ jest zdefiniowany przez LockName , KeyName .
  • Zgadiwanie przedmiotów - 4 misje zgadują przedmioty. Ten typ jest zdefiniowany przez MatchItems .
  • Ubieranie manekinu używając warstwowego płótna - 1 misja na poddaszu ma graczy zbiera trzy przedmioty. Ten typ jest zdefiniowany przez DressItemsTagList .
  • Kliknij na przedmiot, aby ukończyć - 1 misja ma ten wpisywać, który jest zdefiniowany przez ClickTargetName.

Każdy typ misji ma swoją własną StartMissionFunc i CompleteMissionFunc. Funkcja uruchamiana zwykle czytuje parametry z mapy

Logika dopasowywania pozwala na "używanie" (klikaj, gdy przytrzymujesz) przedmiotów oznaczonych PuzzlePieceXX tagami nad przedmiotami z PuzzleSlotXX tagiem. Są kilka dostępnych opcji jako parametrów w MatchItems mapie

Łapanie

Rozwinięliśmy prosty system chwytu dla trzymania obiektu poprzez przyczepienie obiektu do prawego r

Na każdym klatku sprawdzamy, czy próba chwytu jest w toku. Jeśli gracz jest w zasięgu ręki, zaczynamy grać ToolHoldAnim. Gdy gracz jest w maksymalnym zasięgu ręki, kliент wysyła prośbę do serwera, aby właściwie złapać model (funkcja 2> paramètres).

Skrypt strony serwera ma 2 główne funkcje:

  • Chwytuj - Przyjmuje prośbę klienta o chwytanie modelu.
  • Wypuść - Przyjmuje zapis w wersji gry w wersji gry.

Informacje o tym, co każdy gracz trzyma, są utrzymywane w mapie playerInfos . W funkcji grabu sprawdzamy, czy ten model jest już chwycony przez innego gracza. Jeśli tak - wysyłany jest "EquipWorldFail" do klienta, a anuluje podejmować próbęgrabienia. Uwaga, że musieliśmy zaradzić sytuacjom, w których gracze grabią różne czę

Jeśli można go chwyć, skrypt tworzy dwa Attachments, jeden na ręce prawnej i jeden na obiekcie używając prz

Aby uwolnić uchwycony model, skrypt klienta połączy się z przyciskiem GrabReleaseButton w HUD ScreenGUI. Funkcja Connected wysyłuje wydarzenie na serwer. Na serwerze, uwolnij usuwa Attachments i