概要
API 参考
属性
Generator
代码示例
默认生成器模块
-- 生成器模块是一个 ModuleScript,定义了 ProceduralModel 如何构建其内容。
-- 请参阅 https://create.roblox.com/docs/reference/engine/classes/ProceduralModel 获取详细信息。
--
-- 作为生成器使用时,ModuleScript 必须返回一个包含两个字段的表:
-- * `Attributes` - 一个默认值的表。每个键都会在使用此生成器的每个
-- ProceduralModel 上作为属性出现。用户可以在属性面板中调整这些
-- 属性,以使用新输入重新运行生成。
-- * `OnGenerate` - 引擎调用的函数,用于(重)构建模型的内容。
--
-- 此脚本或其放置位置没有特殊之处。它可以位于 DataModel 中的任何地方,
-- 并且 ProceduralModel 上的 `Generator` 属性可以重新分配指向它。
-- 下面的类型注释是可选的,但在此文档中以明确所需形状。
-- `GenerationFunctionParams` 每次生成运行时都会传递给 `OnGenerate`。它公开:
-- * `Attributes` - ProceduralModel 上当前的属性值。
-- * `Size` - 要在其中生成的边界体积(来自 `ProceduralModel.Size`)。
-- * `Pause` - 一个合作的暂停。在长循环内部调用 `parameters:Pause()`,以便大型
-- 生成不会阻塞调用线程;引擎可能会稍后恢复您。
type GenerationFunctionParams<Attributes> = {
Attributes: Attributes,
Size: Vector3,
Pause: (self: GenerationFunctionParams<Attributes>) -> (),
}
-- `GeneratorModuleDefinition` 是 ModuleScript 必须返回的表。
-- `OnGenerate` 必须不返回值;而是将生成的实例父级放入 `targetContainer`。
-- 任何父级到 `targetContainer`(或其后代)的实例都会成为生成的输出。
type GeneratorModuleDefinition<Attributes> = {
Attributes: Attributes,
OnGenerate: (
parameters: GenerationFunctionParams<Attributes>,
targetContainer: GeneratedFolder
) -> (),
}
-- 默认属性。这里的每个条目作为可编辑属性出现在 ProceduralModel 上。
-- 固定的 `RandomSeed` 保持生成的确定性:相同的输入总是产生相同的
-- 输出,这一点很重要,因为在用户编辑属性时,生成可能会多次运行。
local defaultAttributes = {
BorderThickness = 1,
RandomSeed = 142376088,
}
local Generator: GeneratorModuleDefinition<typeof(defaultAttributes)> = {
Attributes = defaultAttributes,
OnGenerate = function(parameters, targetContainer)
-- 输入。`parameters.Attributes` 反映用户在
-- ProceduralModel 上设置的内容;`parameters.Size` 是要构建的边界框。
local borderThickness = parameters.Attributes.BorderThickness
local random = Random.new(parameters.Attributes.RandomSeed)
local size = parameters.Size
-- 派生值。上述种子 `random` 使得这些值根据 RandomSeed 可复制。
local minSize = math.min(size.X, size.Y, size.Z)
local baseColor = Color3.fromHSV(random:NextNumber(0.5, 0.8), 0.7, 0.8)
local outlineColor = Color3.fromHSV(random:NextNumber(), 0.4, 0.25)
-- 小帮助函数使下面的构建从上到下可读。您不需要
-- 这样的帮助函数来编写生成器;它们仅减少了重复。
local function assignProperties(instance: Instance, properties: { [string]: unknown })
-- 最后设置 Parent,以便其他属性在实例进入
-- DataModel 并触发 Changed 事件之前就位。
for name, value in properties do
if name ~= "Parent" then
(instance :: any)[name] = value
end
end
if properties.Parent ~= nil then
instance.Parent = properties.Parent :: Instance
end
return instance
end
local function createInstance(className: string, properties: { [string]: unknown })
return assignProperties(Instance.new(className), properties)
end
local function createPartWithDefaults(properties: { [string]: unknown })
-- 生成的部件通常是锚定和不碰撞的;根据需要覆盖每个部件。
local part = createInstance("Part", {
Anchored = true,
CanCollide = false,
Color = baseColor,
Material = Enum.Material.SmoothPlastic,
BottomSurface = Enum.SurfaceType.Smooth,
TopSurface = Enum.SurfaceType.Smooth,
})
return assignProperties(part, properties)
end
-- 下面的所有内容都父级到 `targetContainer`,这是实例成为
-- 生成输出一部分的方式。在这里没有父级的实例将被丢弃。
-- 用作广告牌装饰的不可见边界部分。
local bounds = createPartWithDefaults({
Name = "Bounds",
Parent = targetContainer,
Transparency = 1,
Size = size,
})
-- 下面有一个边框轮廓的凹陷平台。
local base = createPartWithDefaults({
Name = "PlatformBase",
Parent = targetContainer,
Color = baseColor,
CFrame = CFrame.new(0, (-size.Y + 1) / 2, 0),
Size = Vector3.new(
size.X - 2 * borderThickness,
1.01,
size.Z - 2 * borderThickness
),
})
local outline = createPartWithDefaults({
Name = "PlatformOutline",
Parent = targetContainer,
Color = outlineColor,
Position = Vector3.yAxis * (-size.Y + 1) / 2,
Size = Vector3.new(size.X, 1, size.Z),
})
-- "Hello World!" 广告牌。生成器可以创建任何实例类型,而不只是部件。
local billboard = createInstance("BillboardGui", {
Name = "Text",
Parent = targetContainer,
Adornee = bounds,
LightInfluence = 0,
Size = UDim2.fromScale(minSize, minSize),
})
local textLabel = createInstance("TextLabel", {
Name = "HelloWorld",
Parent = billboard,
AnchorPoint = Vector2.new(0.5, 0.5),
BackgroundTransparency = 1,
Position = UDim2.fromScale(0.5, 0.5),
Size = UDim2.fromScale(1, 1),
Text = "Hello World!",
TextColor3 = baseColor,
TextScaled = true,
TextStrokeTransparency = 0,
})
local textStroke = createInstance("UIStroke", {
Parent = textLabel,
Color = outlineColor,
Thickness = borderThickness * 3,
})
end,
}
-- 返回模块定义使得此 ModuleScript 可用作 `Generator`。
return Generator经典梯子生成器模块
-- 生成器模块是一个 ModuleScript,返回一个包含 `Attributes` 和 `OnGenerate` 的表。
-- 将此 ModuleScript 分配给 ProceduralModel 的 `Generator` 属性时,会在模型的大小、属性或模块源更改时运行 `OnGenerate`。
-- 请参阅 https://create.roblox.com/docs/reference/engine/classes/ProceduralModel。
local ClassicRobloxLadderGenerator = {}
-- 默认属性值。每个键都成为任何使用该生成器的 ProceduralModel 上可编辑的属性,并显示在 Studio 属性面板中的 Attributes 下。编辑任何
-- 它们都会使用新值重新运行 `OnGenerate`。
ClassicRobloxLadderGenerator.Attributes = {
RungSpacing = 2,
RungThickness = 1,
PostSize = 1,
Color = Color3.new(0.5, 0.3, 0),
}
-- `OnGenerate` 由引擎调用以构建模型的内容。
-- 合同:
-- * `parameters.Size` - 要在其中构建的边界框(来自 `ProceduralModel.Size`)。
-- * `parameters.Attributes` - ProceduralModel 上的当前属性值。
-- * `parameters:Pause()` - 协作让出;在长循环内调用,以便大型生成不会阻塞线程。
-- * `targetContainer` - 在这里(或其子孙中)父级的任何内容都成为输出。
-- * 不要从 `OnGenerate` 返回值;输出通过 `targetContainer` 进行通信。
ClassicRobloxLadderGenerator.OnGenerate = function(parameters, targetContainer)
local size = parameters.Size
local rungThickness = parameters.Attributes.RungThickness
local postSize = parameters.Attributes.PostSize
local count = (size.Y - rungThickness) // parameters.Attributes.RungSpacing + 1
local function createPart(position, size)
local part = Instance.new("Part")
part.Size = size
part.Position = position
part.Anchored = true
part.Color = parameters.Attributes.Color
part.TopSurface = Enum.SurfaceType.Smooth
part.BottomSurface = Enum.SurfaceType.Smooth
-- 将对象放入 `targetContainer` 是将部件添加到生成的输出中的方法。
part.Parent = targetContainer
end
-- 从边界框底部向上堆叠的梯级。
local position = Vector3.new(0, -size.Y / 2 + rungThickness / 2, 0)
for i = 1, count do
-- 在梯级之间让出,以便有很多梯级的梯子不会阻塞线程。
parameters:Pause()
createPart(position, Vector3.new(size.X - 2 * postSize, rungThickness, size.Z))
position += Vector3.new(0, parameters.Attributes.RungSpacing, 0)
end
-- 左右侧柱延伸到整个高度。
createPart(Vector3.new(-0.5 * size.X + postSize / 2, 0, 0), Vector3.new(postSize, size.Y, size.Z))
createPart(Vector3.new(0.5 * size.X - postSize / 2, 0, 0), Vector3.new(postSize, size.Y, size.Z))
end
-- 返回模块定义使得该 ModuleScript 可以作为 `Generator` 使用。
return ClassicRobloxLadderGenerator方法