Reutilizar código

*Este conteúdo é traduzido por IA (Beta) e pode conter erros. Para ver a página em inglês, clique aqui.

Depois de criar alguns scripts, nunca demora muito antes que você queira reutilizar algum código entre eles.Dependendo de localização, ModuleScripts deixe você reutilizar código entre scripts em diferentes lados da fronteira cliente-servidor ou no mesmo lado da fronteira.

Você pode colocar scripts de módulo em qualquer lugar que coloque scripts, mas ReplicatedStorage é um local popular; armazenar scripts de módulo aqui permite que você reutilize código entre o servidor e os clientes.

Anatomia de um script de módulo

No Roblox Studio, adicione um script de módulo a ReplicatedStorage e renomeie-o para PickupManager. Cada ModuleScript começa com o seguinte código:


local module = {}
return module

Este código cria uma tabela Luau vazia e retorna-a a qualquer script que requer o script do módulo.

O valor de retorno pode ser qualquer tipo de dado exceto nil, mas a maioria dos scripts de módulo retorna uma função, uma tabela ou uma tabela de funções.Para gerar seu valor de retorno, os scripts de módulo podem, claro, executar código arbitrário, que inclui exigir outros scripts de módulo.

O seguinte exemplo retorna uma tabela com uma única função chamada getPickupBonus. Cole-a no novo script de módulo:


-- ModuleScript em ReplicatedStorage
local PickupManager = {}
local defaultMultiplier = 1.25
local rarityMultipliers = {
common = 10,
uncommon = 20,
rare = 50,
legendary = 100
}
-- Adicione a função getPickupBonus à tabela PickupManager
PickupManager.getPickupBonus = function(rarity)
local bonus = rarityMultipliers[rarity] * defaultMultiplier
return bonus
end
return PickupManager

Adicionar a função a uma tabela não é estritamente necessário - você pode apenas retornar a própria função -, mas é um bom padrão a seguir; dá a você uma síntese fácil de entender quando você chamar a função de outro script e permite que você adicione facilmente mais funções ao script do módulo ao longo do tempo.

Exigir scripts de módulo

Para carregar um script de módulo, você chama a função require().Em ReplicatedStorage, adicione um novo script e altere seu RunContext para Client.Então adicione o seguinte código para chamar a função PickupManager.getPickupBonus:

Script do cliente no ReplicatedStorage

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obtenha o valor retornado pelo ModuleScript
local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))
-- Chamar uma função de ModuleScript
local bonus = PickupManager.getPickupBonus("legendary")
print(bonus) --> 125

Armazenar scripts de módulo em ReplicatedStorage deixa você compartilhar código entre o servidor e o cliente, para que você possa usar o mesmo código para exigir o script de ServerScriptService :

Script em ServerScriptService

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

Quando você chama require() em um ModuleScript, ele é executado uma vez e retorna um único item como referência.Chamar novamente retorna exatamente a mesma referência, o que significa que se você modificar uma tabela retornada ou , as chamadas subsequentes retornam essa referência modificada.O próprio módulo não é executado várias vezes.

Se você precisar de um ModuleScript de ambos os lados da fronteira cliente-servidor, como no exemplo acima, o ModuleScript retorna uma referência única para cada lado.

Padrões

Os scripts de módulo têm alguns padrões comuns que você pode usar para simplificar seu código e evitar armadilhas à medida que sua experiência cresce em tamanho e complexidade.

Compartilhamento de dados

Para associar dados a objetos individuais, você pode atribuir atributos a eles ou criar Configuration pastas com objetos de valor, como StringValue ou IntValue.No entanto, ambas as abordagens são problemáticas se você quiser adicionar ou modificar dezenas de objetos ou valores de dados.Eles também não armazenam tabelas ou funções.

Se você quiser modificar os mesmos dados para várias cópias do mesmo objeto ou reutilizar os mesmos dados para diferentes objetos, armazene os dados em ModuleScripts .É uma maneira mais fácil de reutilizar os dados em outros scripts e você pode armazenar tabelas e funções.

O seguinte exemplo ModuleScript em ReplicatedStorage armazena os valores de configuração para uma arma genérica:

ModuleScript em ReplicatedStorage

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

Eventos personalizados

Eventos personalizados permitem que scripts se comuniquem entre si, mas ter que acompanhar referências a objetos individuais BindableEvent pode sobrecarregar seu código.

