식물은 플레이어가 심고 물을 주는 참조 경험이므로, 나중에 수확하고 판매할 수 있는 결과 식물을 얻을 수 있습니다.

프로젝트는 Roblox에서 경험을 개발할 때 발생할 수 있는 일반적인 사용 사례에 초점을 둡니다.적용 해당경우 트레이드오프, 타협, 다양한 구현 선택의 이유에 대한 노트를 찾아 자신의 경험에 가장 적합한 결정을 내릴 수 있습니다.
파일 가져오기
- 식물 경험 페이지로 이동합니다.
- 클릭하십시오 ⋯ 버튼과 Studio에서 편집 .
사례 사용
식물은 다음 사용 사례를 다룹니다:
- 세션 데이터 및 플레이어 데이터 지속성
- UI 뷰 관리
- 클라이언트-서버 네트워크
- 처음 사용자 경험(FTUE)
- 하드 및 소프트 통화 구매
또한 이 프로젝트는 다음과 같은 많은 경험에 적용할 수 있는 더 좁은 범위의 문제를 해결합니다.
- 플레이어와 연결된 장소의 영역 사용자 정의
- 플레이어 캐릭터의 이동 속도 관리
- 문자를 따라 이동하는 개체 생성
- 캐릭터가 세계의 어느 부분에 있는지 감지
이 경험에는 너무 작거나, 너무 특화되거나, 흥미로운 디자인 문제에 대한 해결책을 보여주지 않는 여러 사용 사례가 있습니다. 이들은 다루지 않습니다.
프로젝트 구조
경험을 만들 때의 첫 번째 결정은 주로 데이터 모델에 특정 인스턴스를 배치할 위치와 클라이언트 및 서버 코드에 대한 입력 지점을 구성하고 구조화하는 방법을 결정하는 것입니다.
데이터 모델
다음 표에서는 데이터 모델 인스턴스에 배치된 컨테이너 서비스를 설명합니다.
서비스 | 인스턴스 유형 |
---|---|
Workspace | 3D 세계를 나타내는 정적 모델을 포함하며, 특히 플레이어에 속하지 않는 세계의 부분을 나타냅니다.런타임에 이러한 인스턴스를 동적으로 생성, 수정 또는 삭제할 필요가 없으므로 여기에 남겨두는 것이 적합합니다.: 또한 빈 Folder 가 있으며, 플레이어의 농장 모델이 런타임에 추가됩니다. |
Lighting | 대기 및 조명 효과입니다. |
ReplicatedFirst | 로딩 화면을 표시하고 게임을 초기화하는 데 필요한 가장 작은 하위 집합의 인스턴스를 포함합니다.더 많은 인스턴스가 ReplicatedFirst 에 배치되면, ReplicatedFirst 코드가 실행되기 전에 복제하는 데 걸리는 시간이 길어집니다.: 인스턴스 폴더에는 로딩 화면 GUI가 있습니다.: 원본 폴더에는 로딩 화면 코드와 게임의 나머지를 불러오다위해 대기해야 하는 코드가 있습니다.The 3> 6> 는 프로젝트의 모든 클라이언트 측 코드의 입력 지점입니다.8> 7> 0> |
ReplicatedStorage | 클라이언트와 서버에서 모두 액세스가 필요한 모든 인스턴스의 저장소 컨테이너로 사용됩니다.: 종속성 폴더에는 프로젝트에서 사용하는 일부 타사 라이브러리가 있습니다. : 인스턴스 폴더에는 게임에서 다양한 클래스가 사용하는 미리 제작된 인스턴스의 넓은 범위가 존재합니다.: 소스 폴더에는 클라이언트와 서버 모두에서 액세스해야 하는 로드 프로세스에 필요한 모든 코드가 존재합니다. 8> 7> |
ServerScriptService | 프로젝트의 모든 서버 측 코드의 입력 지점으로 기능하는 Script 를 포함합니다. |
ServerStorage | 클라이언트에 복제할 필요가 없는 모든 인스턴스의 저장소 컨테이너로 사용됩니다.: 인스턴스 폴더에는 템플릿 팜 모델이 존재합니다.플레이어가 게임에 참여할 때 4> 에 이 복사본이 배포되어 모든 플레이어에게 복제됩니다.: 원본 폴더에는 서버에 독점적인 모든 코드가 있습니다.8> 7> |
SoundService | 게임에서 사운드 효과에 사용된 개체를 포함합니다. Sound아래 SoundService 에서 이러한 Sound 개체에는 위치가 없으며 3D 공간에서 시뮬레이션되지 않습니다. |
입력 포인트
대부분의 프로젝트는 전체 코드베이스에서 가져올 수 있는 재사용 가능한 ModuleScripts 내에서 코드를 구성합니다.ModuleScripts 는 재사용 가능하지만 보유실행되지는 않습니다; 그들은 Script 또는 LocalScript 에 의해 가져와야 합니다.많은 Roblox 프로젝트에는 큰 수의 Script 및 LocalScript 개체가 있으며, 각각 게임의 행동이나 특정 시스템과 관련이 있으며, 여러 개의 입점을 생성합니다.
식물 마이크로게임의 경우, 모든 클라이언트 코드의 입력 지점인 단일 와 모든 서버 코드의 입력 지점인 단일 를 통해 다른 접근법이 구현됩니다.프로젝트에 대한 올바른 접근 방식은 요구 사항에 따라 다르지만, 단일 입력 지점을 통해 시스템이 실행되는 순서에 대한 더 많은 제어가 제공됩니다.
다음 목록에서는 두 접근법의 장단점을 설명합니다:
- 단일 Script 및 단일 LocalScript 서버 및 클라이언트 코드를 각각 커버합니다.
- 모든 코드가 단일 스크립트에서 초기화되므로 다른 시스템이 시작되는 순서에 대한 더 많은 제어가 가능합니다.
- 시스템 간에 참조로 개체를 전달할 수 있습니다.
고수준 시스템 아키텍처
프로젝트의 최상위 시스템은 아래에 자세히 설명되어 있습니다.이러한 시스템 중 일부는 다른 시스템보다 훨씬 복잡하며, 많은 경우 다른 클래스의 계층에서 기능이 추상화됩니다.

