Ponowne wykorzystanie kodu

*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.

Po utworzeniu kilku skryptów nigdy nie minie dużo czasu, zanim będziesz chciał ponownie wykorzystać jakiś kod między nimi.W zależności od lokalizacji, ModuleScripts pozwala ponownie używać kodu między skryptami po obu stronach granicy klienta-serwera lub na tej samej stronie granicy.

Możesz umieścić skrypty modułu w dowolnym miejscu, gdzie umieszczasz skrypty, ale ReplicatedStorage jest popularną lokalizacją; przechowywanie skryptów modułu tutaj pozwala ponownie używać kodu między serwerem a klientami.

Anatomia skryptu modułu

W Roblox Studio dodaj skrypt modułu do ReplicatedStorage i zmień nazwę na PickupManager. Każdy ModuleScript zaczyna się następującym kodem:


local module = {}
return module

Ten kod tworzy pustą tabelę Luau i zwraca ją do każdego skryptu, który wymaga skryptu modułu.

Wartość zwrotna może być dowolnym typem danych z wyjątkiem nil, ale większość skryptów modułowych zwraca funkcję, tabelę lub tabelę funkcji.Aby wygenerować swoją wartość zwrotną, skrypty modułu mogą oczywiście uruchomić dowolny kod, który obejmuje wymaganie innych skryptów modułowych.

Poniższy przykład zwraca tabelę z jedną funkcją o nazwie getPickupBonus. Wklej ją do nowego skryptu modułu:


-- Modułowy skrypt w ReplicatedStorage
local PickupManager = {}
local defaultMultiplier = 1.25
local rarityMultipliers = {
common = 10,
uncommon = 20,
rare = 50,
legendary = 100
}
-- Dodaj funkcję getPickupBonus do tabeli PickupManager
PickupManager.getPickupBonus = function(rarity)
local bonus = rarityMultipliers[rarity] * defaultMultiplier
return bonus
end
return PickupManager

Dodawanie funkcji do tabeli nie jest ściśle konieczne - możesz po prostu zwrócić samą funkcję - ale jest to dobry wzór do naśladowania; daje ci łatwą do zrozumienia składnię, gdy wzywasz funkcję z innego skryptu, i pozwala ci łatwo dodawać więcej funkcji do skryptu modułu z czasem.

Wymagaj skryptów modułowych

Aby załadować skrypt modułu, wezwij funkcję require().W ReplicatedStorage, dodaj nowy skrypt i zmień jego RunContext na Client.Następnie dodaj następujący kod, aby wezwać funkcję PickupManager.getPickupBonus:

Skrypt klienta w ReplicatedStorage

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź wartość zwróconą przez ModuleScript
local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))
-- Wezwij funkcję ModuleScript
local bonus = PickupManager.getPickupBonus("legendary")
print(bonus) --> 125

Przechowywanie skryptów modułu w ReplicatedStorage pozwala na udostępnianie kodu między serwerem a klientem, więc możesz używać tego samego kodu, aby wymagać skryptu z ServerScriptService :

Skrypt w ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))

Gdy wywołasz require() na ModuleScript, uruchamia się raz i zwraca pojedynczy element jako odniesienie.Wezwanie ponownie zwraca dokładnie tę samą referencję, co oznacza, że jeśli zmodyfikujesz zwróconą tabelę lub , kolejne wezwania zwracają tę zmienioną referencję.Sama moduł nie uruchamia się wielokrotnie.

Jeśli potrzebujesz ModuleScript z obu stron granicy klient-serwer, tak jak w powyższym przykładzie, ModuleScript zwraca unikalny odniesienie dla każdej strony.

Wzory

Skrypty modułów mają pewne wspólne wzory, których możesz użyć, aby uprościć swój kod i uniknąć pułapek, gdy twoje doświadczenie rośnie w rozmiarze i złożoności.

Dzielenie danych

Aby powiązać dane z poszczególnymi obiektami, możesz przypisać im atrybuty lub utworzyć Configuration foldery z obiektami wartości, takimi jak StringValue lub IntValue.Jednak oba podejścia są problematyczne, jeśli chcesz dodać lub zmodyfikować dziesiątki obiektów lub wartości danych.Nie przechowują też tabel lub funkcji.

Jeśli chcesz zmodyfikować te same dane dla wielu kopii tego samego obiektu lub ponownie wykorzystać te same dane dla różnych obiektów, przechowuj dane w ModuleScripts .To łatwiejszy sposób na ponowne wykorzystanie danych w innych skryptach i możesz przechowywać tabele i funkcje.

Poniższy przykład ModuleScript w ReplicatedStorage przechowuje wartości konfiguracyjne dla ogólnego pistoletu:

Modułowy skrypt w ReplicatedStorage

local GunConfig = {}
GunConfig.MagazineSize = 20
GunConfig.AmmoCount = 100
GunConfig.Firerate = 600
GunConfig.Damage = {
["Head"] = 50;
["Torso"] = 40;
["Body"] = 25;
}
return GunConfig

Własne wydarzenia

Wydarzenia niestandardowe umożliwiają skryptom komunikowanie się ze sobą, ale konieczność śledzenia odniesień do poszczególnych obiektów BindableEvent może zagracić twój kod.

