몇 개의 스크립트를 만든 후 클라이언트-서버 경계의 서로 다른 측면에 있는 스크립트 사이에서 일부 코드를 다시 사용하려면 오래 걸리지 않습니다. 위치에 따라 위치 , ModuleScripts 코드를 다시 사용하려면 경계의 서쪽에 있는 스크립트 사이에서 코드를
모듈 스크립트 생성
스크립트를 배치할 수 있지만 모듈 스크립트는 모듈 스크립트를 배포할 수 있습니다. ReplicatedStorage는 인기 위치이지만 여기에 모듈 스크립트를 저장하면 서버와 클라이언트 사이에서 코드를 재사용할 수 있습니다.
- 새로운 모듈 스크립트를 추가하려면 모듈 스크립트 를 선택합니다.
- 스크립트를 마우스 오른쪽 버튼으로 클릭하고 PickupManager 로 이름을 변경합니다.
- 스크립트를 두 번 클릭하여 스크립트 편집기에서 열립니다.
모듈 스크립트 해부
각 ModuleScript 시작 코드는 다음과 같습니다:
local module = {}return module
이 코드는 모듈 스크립트를 필요로 하는 모든 스크립트에 빈 Luau 테이블을 생성하고 반환합니다.
반환 값은 모든 데이터 유형 을 포함하여 nil 을 제외하고 모든 모듈 스크립트가 반환하는 함수, 테이블 또는 함수 테이블을 반환할 수 있습니다. 반환 값을 생성하려면 모듈 스크립트는 임의의 코드를 실행할 수 있습니다, 다른 모듈 스크립트를 필요로 하는 경우 포함
다음 예시에서는 getPickupBonus라는 단일 함수가 있는 테이블을 반환합니다. 새 모듈 스크립트에 붙여넣으세요:
-- ReplicatedStorage의 ModuleScript
local PickupManager = {}
local defaultMultiplier = 1.25
local rarityMultipliers = {
common = 10,
uncommon = 20,
rare = 50,
legendary = 100
}
-- PickupManager 테이블에 getPickupBonus 함수 추가
PickupManager.getPickupBonus = function(rarity)
local bonus = rarityMultipliers[rarity] * defaultMultiplier
return bonus
end
return PickupManager
함수를 테이블에 추가할 필요는 엄격하지 않지만, 함수 자체를 반환할 수도 있습니다—하지만 좋은 패턴을 팔로우것이 좋습니다—이는 함수를 다른 스크립트에서 호출할 때 쉽게 이해할 수 있는 구문을 제공하고 모듈 스크립트에 시간이 지남에 따라 더 쉽게 함수를 추가할 수 있습니다.
모듈 스크립트 필요
모듈 스크립트를 로드하려면 require() 함수를 호출합니다. 在 ReplicatedStorage 에 새 스크립트를 추가하고 그의 RunContext 를 1> Client1> 로 변경합니다. 그런 다음 다음 코드
ReplicatedStorage의 클라이언트 스크립트
local ReplicatedStorage = game:GetService("ReplicatedStorage")-- ModuleScript에서 반환된 값local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))-- ModuleScript 함수 호출local bonus = PickupManager.getPickupBonus("legendary")print(bonus) --> 125
ServerScriptService에서 스크립트를 요구하려면 동일한 코드를 사용할 수 있습니다.
ServerScriptStorage의 스크립트
local ReplicatedStorage = game:GetService("ReplicatedStorage")-- PickupManager라는 모듈 스크립트의 반환 값을 가져옵니다.local PickupManager = require(ReplicatedStorage:WaitForChild("PickupManager"))
Global.LuaGlobals.필요()를 Class.ModuleScript에서 호출하면 이 모듈이 한 번만 실행되고 단일 항목을 참조로 반환합니다. Global.LuaGlobals.필요()</
클라이언트-서버 경계의 양쪽에서 ModuleScript 을 필요로 하는 경우, ModuleScript 는 각 측면에 대해 고유한 참조를 반환합니다.
패턴
모듈 스크립트에는 코드를 단순화하고 경험의 크기와 복잡성이 증가함에 따라 함정을 피할 수 있는 몇 가지 일반적인 패턴이 있습니다.
데이터 공유
데이터와 개별 개체를 연결하려면, 그들에게 속성을 할당하거나 Configuration 또는 StringValue 와 같은 값 개체를 생성하는 폴더를 만들 수 있습니다. 그러나 객체나 데이터 값을 수십 개 추가하거나 수정하려면 두 접근 방식 모두
동일한 개체의 여러 복사본에 대해 동일한 데이터를 수정하거나 다른 개체에 대해 동일한 데이터를 재사용하려면 ModuleScripts 에 데이터를 저장하십시오. 다른 스크립트에서 데이터를 재사용하는 더 쉬운 방법이며 테이블과 함수를 저장할 수 있습니다.
다음 예시 ModuleScript 인 ReplicatedStorage 에 구성 값을 저장하는 일반적인 총에 대한 구성 값:
ReplicatedStorage의 ModuleScript
local GunConfig = {}GunConfig.MagazineSize = 20GunConfig.AmmoCount = 100GunConfig.Firerate = 600GunConfig.Damage = {["Head"] = 50;["Torso"] = 40;["Body"] = 25;}return GunConfig
사용자 지정 이벤트
사용자 정의 이벤트는 스크립트가 서로 통신할 수 있게 하지만, 개별 BindableEvent 개체에 대한 참조를 추적해야 하는 것은 코드를 어지럽힐 수 있습니다.
Class.ModuleScript|ModuleScripts 를 사용하여 BindableEvents 를 저장하고 ModuleScript 의 메서드에 직접 연결되는 사용자 지정 이벤트 핸들러를 제공할 수 있습니다.
Class.ReplicatedStorage|ReplicatedStorage의 다음 ReplicatedStorage에는 스위치가 상태를 변경할 때 실행되는 사용자 지정 이벤트가 있습니다.
ReplicatedStorage의 ModuleScript
local Switch = {}
-- 스위치가 변경될 때 모든 스크립트가 듣기 좋도록 바인딩을 만드는 것
local bindableEvent = Instance.new("BindableEvent")
Switch.Changed = bindableEvent.Event
local state = false
function Switch.flip()
state = not state
bindableEvent:Fire(state)
end
return Switch
Class.ReplicatedStorage의 다음 클라이언트 스크립트는 Switch.Changed 이벤트가 발생했을 때 호출할 함수를 연결합니다.
ReplicatedStorage의 스크립트
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Switch = require(ReplicatedStorage:WaitForChild("Switch"))
Switch.Changed:Connect(function(newState)
print("Switch state is now", newState)
end
-- 몇 번 뒤집기를 테스트하십시오
task.wait(1)
Switch.flip()
task.wait(1)
Switch.flip()
캡슐화
캡슐화는 복잡성을 숨기기 위해 개체 또는 스크립트 논리 주위에 추상화 레이어를 만드는 관행입니다. ModuleScripts 를 사용하여 Roblox 개체를 사용자 정의 Lua 함수로 캡슐화하여 코드를 간소화할 수 있습니다.
예를 들어, 캡슐화를 사용하여 다음을 수행할 수 있습니다.
- 단일 RemoteEvent 개체로 교차 네트워크 통신을 간소화합니다.
- 오류 처리 코드를 DataStoreService와 같은 민감한 서비스에 감싼다.
- Roblox 개체 기능을 제어하거나 확장하기 위해 사용자 정의 메서드를 정의합니다.
게임에 네트워킹을 구현하기 위해 수십 개의 개별 RemoteEvent 개체를 추적하는 것은 어렵습니다. ModuleScript 를 사용하여 단일 RemoteEvent 를 캡슐화
아래 예에서, ModuleScript라는 이름의 NetworkManagerClient는 Class.RemoteEvent:
Class.ReplicatedFirst의 다음 ReplicatedFirst는 클라이언트 스크립트를 호출하여 네트워크 메시지를 전송할 수 있는 캡슐화된 기능을 제공합니다.
네트워크 모듈
-- NetworkManagerClient라는 이름의 ReplicatedFirst 내 ModuleScript
local NetworkManagerClient = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
-- 원격 개체의 FireServer 함수 캡슐화
function NetworkManagerClient.FireServer(id, ...)
remoteEvent:FireServer(id, ...)
end
return NetworkManagerClient
Class.ServerScriptService 의 다음 ServerScriptService 는 모든 스크립트에서 BindableEvents 를 사용하여 특정 ID에 연결합니다. 클라이언트가 네트워크 메시지를 보낼 때, 지정된 ID와 연관된 각 1>Class.BindableEvent1> 가 실행됩니다.
-- NetworkManagerServer라는 이름의 ServerScriptService 내 ModuleScript
local NetworkManagerServer = {}
local networkSignalList = {}
function NetworkManagerServer.GetServerEventSignal(id)
local bindableEvent = Instance.new("BindableEvent")
-- 새로운 바인더블 이벤트를 id에 연결하기
table.insert(networkSignalList, {
id = id,
bindableEvent = bindableEvent,
})
return bindableEvent.Event
end
-- 연결 대상
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEvent")
remoteEvent.OnServerEvent:Connect(function(player, id, ...)
-- 받은 원격 이벤트의 아이디와 일치하는 바인딩 가능한 모든 이벤트 찾기
for _, signal in networkSignalList do
if signal.id == id then
signal.bindableEvent:Fire(player, ...)
end
end
end)
return NetworkManagerServer
다음 LocalScript는 옵션 RequestA 와 함께 ID Hello 를 사용하여 메시지를 보냅니다.
-- ReplicatedFirst의 LocalScriptlocal ReplicatedFirst = game:GetService("ReplicatedFirst")local NetworkManagerClient = require(ReplicatedFirst:WaitForChild("NetworkManagerClient"))NetworkManagerClient.FireServer("RequestA", "Hello")
다음 Script 는 네트워크 메시지 ID RequestA 에 연결하고 요청을 받을 때 모든 추가 매개 변수를 포함한 명령문을 출력합니다.
-- ServerScriptService의 스크립트
local ServerScriptService = game:GetService("ServerScriptService")
local NetworkManagerServer = require(ServerScriptService:WaitForChild("NetworkManagerServer"))
NetworkManagerServer.GetServerEventSignal("RequestA"):Connect(function(player, ...)
print("Received RequestA from", player, ...)
end)