이러한 시스템 각각은 "싱글턴"이며, 관련 클라이언트 또는 서버 start에 의해 대신 초기화되는 비인스턴스화된 클래스입니다.이 가이드의 나중 부분에서 싱글턴 패턴에 대해 자세히 알아볼 수 있습니다.
서버
다음 시스템이 서버와 연결되어 있습니다.
시스템 | 설명 |
---|---|
네트워크 |
|
플레이어 데이터 서버 |
|
시장 |
|
충돌 그룹 관리자 |
|
농장 관리자 서버 |
|
플레이어 객체 컨테이너 |
|
태그 플레이어 |
|
FtueManagerServer |
|
캐릭터 생성기 |
|
클라이ент
다음 시스템이 클라이언트와 연결되어 있습니다.
시스템 | 설명 |
---|---|
네트워크 |
|
플레이어데이터클라이언트 |
|
마켓 클라이언트 |
|
로컬워크점프매니저 |
|
농장 관리자 클라이언트 | 특정 태그가 인스턴스에 적용되는 것을 감지하고 이러한 인스턴스에 "구성 요소" 추가 동작을 생성합니다.요소는 인스턴스에 태그가 추가되고 제거될 때 생성되는 클래스를 참조하며; 이는 농장의 CTA 프롬프트와 플레이어에게 농장 상태를 전달하는 다양한 클래스에 사용됩니다. |
UI설정 |
|
FtueManagerClient |
|
캐릭터 스프린트 |
|
클라이언트-서버 통신
대부분의 Roblox 경험에는 클라이언트와 서버 간의 통신 요소가 포함됩니다.여기에는 서버에서 특정 작업을 수행하도록 요청하는 클라이언트와 클라이언트에 업데이트를 복제하는 서버가 포함될 수 있습니다.
이 프로젝트에서는 추적해야 할 특별 규칙의 수를 줄이기 위해 RemoteEvent 및 RemoteFunction 개체의 사용을 제한하여 클라이언트-서버 통신을 가능한 한 일반적으로 유지합니다.이 프로젝트는 선호 순서대로 다음 방법을 사용합니다:
- 플레이어 데이터 시스템을 통한 복제.
- 태그를 통한 복제.
- 메시징 직접 네트워크 모듈 을 통해.
플레이어 데이터 시스템을 통한 복제
플레이어 데이터 시스템 은 저장 세션 사이에 지속되는 플레이어에 데이터를 연결할 수 있습니다.이 시스템은 클라이언트에서 서버로의 복제와 데이터를 쿼리하고 변경 사항을 구독할 수 있는 API 집합을 제공하여 플레이어 상태의 변경을 서버에서 클라이언트로 복제하는 데 이상적입니다.
예를 들어, 클라이언트에 얼마나 많은 코인이 있는지 알려주기 위해 특별한 UpdateCoins``Class.RemoteEvent 을 발사하는 대신, 다음을 호출하고 클라이언트가 이벤트 PlayerDataClient.updated를 통해 구독하도록 허용할 수 있습니다.
PlayerDataServer:setValue(player, "coins", 5)
물론 이것은 서버 간 복제와 세션 간에 유지하려는 값에만 유용하며, 프로젝트에는 다음과 같은 놀라운 수의 경우가 포함됩니다:
- 현재 FTUE 단계
- 플레이어의 인벤토리
- 플레이어가 가진 코인 수
- 플레이어의 농장 상태
특성을 통한 복제
서버가 특정 Instance에 대한 클라이언트에 사용자 지정 값을 복제해야 하는 상황에서는 특성을 사용할 수 있습니다.Roblox는 특성 값을 자동으로 복제하므로 개체와 관련된 상태를 복제하기 위해 코드 경로를 유지할 필요가 없습니다.또 다른 장점은 이 복제가 인스턴스 자체와 함께 발생한다는 것입니다.
런타임에 생성된 인스턴스에 특히 유용하며, 데이터 모델에 부모로 지정되기 전에 새 인스턴스에 설정된 특성이 인스턴스 자체와 아토믹으로 복제되기 때문입니다.이렇게 하면 RemoteEvent 또는 StringValue를 통해 추가 데이터가 복제되기를 "기다리기" 위해 코드를 작성할 필요가 없습니다.
클라이언트나 서버에서 데이터 모델의 특성을 직접 읽고 GetAttribute() 메서드로 변경에 가입할 수도 있으며, 변경 내용을 GetAttributeChangedSignal() 메서드로 구독할 수도 있습니다.식물 프로젝트에서 이 접근법은 다른 것들 중에서 현재 식물의 상태를 클라이언트에 복제하는 데 사용됩니다.
태그를 통한 복제
CollectionService 는 문자열 태그를 Instance 에 적용할 수 있게 해줍니다. 이것은 인스턴스를 분류하고 클라이언트에 그 분류를 복제하는 데 유용합니다.
예를 들어, CanPlant 태그는 서버에 적용되어 클라이언트에 지정된 냄비가 식물을 수신할 수 있음을 나타냅니다.
네트워크 모듈을 통한 직접 메시지
이전 옵션 중 하나도 적용되지 않는 상황에서는 네트워크 모듈을 통해 사용자 지정 네트워크 호출을 사용할 수 있습니다.이는 클라이언트-서버 통신을 허용하는 프로젝트의 유일한 옵션이므로 클라이언트 요청 전송 및 서버 응답 수신에 가장 유용합니다.
식물은 다양한 클라이언트 요청, 포함:
- 식물 물주기
- 씨앗 심기
- 아이템 구매
이 접근법의 단점은 각 개별 메시지에는 프로젝트 복잡성을 증가시킬 수 있는 사용자 지정 구성이 필요하지만, 가능한 한 회피하여 특히 서버에서 클라이언트 통신에서 이를 피했습니다.
클래스와 싱글톤
Roblox의 인스턴스와 마찬가지로 플랜트 프로젝트의 클래스를 만들고 삭제할 수 있습니다.클래스 구문은 엄격한 형식 검사를 지원하기 위해 여러 변경 사항으로 영감을 받은 idiomatic Lua 접근법을 사용하여 개체 지향 프로그래밍 에 대한 지원을 활성화합니다.
인스턴스화
프로젝트의 많은 클래스가 하나 이상의 Instances와 연결되어 있습니다.지정된 클래스의 개체는 new() 메서드를 사용하여 생성되며, Roblox에서 인스턴스를 생성하는 방법과 일치합니다 Instance.new().
이 패턴은 일반적으로 클래스에 데이터 모델에 물리적 표현이 있고 클래스가 기능을 확장하는 개체에 사용됩니다.좋은 예는 BeamBetween 로, 두 개의 주어진 Beam 개체 사이에 Attachment 개체를 생성하고 빔이 항상 위를 향하도록 부착물을 향하게 유지합니다.이러한 인스턴스는 ReplicatedStorage 에서 미리 제작된 버전에서 복제되거나 new() 에 인수로 전달되어 self 의 개체 내에 저장될 수 있습니다.
해당 인스턴스
위에서 언급했듯이 이 프로젝트의 많은 클래스에는 데이터 모델 표현, 클래스와 일치하고 그것에 의해 조작되는 인스턴스가 있습니다.
클래스 개체가 인스턴스화될 때 이러한 인스턴스를 생성하는 대신, 코드는 일반적으로 Clone() 저장된 아래의 미리 제작된 버전을 선택합니다 Instance 또는 ReplicatedStorage 또는 ServerStorage 아래에 저장됩니다.이러한 인스턴스의 속성을 직렬화하고 클래스의 new() 함수에서 처음부터 만들 수는 있지만, 그렇게 하면 개체를 편집하기가 어려워지고 읽기가 더 어려워집니다.또한 인스턴스를 복제하는 것은 일반적으로 새 인스턴스를 생성하고 런타임에 속성을 사용자 지정하는 것보다 더 빠른 작업입니다.
구성
Luau에서 메타테이블을 사용하여 상속이 가능하지만, 프로젝트는 대신 클래스가 서로를 통해 확장할 수 있도록 구성 을 허용합니다.구성을 통해 클래스를 결합할 때, "자식" 개체는 클래스의 new() 메서드에서 인스턴스화되고 self 아래에 멤버로 포함됩니다.
이 액션예제는 CloseButton 클래스로 감싸는 Button 클래스를 참조하십시오.
정리
방법으로 파괴할 수 있는 것과 마찬가지로, 인스턴스화할 수 있는 클래스도 파괴될 수 있습니다.프로젝트 클래스의 파괴 메서드는 소문자 를 사용하여 코드베이스의 메서드 간의 일관성과 프로젝트 클래스와 Roblox 인스턴스를 구별하기 위해 낮은 대/소문자입니다.
destroy() 메서드의 역할은 개체에 의해 생성된 모든 인스턴스를 파괴하고, 모든 연결을 끊고, 모든 자식 개체에서 destroy() 를 호출하는 것입니다.특히 연결에 중요한데, 인스턴스에 활성 연결이 있는 경우에도 인스턴스나 연결에 대한 참조가 남아 있지 않아도 Luau 가비지 수집기가 정리되지 않기 때문입니다.
싱글턴
이름에서 알 수 있듯이 싱글턴은 하나의 개체만 존재할 수 있는 클래스입니다.그들은 Roblox의 서비스와 프로젝트의 동등한 것입니다.단일 개체에 대한 참조를 저장하고 루아우 코드에서 전달하는 대신, 식물은 반환된 값을 캐시하도록 요구하는 사실을 활용합니다.즉, 서로 다른 장소에서 동일한 싱글턴 ModuleScript 을 요구하면 동일한 반환 개체를 일관되게 제공합니다.이 규칙의 유일한 예외는 다른 환경(클라이언트 또는 서버)이 접근한 ModuleScript에 있을 것입니다.
싱글턴은 불안정한 클래스와 구별되는 점은 그들이 new()을 가지고 있지 않다는 사실입니다.대신, 해당 메서드와 상태를 포함한 개체는 ModuleScript를 통해 직접 반환됩니다.싱글톤이 인스턴스화되지 않으므로 self 구문은 사용되지 않고 메서드는 대신 콜론(.) 대신 점(:)으로 호출됩니다.
엄격한 유형 추론
Luau는 점진적 입력을 지원하므로 일부 또는 전체 코드에 선택적 형식 정의를 추가할 수 있습니다.이 프로젝트에서는 모든 스크립트에 대해 strict 형식 검사가 사용됩니다.이는 Roblox의 스크립트 분석 도구에서 가장 허용적인 옵션이며, 따라서 런타임 전에 형식 오류를 가장 가능성 있게 검색할 수 있습니다.
입력된 클래스 구문
루아에서 클래스를 생성하는 확립된 접근법은 잘 문서화되었습니다 , 그러나 강력한 Luau 타이핑에는 적합하지 않습니다.Luau에서 클래스의 유형을 가져오는 가장 간단한 방법은 typeof() 메서드입니다:
type ClassType = typeof(Class.new())
이는 작동하지만 클래스가 런타임에만 존재하는 값으로 초기화되는 경우, 예를 들어 Player 개체, 매우 유용하지 않습니다.또한, 이디엄적인 Lua 클래스 구문에서 방법을 선언하는 것이 항상 클래스의 인스턴스가 될 것이라는 가정은 형식 추론 엔진이 할 수 있는 가정이 아닙니다.Additionally, the assumption made in idiomatic Lua class syntax is that declaring a method on a class self will always be an instance of that class; this is not an assumption the type inference engine can make.
엄격한 형식 유추를 지원하기 위해 식물 프로젝트는 여러 가지 방법으로 idiomatic Lua 클래스 구문과 다른 솔루션을 사용하며, 일부는 직관적이지 않을 수 있습니다:
- self의 정의는 형식 선언과 생성자에서 모두 복제됩니다.이렇게 하면 유지 관리 부담이 발생하지만, 두 정의가 서로 동기를 잃으면 경고가 표시됩니다.
- 클래스 메서드는 도트로 선언되므로 self 를 명시적으로 ClassType 형식으로 선언할 수 있습니다.메서드는 여전히 예상대로 콜론으로 호출할 수 있습니다.
--!스트릭트
local MyClass = {}
MyClass.__index = MyClass
export type ClassType = typeof(setmetatable(
{} :: {
property: number,
},
MyClass
))
function MyClass.new(property: number): ClassType
local self = {
property = property,
}
setmetatable(self, MyClass)
return self
end
function MyClass.addOne(self: ClassType)
self.property += 1
end
return MyClass
논리적 가드 이후에 형식 캐스트
작성 시 가드 조건문 이후에 값의 유형이 좁혀지지 않습니다.예를 들어, 아래의 가드를 따르면 optionalParameter의 유형이 number로 좁혀지지 않습니다.
--!스트릭트
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
print(optionalParameter + 1)
end
이를 완화하기 위해 새 변수는 이러한 보호자 후에 형식을 명시적으로 캐스팅하여 생성됩니다.
--!스트릭트
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
local parameter = optionalParameter :: number
print(parameter + 1)
end
데이터 모델 계층 트래버스
경우에 따라 코드베이스는 런타임에 생성되는 개체 트리의 데이터 모델 계층을 탐색해야 합니다.이는 형식 검사에 흥미로운 도전을 제시합니다.작성 시점에서 일반적인 데이터 모델 계층을 입력정의할 수는 없습니다.결과적으로 데이터 모델 구조에 사용할 수 있는 유일한 유형 정보가 최상위 인스턴스의 유형인 경우가 있습니다.
이 도전에 대한 하나의 접근법은 캐스트하여 any 및 수정하는 것입니다. 예를 들어:
local function enableVendor(vendor: Model)
local zonePart: BasePart = (vendor :: any).ZonePart
end
이 접근법의 문제는 가독성에 영향을 준다는 것입니다.대신, 프로젝트는 내부적으로 데이터 모델 계층을 트래버스하기 위해 일반 모듈인 를 사용합니다.
local function enableVendor(vendor: Model)
local zonePart: BasePart = getInstance(vendor, "ZonePart")
end
데이터 모델에 대한 유형 엔진의 이해가 진화함에 따라 이와 같은 패턴이 더 이상 필요하지 않을 수 있습니다.
사용자 인터페이스
식물에는 다양한 복잡하고 간단한 2D 사용자 인터페이스가 포함되어 있습니다.여기에는 코인 카운터와 같은 비인터랙티브 헤드업 디스플레이(HUD) 아이템과 상점과 같은 복잡한 상호 작용 메뉴가 포함됩니다.
UI 접근법
사용자가 볼 내용을 설명하는 개체의 계층인 Roblox UI 를 HTML DOM과 비교할 수 있으며, 이는 사용자가 볼 내용을 설명하는 개체의 계층이기 때문입니다.Roblox UI를 만들고 업데이트하는 방법은 강제적인 것과 선언적인 것으로 넓게 분류됩니다. 명령적 및 선언적 연습.
접근법 | 장점과 단점 |
---|---|
명령적 | 강제 접근 방식에서 UI는 Roblox의 다른 인스턴스 계층과 마찬가지로 처리됩니다.UI 구조는 Studio에서 런타임 전에 생성되고 데이터 모델에 추가되며, 일반적으로 직접 StarterGui에 추가됩니다.그런 다음 런타임에 코드는 UI의 특정 부분을 조작하여 크리에이터가 요구하는 상태를 반영합니다.: 이 접근법에는 몇 가지 장점이 있습니다.Studio에서 UI를 처음부터 새로 만들고 데이터 모델에 저장할 수 있습니다.UI 작품가속화할 수 있는 간단하고 시각적인 편집 경험입니다.강제적인 UI 코드는 변경해야 할 내용만 관련되기 때문에, 간단한 UI 변경을 구현하기 쉽습니다.: 주목할 단점은 강제적인 UI 접근 방식에서는 상태가 변환의 형태로 수동으로 구현되어야 하므로 상태의 복잡한 표현을 찾고 디버깅하기가 매우 어려울 수 있다는 점입니다.특히 상태와 UI가 예기치 않은 순서로 상호작용하는 여러 업데이트로 인해 비동기화되면 강제 유형 UI 코드를 개발할 때 오류가 발생하는 것이 일반적입니다.: 강제 접근법으로 인한 또 다른 도전은 UI를 한 번 선언하고 재사용할 수 있는 의미 있는 구성 요소로 분해하기가 더 어렵다는 것입니다.전체 UI 트리가 편집 시간에 선언되기 때문에 일반적인 패턴이 데이터 모델의 여러 부분에서 반복될 수 있습니다. |
선언적 | 선언적 접근에서는 UI 인스턴스의 원하는 상태가 명시적으로 선언되고, 이 상태의 효율적인 구현은 Roact나 Fusion과 같은 라이브러리에 의해 추상화됩니다.: 이 접근법의 장점은 상태 구현이 간단해지고 사용자 인터페이스가 어떻게 보이길 원하는지만 설명하면 되기 때문에 간단합니다.이렇게 하면 버그 식별 및 해결이 크게 쉬워집니다.: 주요 단점은 코드에서 전체 UI 트리를 선언해야 한다는 것입니다.Roact 및 Fusion과 같은 라이브러리에는 이를 더 쉽게 만들기 위한 구문이 있지만, UI를 구성할 때 여전히 시간이 많이 걸리고 편집 경험이 덜 직관적입니다. |
식물은 Roblox에서 UI가 생성되고 조작되는 방법을 직접 보여주는 것이 더 효과적인 개요를 제공한다는 개념 아래에서 명령적 접근법을 사용합니다.선언적 접근법으로는 이러한 일이 불가능할 것입니다.일부 반복된 UI 구조와 논리는 강제적인 UI 디자인의 일반적인 함정을 피하기 위해 재사용 가능한 구성 요소로 추상화됩니다.
고위 아키텍처

