Designing no-code games with Reality Composer Pro 3
Build a video game in Reality Composer Pro without code using Script Graphs.
Overview
This sample code project uses Reality Composer Pro and RealityKit to build a video game whose gameplay you author visually instead of by writing code. The game follows a sleepy squirrel who is taking a nap on top of a leafy pad. The goal of the game is to wake up the squirrel, guide them up a tree through the branches and leaves, so they make it home in time for dinner.
[Image]
Rather than writing code, the sample relies on Script Graphs to drive almost every behavior of the squirrel and the world. A small SwiftUI layer hosts the scene, shows the speech bubbles and buttons, and trades messages with those graphs. This sample demonstrates how to initialize the RealityKitScripting runtime, pass messages between the Script Graph layer and the SwiftUI layer, and design platformer game mechanics inside Reality Composer Pro.
Start the Script Graph runtime
Script Graphs are the visual gameplay logic you author in Reality Composer Pro. Inside Reality Composer Pro, you attach a Scripting component to entities, edit the Script Graph associated with those entities, then publish the entities and logic together as a Reality file. Then in your Xcode project, you initialize the runtime before loading your content in a RealityView marked with the .realityScripting() view modifier.
The runtime and view modifier ships in RealityKitScripting, an open source Swift package maintained by Apple that you add to your Xcode project. Use the Swift Package Manager to add a dependency pointing at RealityKitScripting, link the RealityKitScripting library to your app target, then import the module wherever your code starts or talks to the runtime. For more detailed instructions on how to add a package to your Xcode project, see Adding package dependencies to your app.
The app initializes the runtime by calling RKS.initialize(inputOptions:), setting the initialization option to .all.subtracting(.ar) because .ar input modes aren’t available in a volumetric window.
import RealityKit
import RealityKitScripting
import SwiftUI
@main
struct SquirrelApp: App {
init() {
do {
try RKS.initialize(inputOptions: .all.subtracting(.ar))
} catch {
assertionFailure("Failed to initialize the Script Graph runtime: \(error)")
}
}
// ...
}Then the sample loads the world entity from the built Reality file inside a RealityView, and uses the .realityScripting() view modifier to run your scene’s logic:
RealityView { content, attachments in
let entity = try await Entity(named: "world")
content.add(entity)
// ...
}
.realityScripting()Pass messages between SwiftUI and the graph
The interface and the gameplay logic need to stay in agreement. When the squirrel speaks, a bubble appears, and when you press a button, the game responds. Script Graphs and SwiftUI keep that agreement through named scene events. You declare each event once in Reality Composer Pro, after which both sides refer to the events by name.
Send events to the Scene using the extension method .send(name:with:) provided by the RealityKitScripting package. Events that require extra data can receive that information in a dictionary using the with: parameter.
scene.send(name: "setCurrentLevelScreen", with: ["levelScreenName": sceneName])Receive events from the Scene by using the .subscribe(forEventName:on:) extension method provided by the RealityKitScripting package.
scene.subscribe(forEventName: "squirrelTalk", on: { event in
if let sayThis: String = try? event.value("sayThis") {
DispatchQueue.main.async {
if sayThis == "zzz" {
self.showSquirrelTalk = true
}
self.squirrelTalkText = sayThis
self.squirrelTalkTrigger += 1
}
}
}).store(in: &cancellables)Drive game mechanics with Script Graphs
Script Graphs drive almost every behavior in this game instead of Swift code. The moving platforms, the collectibles, and the squirrel’s animations all run as visual node graphs in the scene.
To learn more about building logic in the Script Graph editor, see Getting started with Script Graphs.
Consider the example of bouncy animations on some of the platforms the squirrel jumps across. When the squirrel lands on a surface, the surface squashes under the impact then bounces back to rest. Two Script Graphs produce this behavior, coordinating through a single named event. Unlike the squirrel talk example above, where the graph exchanges messages with SwiftUI, both sides of this event are graphs — one graph detects the landing and announces it, and the other graph plays the reaction.
One graph detects the landing and announces it. In OnFloorCollision, an On Collision Began node starts when the squirrel touches the surface, and a Send Entity Event node sends an event named bounce to the entity that plays the animation.
[Image]
In BounceAnim, an On Entity Event node listens for bounce and records the moment it arrives. The rest of the graph uses that timestamp to animate the surface so it squashes and springs back.
[Image]
See Also
RealityKit and Reality Composer Pro
Reality Composer ProChaparral Village: Building an immersive visionOS adventure gamePetite Asteroids: Building a volumetric visionOS gameBOT-anistSwift SplashDioramaBuilding an immersive media viewing experienceEnabling video reflections in an immersive environmentCombining 2D and 3D views in an immersive appUnderstanding the modular architecture of RealityKitUsing transforms to move, scale, and rotate entitiesCapturing screenshots and video from Apple Vision Pro for 2D viewingImplementing object tracking in your appPlacing entities using head and device transformManipulating entities with solid collisions