Você pode usar ModuleScripts para armazenar BindableEvents e fornecer manipuladores de eventos personalizados que estão diretamente ligados aos métodos de ModuleScript.

O seguinte ModuleScript em ReplicatedStorage tem um evento personalizado que dispara quando o interruptor muda de estado:

ModuleScript em ReplicatedStorage

local Switch = {}
-- Criar vinculável para que qualquer script possa ouvir quando o interruptor foi alterado
local bindableEvent = Instance.new("BindableEvent")
Switch.Changed = bindableEvent.Event
local state = false
function Switch.flip()
state = not state
bindableEvent:Fire(state)
end
return Switch

O seguinte script de cliente em ReplicatedStorage conecta uma função para ser chamada quando o evento Switch.Changed é disparado.

Script em ReplicatedStorage

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Switch = require(ReplicatedStorage:WaitForChild("Switch"))
Switch.Changed:Connect(function(newState)
print("Switch state is now", newState)
end
-- Teste virar algumas vezes
task.wait(1)
Switch.flip()
task.wait(1)
Switch.flip()

Encapsulamento

Encapsulamento é a prática de criar uma camada de abstração em torno de objetos ou lógica de script para esconder a complexidade.Você pode usar ModuleScripts para encapsular objetos do Roblox com funções Luau personalizadas para simplificar o código.

Por exemplo, você pode usar a encapsulagem para:

  • Simplifique a comunicação entre redes com um único ObjetoRemoteEvent .
  • Envolva o código de manipulação de erros em torno de serviços sensíveis, como DataStoreService.
  • Defina métodos personalizados para controlar ou estender recursos de objetos do Roblox.

É difícil acompanhar dezenas de objetos individuais RemoteEvent para implementar a rede em seu jogo.Você pode usar um ModuleScript para encapsular um único RemoteEvent para ajudar a simplificar esse problema.Ao incluir um argumento exclusivo id único, você ainda pode enviar diferentes mensagens de rede usando apenas um único RemoteEvent.

No exemplo abaixo, o ModuleScript chamado NetworkManagerClient encapsula o método RemoteEvent:FireServer() para incluir esse argumento extra id .Além disso, este ModuleScript refere-se ao próprio objeto RemoteEvent para que você não precise referenciá-lo em outras partes do código.Você só precisa exigir isso ModuleScript para enviar mensagens de rede e não precisa lidar com RemoteEvent objetos no resto de sua base de código.

O seguinte ModuleScript em ReplicatedFirst fornece uma função encapsulada que você pode chamar em seus scripts de cliente para enviar uma mensagem de rede:

Modulo de Rede

-- ModuleScript em ReplicatedFirst chamado NetworkManagerClient
local NetworkManagerClient = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
-- Encapsulando a função FireServer do Objetoremoto
function NetworkManagerClient.FireServer(id, ...)
remoteEvent:FireServer(id, ...)
end
return NetworkManagerClient

O seguinte ModuleScript em ServerScriptService usa BindableEvents para que cada script se conecte a um ID específico.Quando um cliente envia uma mensagem de rede, cada BindableEvent associada ao ID especificado é acionada.


-- ModuleScript em ServerScriptService chamado NetworkManagerServer
local NetworkManagerServer = {}
local networkSignalList = {}
function NetworkManagerServer.GetServerEventSignal(id)
local bindableEvent = Instance.new("BindableEvent")
-- Vincular o novo BindableEvent ao ID
table.insert(networkSignalList, {
id = id,
bindableEvent = bindableEvent,
})
return bindableEvent.Event
end
-- Conectando a
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
remoteEvent.OnServerEvent:Connect(function(player, id, ...)
-- Encontrar todos os eventos bindáveis que correspondem ao ID do evento remoto recebido
for _, signal in networkSignalList do
if signal.id == id then
signal.bindableEvent:Fire(player, ...)
end
end
end)
return NetworkManagerServer

O seguinte LocalScript envia uma mensagem com o ID RequestA com um argumento opcional Hello.


-- LocalScript em ReplicatedFirst
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local NetworkManagerClient = require(ReplicatedFirst:WaitForChild("NetworkManagerClient"))
NetworkManagerClient.FireServer("RequestA", "Hello")

O seguinte Script conecta-se ao ID da mensagem de rede RequestA e imprime uma declaração com quaisquer parâmetros adicionais quando recebe a solicitar / pedir.


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