6 min read

Source: Roblox Creator Hub · CC BY 4.0 · View source · Code samples: MIT Imported 2026-10-03. Formatting adapted for this site.

Model generation

Through text prompts and preset schemas, you (and players in-game) can generate both static 3D assets and fully functional models such as vehicles that drive, planes that fly, and weapons that shoot. This guide demonstrates how to use GenerateModelAsync() as part of a dynamic, player‑driven creative experience.

Overview

GenerateModelAsync() enables generation of multi‑mesh geometries with the following advantages:

Schema-based generation

To create articulated, functional objects, the generated geometry must be separated into multiple MeshParts. For example, to create a drivable car with wheels that spin and steer, at least five MeshParts are needed: one for the car body and four for each of the car's wheels. GenerateModelAsync() achieves this through a schema that lists the parts to generate, as shown in the following code snippet:

local GenerationService = game:GetService("GenerationService")
local Workspace = game:GetService("Workspace")

-- Set up inputs for the generated geometry
local inputs = {
	TextPrompt = "green dragon car with 4 wheels"
}
-- Set schema to the predefined five-model car chassis
local schema = {
	PredefinedSchema = "Car5"
}

-- Make the call to generate the model
local success, result, metadata = pcall(function()
	return GenerationService:GenerateModelAsync(inputs, schema)
end)
if success then
	-- Scale model to target size and position near world center
	local targetSize = 16
	local modelSize = result:GetExtentsSize()
	local scaleFactor = targetSize / math.max(modelSize.X, modelSize.Y, modelSize.Z)
	result:ScaleTo(scaleFactor)
	result:PivotTo(CFrame.new(0, result:GetExtentsSize().Y / 2, -40))

	-- Anchor all parts so that the meshes don't fall apart
	for _, descendant in result:GetDescendants() do
		if descendant:IsA("BasePart") then
			descendant.Anchored = true
		end
	end

	-- Name the model and parent it to workspace
	result.Name = "BasicDragonCarGeneration"
	result.Parent = Workspace
else
	warn(result)
end

Note

GenerateModelAsync() currently supports two fixed schemas: Car5 which produces a car with a body and four wheels, and Body1 which yields a single MeshPart object.

The following image shows the expected output and its construction as it appears in the Explorer hierarchy:

Retargetable scripts

In Roblox, behaviors typically encompass the scripts, attachments, constraints, and other instance types attached to static textured geometries to make them functional. Since GenerateModelAsync() generates a wide range of geometries on‑the‑fly, retargetable scripts must be attached to automatically adapt behaviors to expected functionality.

For example, consider a game where players get to make their own drivable cars. GenerateModelAsync() takes the player prompt and generates five distinct meshes (body and four wheels) via the Car5 schema. Then, a preset retargetable script adapts its driving behavior to the size and shape of the model to ensure the car is drivable and its wheels spin realistically.

block-beta
columns 1

  block:Main
    columns 5
    Prompt(["&nbsp; &nbsp;prompt&nbsp; &nbsp;<br />&nbsp; &nbsp;(creator)&nbsp; &nbsp;"])
    Generate{"&nbsp;Geometry&nbsp;<br />&nbsp;Generator&nbsp;<br />(Roblox)"}  

    Geometry(("<b>GEOMETRY</b><br />&nbsp; &nbsp;<span style="font-size:80%; color:white;">single / multi-mesh</span>&nbsp; &nbsp;"))
    space:2
    Schema(["&nbsp; &nbsp;schema&nbsp; &nbsp;"])
    space
    Retarget{"&nbsp; &nbsp;&nbsp;Retarget&nbsp; &nbsp;&nbsp;<br />behavior<br />(creator)"}
    space
    FunctionalModel((("&nbsp; &nbsp; <b>FUNCTIONAL</b> &nbsp; &nbsp;<br /><b>MODEL</b>")))

  Prompt --> Generate
  Generate --> Geometry
  Geometry --> Retarget
  Retarget --> FunctionalModel
  Schema --> Generate
end

style Main fill-opacity: 0, stroke-opacity: 0;
style Prompt color:white, fill:RoyalBlue;
style Schema color:white, fill:RoyalBlue;
style Generate color:white, fill:#9933FF, fill-opacity:0.7;
style Retarget color:white, fill:RoyalBlue;
style Geometry color:white, fill:SeaGreen
style FunctionalModel color:white, fill:SeaGreen