레이어 및 구성 요소
In 식물 , 모든 UI 구조는 Layer 또는 Component 입니다.
- Layer 는 미리 제작된 UI 구조를 ReplicatedStorage 에 감싼 최상위 그룹화 단일을 정의합니다.레이어에는 여러 구성 요소가 포함될 수 있거나 자체 논리를 완전히 캡슐화할 수 있습니다.레이어의 예는 인벤토리 메뉴 또는 헤드업 디스플레이의 코인 수 표시기입니다.
- Component는 재사용 가능한 UI 요소입니다.새 구성 요소 개체가 인스턴스화되면 ReplicatedStorage 에서 미리 제작된 템플릿을 복제합니다.구성 요소는 자체에 다른 구성 요소를 포함할 수 있습니다.구성 요소의 예는 일반 버튼 클래스 또는 아이템 목록의 개념입니다.
처리 보기
일반적인 UI 관리 문제는 뷰 처리입니다.이 프로젝트에는 메뉴 및 HUD 항목의 범위가 있으며, 일부는 사용자 입력을 수신하고 표시 또는 활성화 시기를 신중하게 관리해야 합니다.
식물는 UI 레이어가 표시되거나 표시되지 않을 때를 관리하는 UI처리기 시스템으로 이 문제에 접근합니다.게임의 모든 UI 레이어는 HUD 또는 Menu로 분류되며 해당 가시성은 다음 규칙에 따라 관리됩니다.
- Menu 및 HUD 레이어의 활성화된 상태를 전환할 수 있습니다.
- 활성화된 HUD는 활성화된 Menu가 없으면 표시되지 않습니다.
- 활성화된 Menu 레이어는 스택에 저장되고, 한 번에 하나의 Menu 레이어만 표시됩니다.Menu 레이어가 활성화되면 스택의 앞에 삽입되고 표시됩니다.Menu 레이어가 비활성화되면 스택에서 제거되고 큐에서 다음에 활성화된 Menu 레이어가 표시됩니다.
이 접근법은 메뉴를 역사와 함께 탐색할 수 있기 때문에 직관적입니다.다른 메뉴에서 메뉴 하나가 열리면 새 메뉴를 닫으면 이전 메뉴가 다시 표시됩니다.
UI 레이어 싱글턴은 UI처리기 와 등록하여 자신을 등록하고 표시가 변경될 때 발생하는 신호를 제공합니다.
추가 읽기
이 상세한 식물 프로젝트 개요에서 관련 개념과 주제에 대해 자세히 설명하는 다음 가이드를 살펴보고 싶을 수도 있습니다.
- 클라이언트-서버 모델 — Roblox에서 클라이언트-서버 모델의 개요
- 원격 이벤트 및 콜백 — 클라이언트-서버 경계를 넘어 통신을 위한 원격 네트워크 이벤트 및 콜백에 관한 모든 것
- UI — Roblox에서 사용자 인터페이스 개체 및 디자인에 대한 세부 정보.