Reality Composer Pro 3 allows developers to build Xcode plug-ins that expose custom RealityKit components, systems, animation actions, and Script Graph nodes directly inside the editor, enabling artists to iterate on 3D content without rebuilding the app.
• Artists and designers can tweak custom component properties (e.g. water level, vortex speed) in real time inside Reality Composer Pro 3 without any app rebuilds or deploys
• Custom EntityAction types can be added to the sequencer timeline, enabling code-driven animations that are fully editable by non-engineers
• The plugin framework shares Swift code between the editor plugin and the final app, eliminating duplication and keeping editor behavior in sync with runtime behavior
Demonstrates how to create a custom RealityKit component and system, register them via a Reality Composer Pro plugin, and expose an editable water-level property to the editor so artists can adjust it in real time.
import RealityKit
import RealityComposerPro
// MARK: - Custom Component
struct CauldronComponent: Component, Codable {
var waterLevel: Float = 0.5 // 0.0 = empty, 1.0 = full
var rotationSpeed: Float = 0.0 // radians per second
var vortexCoefficient: Float = 0.0
}
// MARK: - Custom System
final class CauldronSystem: System {
static let query = EntityQuery(where: .has(CauldronComponent.self))
required init(scene: Scene) {}
func update(context: SceneUpdateContext) {
for entity in context.entities(matching: Self.query, updatingSystemWhen: .rendering) {
guard let cauldron = entity.components[CauldronComponent.self],
let waterMesh = entity.findEntity(named: "WaterSurface") else { continue }
// Lift the water plane based on the waterLevel property
let baseY: Float = -0.1
let rangeY: Float = 0.2
waterMesh.position.y = baseY + cauldron.waterLevel * rangeY
}
}
}
// MARK: - Plugin Entry Point
final class CauldronPlugin: RealityComposerProPlugin {
required init() {}
func setup(context: RealityComposerProPluginContext) {
// Register the component so it appears in the editor's component browser
context.registerComponent(CauldronComponent.self)
// Register the system so it runs live inside the editor viewport
context.registerSystem(CauldronSystem.self)
}
}
// Exported C entry point so the plugin loader can instantiate the plugin
@_cdecl("createRealityComposerProPlugin")
public func createRealityComposerProPlugin() -> UnsafeMutableRawPointer {
Unmanaged.passRetained(CauldronPlugin()).toOpaque()
}
// MARK: - Custom Animation Action
struct WaterLevelAction: EntityAction, Codable {
var startLevel: Float
var endLevel: Float
// EntityAction requirement: declare the value type used for interpolation
static var animatedValueType: (any AnimatableData.Type)? { return nil }
static func subscribe(to scene: Scene) {
EntityAction.subscribe(to: WaterLevelAction.self, on: scene) { event in
guard var cauldron = event.entity.components[CauldronComponent.self] else { return }
cauldron.waterLevel = event.action.startLevel +
Float(event.animationState.normalizedTime) *
(event.action.endLevel - event.action.startLevel)
event.entity.components.set(cauldron)
}
}
}• The plugin framework must be built as a separate Xcode scheme; every code change requires restarting Reality Composer Pro to reload the dynamic library • The createRealityComposerProPlugin() entry point must be exported as a C symbol with @_cdecl — forgetting this prevents the plugin loader from finding it • Custom component properties must conform to Codable; runtime-only state should be excluded via CodingKeys or it will appear in the editor UI • This feature was announced as 'available later this year' at WWDC 2026 — expect beta instability and possible API changes before final release
Reality Composer Pro 3 runs on macOS; plugin preview runs in-editor or on Apple Vision Pro. Apple Intelligence not required, but visionOS/iOS 27 SDK and Xcode 26+ are needed.
More iOS 27 APIs land every week.
Get notified when new capabilities are published — no noise, just signal.