To test retargetable scripts:

  1. Download the Behaviors.rbxm file.

  2. In Studio's Explorer hierarchy, right‑click ReplicatedStorage, select Insert ⟩ Import Roblox Model, and choose the downloaded file. The model unpacks into several folders.

  3. Copy and paste one of the following code snippets into a server Script within ServerScriptService, depending on the object type you'd like to generate.

Car

This example generates a functional car with a brake, nitro boost, audio and visual effects, and an on‑screen UI speedometer.

	```lua title="Script in ServerScriptService"
	local GenerationService = game:GetService("GenerationService")
	local ReplicatedStorage = game:GetService("ReplicatedStorage")
	local Workspace = game:GetService("Workspace")

	-- Set up inputs for the generated geometry
	local inputs = {
		TextPrompt = "green dragon car with 4 wheels"
	}
	-- Set schema to the predefined five-model car chassis
	local schema = {
		PredefinedSchema = "Car5"
	}

	-- Make the call to generate the model
	local success, result, metadata = pcall(function()
		return GenerationService:GenerateModelAsync(inputs, schema)
	end)
	if success then
		-- Scale model to target size
		local targetSize = 16
		local modelSize = result:GetExtentsSize()
		local scaleFactor = targetSize / math.max(modelSize.X, modelSize.Y, modelSize.Z)
		result:ScaleTo(scaleFactor)

		-- Load "makeFunctional" module for "CarBehavior"
		local makeFunctional = require(ReplicatedStorage.Behaviors.CarBehavior.makeFunctional)

		-- Reference car parts by names guaranteed through the "Car5" schema
		local body = result:FindFirstChild("body")
		local frontLeftWheel = result:FindFirstChild("front left wheel")
		local frontRightWheel = result:FindFirstChild("front right wheel")
		local rearLeftWheel = result:FindFirstChild("rear left wheel")
		local rearRightWheel = result:FindFirstChild("rear right wheel")

		-- Set behavioral configuration parameters
		local config = {
			seatPosition = "inside",
			invisibleWhenSeated = false
		}

		-- Attach behavior via the "makeFunctional" script
		local functionalModel = makeFunctional(result, frontLeftWheel, frontRightWheel, rearLeftWheel, rearRightWheel, body, config)

		-- Position the model near world center
		functionalModel:PivotTo(CFrame.new(0, functionalModel:GetExtentsSize().Y / 2, -40))
		functionalModel.Name = "BasicDragonCarGeneration"
		functionalModel.Parent = Workspace
	else
		warn(result)
	end
	```

Note

To test other generated models with retargetable scripts in the Car5 schema, change the TextPrompt string value on line 7 and playtest again. Ideas include:

  - `"yellow sports car with a spoiler"`
  - `"purple bat car with 4 wheels"`
  - `"giant monster truck with spiked roof"`

Airplane

This example generates a basic plane using the Body1 schema that flies through player input.

	```lua title="Script in ServerScriptService"
	local GenerationService = game:GetService("GenerationService")
	local ReplicatedStorage = game:GetService("ReplicatedStorage")
	local Workspace = game:GetService("Workspace")

	-- Set up inputs for the generated geometry
	local inputs = {
		TextPrompt = "basic paper airplane with two wings"
	}
	-- Set schema to the predefined static body
	local schema = {
		PredefinedSchema = "Body1"
	}

	-- Make the call to generate the model
	local success, result, metadata = pcall(function()
		return GenerationService:GenerateModelAsync(inputs, schema)
	end)
	if success then
		-- Scale model to target size
		local targetSize = 30
		local modelSize = result:GetExtentsSize()
		local scaleFactor = targetSize / math.max(modelSize.X, modelSize.Y, modelSize.Z)
		result:ScaleTo(scaleFactor)
		
		-- Load "makeFunctional" module for "AirplaneBehavior"
		local makeFunctional = require(ReplicatedStorage.Behaviors.AirplaneBehavior.makeFunctional)
		
		-- Set behavioral configuration parameters
		local config = {
			seatPosition = "ontop",
			forwardSpeed = 80,
			turnSpeed = 8
		}
		
		-- Attach behavior via the "makeFunctional" script
		local functionalModel = makeFunctional(result, config)
		
		-- Place model slightly above ground to let it fall into place
		local boundingBox = functionalModel:GetBoundingBox()
		local location = Vector3.new(0, boundingBox.Y / 2 + 3, -40)
		functionalModel:PivotTo(CFrame.new(location))
		functionalModel.Name = "BasicPlaneGeneration"
		functionalModel.Parent = Workspace
	else
		warn(result)
	end
	```