Możesz użyć ModuleScripts do przechowywania BindableEvents i dostarczania niestandardowych menedżerów zdarzeń, które są bezpośrednio powiązane z metodami ModuleScript.

Poniższe ModuleScript w ReplicatedStorage ma własne wydarzenie, które uruchamia się, gdy przełącznik zmienia stan:

Modułowy skrypt w ReplicatedStorage

local Switch = {}
-- Tworzenie wiązania, tak aby każde skrypt mogło słuchać, gdy przełącznik został zmieniony
local bindableEvent = Instance.new("BindableEvent")
Switch.Changed = bindableEvent.Event
local state = false
function Switch.flip()
state = not state
bindableEvent:Fire(state)
end
return Switch

Następujący skrypt klienta w ReplicatedStorage połącza funkcję do wezwania, gdy wydarzenie Switch.Changed wystąpi.

Skrypt w ReplicatedStorage

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Switch = require(ReplicatedStorage:WaitForChild("Switch"))
Switch.Changed:Connect(function(newState)
print("Switch state is now", newState)
end
-- Przetestuj przewracanie kilka razy
task.wait(1)
Switch.flip()
task.wait(1)
Switch.flip()

Zakapsułowanie

Zakapsułkowanie to praktyka tworzenia warstwy abstrakcji wokół obiektów lub logiki skryptowania, aby ukryć złożoność.Możesz użyć ModuleScripts , aby owinąć obiekty Roblox za pomocą niestandardowych funkcji Luau, aby uprościć kod.

Na przykład możesz użyć kapsułowania do:

  • Uprość komunikację między sieciami za pomocą pojedynczego obiektu RemoteEvent.
  • Owiń kod obsługi błędów wokół wrażliwych usług, takich jak DataStoreService.
  • Określ niestandardowe metody do kontroli lub rozszerzenia funkcji obiektu Roblox.

Trudno jest śledzić dziesiątki pojedynczych obiektów RemoteEvent w celu wdrożenia sieci w gra.Możesz użyć ModuleScript, aby zamknąć pojedyncze RemoteEvent, aby pomóc uprościć ten problem.Dodając unikalny argument id, nadal możesz wysyłać różne wiadomości sieciowe, używając tylko jednego RemoteEvent.

W poniższym przykładzie ModuleScript o nazwie NetworkManagerClient owija metodę RemoteEvent:FireServer() w celu uwzględnienia tego dodatkowego argumentu id.Ponadto ten ModuleScript odnosi się do samego obiektu RemoteEvent, więc nie musisz go odwoływać w innych częściach kodu.Musisz tylko wymagać tego ModuleScript wysyłania wiadomości sieciowych i nie musisz zajmować się obiektami RemoteEvent w pozostałej części kodu.

Następująca ModuleScript w ReplicatedFirst dostarcza zaszyfrowaną funkcję, którą możesz wezwać na swoje skrypty klienta, aby wysłać wiadomość sieciową:

Moduł sieciowy

-- ModuleScript w ReplicatedFirst o nazwie NetworkManagerClient
local NetworkManagerClient = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
-- Opakowanie funkcji FireServer zdalnego obiektu
function NetworkManagerClient.FireServer(id, ...)
remoteEvent:FireServer(id, ...)
end
return NetworkManagerClient

Następujące ModuleScript w ServerScriptService używa BindableEvents dla każdego skryptu, aby połączyć się z określoną ID.Kiedy klient wysyła wiadomość sieciową, każda BindableEvent powiązana z określonym ID się pali.


-- ModuleScript w ServerScriptService o nazwie NetworkManagerServer
local NetworkManagerServer = {}
local networkSignalList = {}
function NetworkManagerServer.GetServerEventSignal(id)
local bindableEvent = Instance.new("BindableEvent")
-- Połączenie nowego BindableEvent z ID
table.insert(networkSignalList, {
id = id,
bindableEvent = bindableEvent,
})
return bindableEvent.Event
end
-- Łączenie z
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
remoteEvent.OnServerEvent:Connect(function(player, id, ...)
-- Znajdowanie każdego zdarzenia wiązalnego, które pasuje do ID otrzymanego zdarzenia zdalnego
for _, signal in networkSignalList do
if signal.id == id then
signal.bindableEvent:Fire(player, ...)
end
end
end)
return NetworkManagerServer

Następująca LocalScript wysyła wiadomość z ID RequestA z opcjonalnym argumentem Hello.


-- Lokalny skrypt w ReplicatedFirst
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local NetworkManagerClient = require(ReplicatedFirst:WaitForChild("NetworkManagerClient"))
NetworkManagerClient.FireServer("RequestA", "Hello")

Poniższy Script łączy się z ID sieciowym wiadomości RequestA i drukuje oświadczenie z dowolnymi dodatkowymi parametrami po otrzymaniu prośba.


-- Skrypt w ServerScriptService
local ServerScriptService = game:GetService("ServerScriptService")
local NetworkManagerServer = require(ServerScriptService:WaitForChild("NetworkManagerServer"))
NetworkManagerServer.GetServerEventSignal("RequestA"):Connect(function(player, ...)
print("Received RequestA from", player, ...)
end)