게임을 인터랙티브하게 만드는 것은 종종 객체의 속성과 특성을 조작하는 것을 의미합니다:
속성은 객체 클래스의 일부입니다. 예를 들어, BasePart.Anchored 속성은 부분의 물리학을 제어합니다. 육상 경기에서 원반이나 창이 착지하는 순간 이를 고정하고 싶을 수 있으며, 이는 플레이어가 얼마나 멀리 던졌는지를 시각적으로 확인할 수 있도록 해줍니다.
특성은 기본적으로 사용자가 정의하는 사용자 지정 속성입니다. 예를 들어, Plant 참조 프로젝트는 특성을 사용하여 씨앗의 구매 가격과 화분이 담을 수 있는 최대 식물 크기를 설정합니다.
복제 순서
객체를 검색하고 조작하기 시작하기 전에 복제 순서를 이해해야 합니다.
Roblox 엔진은 서버에서 클라이언트로 객체(및 객체의 변경 사항)가 복제되는 순서를 보장하지 않으므로, 특히 Workspace의 클라이언트 스크립트에서 객체에 접근하기 위해서는 Instance:WaitForChild() 메서드가 필수적입니다.
예를 들어, 서버 스크립트가 Workspace의 일부 인스턴스의 속성을 변경한 다음 RemoteEvent:FireAllClients()를 호출할 경우, 속성 변경은 RemoteEvent.OnClientEvent가 발생하기 전이나 후에 클라이언트에 복제될 수 있습니다. 변경 사항이 복제되었다고 가정하기보다 변경 사항을 감지하는 데 사용 가능한 메서드 및 이벤트를 사용하세요. 두 가지 속성 변경과 같은 동일한 유형의 변경 사항은 일반적으로 순서대로 도착합니다.
클라이언트가 처음 게임을 시작할 때, 복제 및 스크립트 실행의 몇 가지 측면은 예측 가능합니다:
클라이언트는 로딩 화면, 자산 및 스크립트와 같은 ReplicatedFirst의 내용을 로드합니다.
LocalScripts (및 Scripts와 RunContext가 Client인 스크립트)에서 ReplicatedFirst가 실행됩니다. 이러한 스크립트는 Instance:WaitForChild()를 사용하지 않고도 ReplicatedFirst에서 객체를 안전하게 가져올 수 있습니다:
-- 안전local ReplicatedFirst = game:GetService("ReplicatedFirst")local LoadingScreen = require(ReplicatedFirst.LoadingScreen)이러한 스크립트는 다른 서비스에서 객체를 안전하게 가져올 수 없습니다. 왜냐하면 해당 서비스가 아직 로드되지 않았을 수 있기 때문입니다:
-- 안전하지 않음local ReplicatedStorage = game:GetService("ReplicatedStorage")local PickupManager = require(ReplicatedStorage.PickupManager)이러한 스크립트에서 다른 서비스에서 객체를 가져오기 위해 WaitForChild()를 사용할 수 있지만, 그렇게 하면 ReplicatedFirst 사용의 이점을 상실하게 됩니다.
클라이언트는 게임의 나머지 부분을 계속 로드합니다.
로드가 완료되면 Loaded 이벤트가 발생하고 IsLoaded()가 true를 반환합니다.
Players.[Player].PlayerScripts의 LocalScripts (복사된 StarterPlayerScripts에서) 실행되며, ReplicatedStorage에 있는 클라이언트 Scripts도 실행됩니다. 이러한 스크립트는 ReplicatedStorage에서 WaitForChild()를 사용하지 않고도 객체를 안전하게 가져올 수 있습니다.
플레이어의 Character 모델이 게임에 생성됩니다.
Workspace.[Character]의 LocalScripts (복사된 StarterCharacterScripts에서) 실행됩니다.
게임이 인스턴스 스트리밍 (Workspace.StreamingEnabled)을 사용하는 경우, 일부 객체가 Workspace에 로드되지 않았을 수 있으므로 Workspace 객체에 접근하기 위해 WaitForChild()를 사용하는 것은 더욱 중요한 안전 조치가 됩니다. 로딩 및 스트리밍 동작 조정을 위한 추가 정보는 스트림 인 및 모델별 스트리밍 제어를 참조하십시오.
객체 가져오기
객체의 속성과 특성을 수정하는 첫 번째 단계는 객체에 대한 참조를 가져오는 것입니다. 가장 간단한 솔루션은 스크립트를 탐색기에서 객체의 자식으로 만들고 script.Parent를 사용하여 객체를 참조하는 것입니다.

local sign = script.Parent
더 보편적인 솔루션은 Instance:FindFirstChild() 또는 Instance:WaitForChild()와 같은 메서드를 사용하여 객체를 서비스에서 가져오는 것입니다.

local ReplicatedStorage = game:GetService("ReplicatedStorage")local signsFolder = ReplicatedStorage:WaitForChild("Signs")local sign = signsFolder:WaitForChild("InteractiveSign")
속성 수정
속성은 간단하게 액세스할 수 있습니다 — 객체 참조 뒤에 .를 사용하면 됩니다 — 다만 모델을 작업하고 있다면 모델 자체가 아닌 개별 파트를 선택해야 할 수도 있습니다.

local ReplicatedStorage = game:GetService("ReplicatedStorage")local chair = ReplicatedStorage:WaitForChild("Chair")chair.LeftArmRest.Size = Vector3.new(10, 1, 10)
특성 만들기
프로그램적으로 특성을 생성할 수 있지만, 더 일반적인 해결책은 스튜디오 사용자 인터페이스에서 기본 값으로 생성하는 것입니다. 그런 다음 스크립트를 사용하여 플레이어의 행동에 따라 값 변경을 수반할 수 있습니다.

스튜디오에서 특성을 만드는 방법에 대한 정보는 인스턴스 특성을 참조하세요.
특성 설정
특성의 값을 수정하려면 이름과 값을 사용하여 Instance:SetAttribute()를 호출합니다.
속성 만들기 또는 수정하기local cabbage = script.Parentcabbage:SetAttribute("Harvestable", true)
특성이 이미 존재하지 않는 경우, 이 메서드는 이를 생성합니다.
특성 값 가져오기
존재하는 특성의 값을 가져오려면 인스턴스에서 Instance:GetAttribute()를 호출합니다.
특성 값 가져오기local cabbage = script.Parentcabbage:SetAttribute("Harvestable", true)local isHarvestable = cabbage:GetAttribute("Harvestable")print(isHarvestable) --> true
유사하게, Instance:GetAttributes()를 호출하여 모든 특성을 가져올 수 있습니다. 이 메서드는 키-값 쌍의 사전을 반환합니다.
모든 특성 가져오기local cabbage = script.Parentlocal cabbageAttributes = cabbage:GetAttributes()print(cabbageAttributes.GrowthRate) --> 2for k, v in cabbageAttributes doprint(k, v)end
특성 삭제
특성을 삭제하려면 값을 nil로 설정합니다.
특성 삭제local cabbage = script.Parentcabbage:SetAttribute("GrowthRate", nil)
변경 사항 감지
속성과 특성의 변경 사항을 수신하기 위한 여러 가지 방법이 있습니다:
- Instance.AttributeChanged 이벤트는 모든 속성의 변경 사항을 수신하고 변경된 특성의 이름을 매개변수로 전달합니다.
- Instance:GetPropertyChangedSignal() 메서드는 하나의 속성 변경 사항을 수신할 수 있게 해주며 매개변수를 전달하지 않습니다.
- Instance:GetAttributeChangedSignal() 메서드는 하나의 특성 변경 사항을 수신할 수 있게 해주며 매개변수를 전달하지 않습니다.
이러한 이벤트와 메서드가 매개변수로 전달하는 정보가 최소화되어 있기 때문에, 이들은 모두 익명 함수에 잘 어울립니다. 특히 Instance:GetPropertyChangedSignal() 및 Instance:GetAttributeChangedSignal()에 적합합니다. 익명 함수 및 이벤트 작업에 대한 더 많은 정보를 보려면 이벤트를 참조하세요.
변경 사항 수신
local cabbage = script.Parent
-- 로컬 함수
local function onAnyPropertyChange(property)
-- 특성 변경 무시
if property ~= "Attributes" then
print(property) --> Name
print(cabbage[property]) --> Cabbage1
end
end
local function onAnyAttributeChange(attribute)
print(attribute) --> Grow, GrowthRate
print(cabbage:GetAttribute(attribute)) --> false, 3
end
-- 변경 사항을 수신하고 로컬 함수에 연결
cabbage.Changed:Connect(onAnyPropertyChange)
cabbage.AttributeChanged:Connect(onAnyAttributeChange)
-- 변경 사항을 수신하고 익명 함수에 연결
cabbage:GetPropertyChangedSignal("Name"):Connect(function()
print(cabbage.Name) --> Cabbage1
end)
cabbage:GetAttributeChangedSignal("GrowthRate"):Connect(function()
print(cabbage:GetAttribute("GrowthRate")) --> 3
end)
-- Changed 및 GetPropertyChangedSignal() 발생
cabbage.Name = "Cabbage1"
-- Changed 및 AttributeChanged 발생
cabbage:SetAttribute("Grow", false)
-- Changed, AttributeChanged, 및 GetAttributeChangedSignal() 발생
cabbage:SetAttribute("GrowthRate", 3)