{"$schema": "https://raw.githubusercontent.com/guitaripod/wwdc-sessions/master/schema/transcript.schema.json", "id": "wwdc2026-393", "language": "eng", "source": "https://developer.apple.com/videos/play/wwdc2026/393", "wordCount": 3391, "segments": [{"start": 7.0, "text": "Hello, my name is Vincent."}, {"start": 9.0, "text": "I'm a Reality Composer Pro engineer."}, {"start": 12.0, "text": "Today I'll show you how visual, node-based tools in Reality Composer Pro"}, {"start": 16.0, "text": "can supercharge your spatial workflow."}, {"start": 19.0, "text": "These tools let you author functionality, animation, particle effects,"}, {"start": 23.0, "text": "and customize the look of your scene all within the editor,"}, {"start": 26.0, "text": "making it fast to prototype and iterate on your ideas."}, {"start": 30.0, "text": "Reality Composer Pro is a visual editor for composing 3D scenes,"}, {"start": 34.0, "text": "creating materials, adding visual effects, setting up lighting,"}, {"start": 38.0, "text": "building interactivity, and so much more."}, {"start": 42.0, "text": "There's a lot you can do with Reality Composer Pro,"}, {"start": 45.0, "text": "and this year it gets even more capable."}, {"start": 48.0, "text": "For a deeper dive into some of these capabilities,"}, {"start": 51.0, "text": "check out the session"}, {"start": 52.0, "text": "\"Iterate Your Spatial Scenes Faster with Reality Composer Pro 3\"."}, {"start": 56.0, "text": "This is the Chaparral Village game that was built entirely"}, {"start": 59.0, "text": "using Reality Composer Pro 3 and Swift,"}, {"start": 63.0, "text": "and utilizes many of the latest capabilities."}, {"start": 67.0, "text": "Today, I'll take you through the alchemy area scene from this game"}, {"start": 70.0, "text": "and bring it to life with an interactive character"}, {"start": 73.0, "text": "and a particle effect for the cauldron."}, {"start": 76.0, "text": "I would like the alchemist character to perform a routine"}, {"start": 78.0, "text": "where it walks to the table, prepares the ingredients, and waits."}, {"start": 83.0, "text": "And when someone taps the alchemist, it would turn and walk to the cauldron"}, {"start": 87.0, "text": "to start brewing the potion."}, {"start": 90.0, "text": "To build this, I'll begin with an Animation Graph"}, {"start": 92.0, "text": "to blend between idle and walk animations as the character moves."}, {"start": 97.0, "text": "I'll setup a Behavior Tree to define how the character moves"}, {"start": 99.0, "text": "around the alchemy area autonomously."}, {"start": 102.0, "text": "I'll wire up a Script Graph to add interactivity,"}, {"start": 105.0, "text": "so the scene responds when someone taps."}, {"start": 108.0, "text": "After that, I'll show you how the Navigation Mesh component"}, {"start": 111.0, "text": "lets characters pathfind around obstacles and navigate through complex environments."}, {"start": 117.0, "text": "I'll show you how I built the particle effect"}, {"start": 119.0, "text": "for the cauldron with Compute Graph."}, {"start": 122.0, "text": "And finally, I will share some enhancements to Shader Graph in Reality Composer Pro 3."}, {"start": 128.0, "text": "Let's start with the Animation Graph."}, {"start": 130.0, "text": "Animation Graph in Reality Composer Pro 3 is a visual, node-based editor"}, {"start": 135.0, "text": "for controlling how a character animates at runtime."}, {"start": 138.0, "text": "It supports a wide array of capabilities, from motion warping, to blend spaces,"}, {"start": 143.0, "text": "to inverse kinematics, and a lot more."}, {"start": 147.0, "text": "To make the alchemist move naturally, I'll use a State Machine,"}, {"start": 151.0, "text": "some Animation clips, Transition conditions,"}, {"start": 153.0, "text": "and Runtime parameters to blend the alchemist's idle and walk animations."}, {"start": 157.0, "text": "Let's take a look."}, {"start": 160.0, "text": "This is the Animation Graph workspace where I can define my animations."}, {"start": 164.0, "text": "The Animation Graph starts with a Final Pose node by default."}, {"start": 168.0, "text": "Whatever pose flows into this node is what the character displays."}, {"start": 172.0, "text": "I'll drag from the Final Pose node's input and connect a State Machine node."}, {"start": 178.0, "text": "The State Machine decides which animation is active at any given moment."}, {"start": 182.0, "text": "Next, I'll double click the State Machine node to step inside."}, {"start": 186.0, "text": "This opens the State Machine editor, where states and transitions are defined."}, {"start": 191.0, "text": "The canvas starts empty, and the character needs two states."}, {"start": 195.0, "text": "I'll add two Animation State nodes and name them Idle and Walk."}, {"start": 201.0, "text": "With the states in place, I'll add the transitions."}, {"start": 204.0, "text": "The two states are independent right now, with no way to switch between them."}, {"start": 209.0, "text": "I'll drag from Idle to Walk to create a transition."}, {"start": 214.0, "text": "Then I'll do the same from Walk back to Idle,"}, {"start": 217.0, "text": "so the character can return to Idle when it's done walking."}, {"start": 221.0, "text": "The transitions are in place, but they don't have any conditions yet."}, {"start": 225.0, "text": "Without conditions,"}, {"start": 226.0, "text": "the State Machine has no way of knowing when to switch between states."}, {"start": 230.0, "text": "Before I can add conditions, I need to define the inputs they'll reference."}, {"start": 235.0, "text": "I'll go to the Inputs Inspector and add a boolean called isWalking."}, {"start": 240.0, "text": "This is the parameter that I will set at runtime"}, {"start": 243.0, "text": "to tell the character when to walk."}, {"start": 245.0, "text": "Now I can add the conditions."}, {"start": 248.0, "text": "I'll select the transition from Idle to Walk."}, {"start": 252.0, "text": "In the Inspector, I'll click Add in the condition section,"}, {"start": 255.0, "text": "choose Bool Condition,"}, {"start": 256.0, "text": "and set it to check whether isWalking is true."}, {"start": 261.0, "text": "For the Walk to Idle transition, the condition is the same but inverted."}, {"start": 266.0, "text": "I'll select that transition, add a Bool Condition,"}, {"start": 268.0, "text": "and set it to check whether isWalking is false."}, {"start": 273.0, "text": "I'll step back out to the Main Graph by clicking the back arrow."}, {"start": 278.0, "text": "The State Machine node now shows two state inputs:"}, {"start": 281.0, "text": "one for Idle and one for Walk."}, {"start": 284.0, "text": "Each input needs an animation source."}, {"start": 287.0, "text": "I'll drag from the Idle input and add an Animation Clip node."}, {"start": 296.0, "text": "In the Inspector, I'll set the timeline to the idle animation,"}, {"start": 300.0, "text": "and set the node name to \"Idle\"."}, {"start": 305.0, "text": "Then I'll do the same for the Walk input,"}, {"start": 307.0, "text": "dragging out to create another Animation Clip node"}, {"start": 310.0, "text": "and setting it to the walk animation and rename it to \"Walk\"."}, {"start": 322.0, "text": "Let me test this."}, {"start": 324.0, "text": "I'll press the Play button at the top of the workspace."}, {"start": 328.0, "text": "The character in the viewport begins playing the idle animation."}, {"start": 332.0, "text": "In the Inspector, I can manually toggle the isWalking boolean."}, {"start": 336.0, "text": "Setting it to true blends the character into the walk animation."}, {"start": 345.0, "text": "Setting it back to false,"}, {"start": 347.0, "text": "the character finishes its current Walk cycle"}, {"start": 349.0, "text": "and then blends back to Idle."}, {"start": 352.0, "text": "Notice the Graph Editor as I toggle the isWalking boolean."}, {"start": 355.0, "text": "The active state node gets highlighted as the character transitions between states."}, {"start": 363.0, "text": "This makes it easy to follow what the State Machine is doing in real time,"}, {"start": 367.0, "text": "which becomes especially useful when debugging more complex"}, {"start": 371.0, "text": "with many states."}, {"start": 373.0, "text": "The character can now blend smoothly between idle and walk animations."}, {"start": 377.0, "text": "But it doesn't know where to go or when to start moving."}, {"start": 381.0, "text": "To give the alchemist a full routine around the alchemy area,"}, {"start": 384.0, "text": "I'll use a Behavior Tree to define each step of its movement."}, {"start": 388.0, "text": "Behavior Trees in Reality Composer Pro let you author autonomous,"}, {"start": 392.0, "text": "multi-step behavior directly in the editor."}, {"start": 395.0, "text": "For example, a character that patrols an area, reacts to events,"}, {"start": 399.0, "text": "or follows a routine."}, {"start": 402.0, "text": "As shown here,"}, {"start": 403.0, "text": "Behavior Trees typically consist of a structured hierarchy of nodes."}, {"start": 407.0, "text": "These are steps that can be rearranged in any order,"}, {"start": 410.0, "text": "and everything can be tested without writing code."}, {"start": 413.0, "text": "A Behavior Tree describes an entity's behavior as a hierarchy of nodes."}, {"start": 417.0, "text": "The tree is evaluated from top to bottom,"}, {"start": 420.0, "text": "and when nodes share the same level, they are evaluated from left to right."}, {"start": 424.0, "text": "Higher nodes and leftmost nodes are always evaluated first."}, {"start": 429.0, "text": "There are two kinds of nodes: Composite nodes and Action nodes."}, {"start": 432.0, "text": "Composite nodes control the flow."}, {"start": 434.0, "text": "Action nodes do the actual work."}, {"start": 437.0, "text": "Action nodes are bound to Composite nodes as children,"}, {"start": 439.0, "text": "and the Composite node determines the order and conditions under which they run."}, {"start": 444.0, "text": "Behavior Tree in Reality Composer Pro provides three Composite nodes"}, {"start": 448.0, "text": "for controlling the flow."}, {"start": 450.0, "text": "A Sequence runs its children one by one in order."}, {"start": 453.0, "text": "If any action fails, the entire sequence stops immediately."}, {"start": 458.0, "text": "A Selector evaluates its children until one succeeds, then stops."}, {"start": 464.0, "text": "A Parallel runs all of its children at the same time."}, {"start": 469.0, "text": "Behavior Trees provide a range of built-in action nodes."}, {"start": 473.0, "text": "For composing the alchemist's routine, I'll use the Move To action node"}, {"start": 476.0, "text": "to walk the character to a destination,"}, {"start": 479.0, "text": "Rotate To Face node to turn towards a target,"}, {"start": 482.0, "text": "the Wait node to pause between steps,"}, {"start": 485.0, "text": "and the Parameter Setter node to update entity parameters along the way."}, {"start": 490.0, "text": "In my app I am just going to use a few built-in nodes,"}, {"start": 493.0, "text": "but there are a number of other action nodes that you will find in the editor."}, {"start": 498.0, "text": "Let's head back to the editor and build the Behavior Tree"}, {"start": 501.0, "text": "that will help the alchemist character through its routine around the alchemy area."}, {"start": 505.0, "text": "This is the Behavior Tree workspace where I will define the alchemist's routine."}, {"start": 510.0, "text": "I want the alchemist character to turn toward the table,"}, {"start": 513.0, "text": "walk to it, and wait for a second to prepare the ingredients."}, {"start": 517.0, "text": "These actions need to happen in order, so I'll use the Sequence Composite node."}, {"start": 522.0, "text": "Inside the Sequence, I'll add a Rotate To Face node,"}, {"start": 525.0, "text": "a Move To node, and a Wait node."}, {"start": 529.0, "text": "I'll set the wait time to 1 second."}, {"start": 541.0, "text": "The Rotate and Move nodes both need a target position and a speed."}, {"start": 545.0, "text": "I'll add inputs for tablePosition, rotationRate, and movementRate,"}, {"start": 549.0, "text": "then plug them into the nodes."}, {"start": 558.0, "text": "Before the character starts moving, the Animation Graph needs to know about it."}, {"start": 563.0, "text": "I'll add an isWalking input for the Animation Graph."}, {"start": 566.0, "text": "Then I'll add a Parameter Setter before the Rotate To Face,"}, {"start": 570.0, "text": "setting isWalking to true."}, {"start": 573.0, "text": "And another Parameter Setter after Move To,"}, {"start": 576.0, "text": "setting isWalking back to false."}, {"start": 586.0, "text": "Now the walk animation plays only while the character is in motion."}, {"start": 590.0, "text": "The alchemist also needs to walk to the cauldron using the same pattern."}, {"start": 594.0, "text": "The steps are identical, just with a different destination."}, {"start": 598.0, "text": "I've gone ahead and built out the full graph"}, {"start": 600.0, "text": "with both sub-sequences already wired up."}, {"start": 603.0, "text": "Here's what I built."}, {"start": 604.0, "text": "The cauldron sub-sequence follows the same structure,"}, {"start": 607.0, "text": "with its own Rotate To Face, Move To,"}, {"start": 610.0, "text": "and Parameter Setter nodes, pointing to a cauldronPosition input."}, {"start": 613.0, "text": "Let me create a Parent Sequence node"}, {"start": 615.0, "text": "and connect both of the subsequences to the parent sequence,"}, {"start": 618.0, "text": "so the alchemist visits the table first, then moves on to the cauldron."}, {"start": 623.0, "text": "The Behavior Tree defines the character's routine,"}, {"start": 626.0, "text": "but it isn't functional yet."}, {"start": 628.0, "text": "In order to make my character perform its routine,"}, {"start": 630.0, "text": "where it turns and walks to the cauldron and starts brewing"}, {"start": 634.0, "text": "I will need to use Script Graph."}, {"start": 636.0, "text": "Script Graph allows you to define interactivity and functionality"}, {"start": 640.0, "text": "for the entities in your scene."}, {"start": 642.0, "text": "It is a visual scripting system that lets you define how entities in the scene behave"}, {"start": 646.0, "text": "and interact with each other."}, {"start": 648.0, "text": "It is event-driven, a Script Graph runs in response to events,"}, {"start": 652.0, "text": "either at the scene level or on specific entities."}, {"start": 656.0, "text": "Because all of this is visual, prototyping and iteration are fast."}, {"start": 661.0, "text": "Anyone on the team can build and test behaviors directly in the editor,"}, {"start": 665.0, "text": "without a build cycle."}, {"start": 666.0, "text": "To see how the Script Graph can power your workflow, checkout the session"}, {"start": 670.0, "text": "\"Design no-code games with Reality Composer Pro 3\"."}, {"start": 674.0, "text": "Let's jump back to the editor to setup the table and cauldron position,"}, {"start": 678.0, "text": "and add an interaction with the tap gesture using Script Graph."}, {"start": 682.0, "text": "This is Script Graph."}, {"start": 684.0, "text": "Here I will define some logic to interact with the alchemist character."}, {"start": 688.0, "text": "I'll start with an On Initialize node."}, {"start": 692.0, "text": "This sends an event the first time the Scripting component is initialized,"}, {"start": 696.0, "text": "making it a good place for setup logic."}, {"start": 699.0, "text": "The Behavior Tree needs the table and cauldron positions,"}, {"start": 702.0, "text": "and I'll use a subgraph to provide them."}, {"start": 705.0, "text": "A subgraph is a reusable piece of logic that works like a function."}, {"start": 710.0, "text": "My team member has already built a Setup Behavior Tree Position subgraph"}, {"start": 714.0, "text": "in the Project Browser."}, {"start": 716.0, "text": "It finds the table and cauldron entities in the scene"}, {"start": 718.0, "text": "and sets their world positions on the entity parameter."}, {"start": 722.0, "text": "I'll drag the subgraph from the Project Browser onto the canvas,"}, {"start": 726.0, "text": "then connect its event input to the On Initialize node's event output."}, {"start": 735.0, "text": "Alright… let's give it a go!"}, {"start": 738.0, "text": "I'll click the play button on top."}, {"start": 740.0, "text": "The alchemist turns to the table, prepares the ingredients for a while"}, {"start": 744.0, "text": "then heads straight to the cauldron."}, {"start": 746.0, "text": "The entire routine plays out from start to finish"}, {"start": 748.0, "text": "just as we defined in the Behavior Tree."}, {"start": 751.0, "text": "But, I am thinking it would be a lot more engaging"}, {"start": 754.0, "text": "if the alchemist responded to a tap interaction."}, {"start": 758.0, "text": "Let's make it so that the alchemist stays at the table preparing the ingredients..."}, {"start": 762.0, "text": "until someone taps it to indicate that it's time to brew the potion."}, {"start": 766.0, "text": "To set this up, let's jump back to the Behavior Tree."}, {"start": 770.0, "text": "First, I'll delete the Wait node in the table sub-sequence."}, {"start": 773.0, "text": "The alchemist should wait indefinitely now until told to move on."}, {"start": 777.0, "text": "In the Inputs Inspector, I'll add a Boolean input called readyToBrew"}, {"start": 782.0, "text": "with a default value of false."}, {"start": 784.0, "text": "Next, I'll select the cauldron sub-sequence."}, {"start": 788.0, "text": "In the Inspector, I'll add a Precondition, and choose Bool Condition."}, {"start": 794.0, "text": "With that set up the alchemist is configured to stay at the table"}, {"start": 797.0, "text": "until readyToBrew becomes true."}, {"start": 799.0, "text": "After which it moves on to the cauldron."}, {"start": 802.0, "text": "Now I'll go back to the Script Graph to wire up the tap interaction"}, {"start": 805.0, "text": "to make our new behavior fully functional."}, {"start": 808.0, "text": "I'll use the Mac Virtual Display along with the Live Preview feature"}, {"start": 811.0, "text": "in Reality Composer Pro 3"}, {"start": 814.0, "text": "that will allow me to work on my scene immersively on Apple Vision Pro."}, {"start": 818.0, "text": "Let me show you what that looks like."}, {"start": 820.0, "text": "I'll add an On Tap node."}, {"start": 822.0, "text": "This node listens for tap gesture events on the entity."}, {"start": 826.0, "text": "I'll also need a Set Entity Parameter node."}, {"start": 829.0, "text": "This node will help me set the pre-condition parameter"}, {"start": 831.0, "text": "that I previously defined in my Behavior Tree."}, {"start": 834.0, "text": "In the name field, I'll define the parameter name as \"readyToBrew\""}, {"start": 838.0, "text": "which will match with the name I defined in my Behavior Tree."}, {"start": 841.0, "text": "This parameter will indicate to my character when it should move to the cauldron."}, {"start": 846.0, "text": "I will enable the toggle to set it to true."}, {"start": 848.0, "text": "Finally, I'll connect the the On Tap node's event output"}, {"start": 851.0, "text": "to the Set Entity Parameter node."}, {"start": 854.0, "text": "I've started a live preview session on Apple Vision Pro"}, {"start": 857.0, "text": "using the Reality Composer Pro Companion App."}, {"start": 861.0, "text": "The alchemist turns to the table, and stays there preparing the ingredients."}, {"start": 866.0, "text": "When I tap the character, it turns and walks to the cauldron to begin brewing."}, {"start": 871.0, "text": "The scene is now interactive!"}, {"start": 874.0, "text": "The alchemist now animates,"}, {"start": 876.0, "text": "follows a routine, and responds to interaction,"}, {"start": 879.0, "text": "all authored visually in the editor with a combination of Animation Graph,"}, {"start": 883.0, "text": "Behavior Tree, and Script Graph."}, {"start": 886.0, "text": "Next, I want to make my character move on an autonomous path"}, {"start": 889.0, "text": "and even avoid obstacles in the scene."}, {"start": 892.0, "text": "For that, I will use the new Navigation Mesh feature"}, {"start": 896.0, "text": "A Navigation Mesh defines the walkable surfaces in a scene."}, {"start": 899.0, "text": "The navigation controller uses the Navigation Mesh"}, {"start": 902.0, "text": "to route characters from one point to another,"}, {"start": 905.0, "text": "automatically avoiding obstacles like the trees and water shown here."}, {"start": 910.0, "text": "And when meshes aren't naturally connected,"}, {"start": 912.0, "text": "like this bridge on the right,"}, {"start": 914.0, "text": "an off-mesh connection can be authored to link them."}, {"start": 918.0, "text": "Let me show you how the village scene in the Chaparral Village project"}, {"start": 921.0, "text": "uses Navigation Mesh to guide the character around the village."}, {"start": 925.0, "text": "Here's the Navigation Mesh component that I set up for the village scene."}, {"start": 928.0, "text": "Starting with the Shapes section."}, {"start": 930.0, "text": "This is where the bounding box is defined for mesh generation."}, {"start": 933.0, "text": "The bounding box determines which parts of the mesh geometry in the scene"}, {"start": 937.0, "text": "should be included when computing the Navigation Mesh."}, {"start": 940.0, "text": "Any parts of the scene within the bounding box"}, {"start": 942.0, "text": "will be used for generating a Navigation Mesh resource."}, {"start": 946.0, "text": "Next is the Off-Mesh Connections section that can help define links between areas"}, {"start": 950.0, "text": "that the mesh wouldn't otherwise connect,"}, {"start": 953.0, "text": "like the ladder here that lets the character climb up to the building's roof."}, {"start": 957.0, "text": "Each connection has a start and end point."}, {"start": 959.0, "text": "You can adjust the positions directly using the gizmo in the viewport."}, {"start": 964.0, "text": "This makes it quick to set up and reposition connections"}, {"start": 967.0, "text": "as the scene evolves."}, {"start": 969.0, "text": "Next is the Generation Parameters section."}, {"start": 971.0, "text": "These control how the scene geometry is sampled."}, {"start": 974.0, "text": "For example, cell size sets the voxel size used during sampling."}, {"start": 978.0, "text": "Smaller values capture finer detail,"}, {"start": 981.0, "text": "while larger values produce a more approximate mesh."}, {"start": 985.0, "text": "There are many more parameters available for fine-tuning the Navigation Mesh."}, {"start": 989.0, "text": "For a complete reference,"}, {"start": 990.0, "text": "check out the documentation on developer.apple.com."}, {"start": 995.0, "text": "To learn how to use the Navigation Mesh in code,"}, {"start": 997.0, "text": "check out Dennis's session"}, {"start": 999.0, "text": "\"Explore Advances in RealityKit\"."}, {"start": 1002.0, "text": "Once the Navigation Mesh is set up, you can use it with a Behavior Tree,"}, {"start": 1006.0, "text": "Animation Graph, or your own custom Swift system"}, {"start": 1009.0, "text": "through the navigation component to guide your character through the scene."}, {"start": 1013.0, "text": "Just like the character in the village here,"}, {"start": 1016.0, "text": "navigating to the tap location autonomously while avoiding obstacles along the way."}, {"start": 1021.0, "text": "And with an off-mesh connection on the ladder,"}, {"start": 1024.0, "text": "the character even knows it can climb up to the rooftop."}, {"start": 1028.0, "text": "Next, let me show you how I built the smoke particle effects for the cauldron"}, {"start": 1032.0, "text": "using Compute Graph."}, {"start": 1033.0, "text": "The Compute Graph is a visual, node-based tool"}, {"start": 1035.0, "text": "for building GPU-driven particle simulations"}, {"start": 1038.0, "text": "backed by Metal directly in Reality Composer Pro."}, {"start": 1041.0, "text": "It gives you full control over spawning, simulation, and rendering,"}, {"start": 1045.0, "text": "with support for custom shaders."}, {"start": 1048.0, "text": "A Compute Graph is organized into four phases,"}, {"start": 1051.0, "text": "each handling a different stage of a particle's life."}, {"start": 1053.0, "text": "The first phase is the Emitter Phase,"}, {"start": 1056.0, "text": "which controls how and when particles are born,"}, {"start": 1059.0, "text": "whether continuously, in bursts, or as a single shot."}, {"start": 1063.0, "text": "The second phase is the Initialize Phase, and it runs once per particle at birth,"}, {"start": 1068.0, "text": "setting starting values like velocity, lifetime, and size."}, {"start": 1073.0, "text": "Next is the Simulate Phase."}, {"start": 1075.0, "text": "It runs every frame,"}, {"start": 1076.0, "text": "applying forces like gravity and turbulence to evolve particles over time."}, {"start": 1081.0, "text": "And the final phase is the Output Phase,"}, {"start": 1083.0, "text": "which controls how particles look on the screen,"}, {"start": 1086.0, "text": "defining their visual appearance as they age and move through space."}, {"start": 1091.0, "text": "Let me walk you through the Compute Graph I built for the cauldron's smoke effect."}, {"start": 1094.0, "text": "Every Compute Graph starts with these four phases as a template."}, {"start": 1098.0, "text": "For the Emitter Phase, I'm using a Continuous Emit node."}, {"start": 1102.0, "text": "This gives a dense, rolling flow of particles"}, {"start": 1105.0, "text": "while keeping each frame's spawn count in check."}, {"start": 1108.0, "text": "In the Initialize Phase,"}, {"start": 1109.0, "text": "I first set the size so each particle starts at the right scale,"}, {"start": 1112.0, "text": "with some random variation."}, {"start": 1115.0, "text": "Then I randomize the lifetime, so particles don't all disappear at the same instant,"}, {"start": 1120.0, "text": "giving the smoke a more natural feel."}, {"start": 1122.0, "text": "Next, a Spawn in Sphere node distributes particles within a spherical volume."}, {"start": 1127.0, "text": "This node comes from a custom Compute Graph bundle,"}, {"start": 1130.0, "text": "please check out the link"}, {"start": 1131.0, "text": "for how you can write your custom Compute Graph node using a bundle."}, {"start": 1135.0, "text": "And finally, a Set Position node clamps the Y position to zero,"}, {"start": 1139.0, "text": "flattening the spawn area to the surface of the sphere."}, {"start": 1142.0, "text": "This way, particles spawn in a circle,"}, {"start": 1144.0, "text": "like smoke rising from the surface of the liquid."}, {"start": 1148.0, "text": "In the Simulate Phase, I'm applying a negative gravity force."}, {"start": 1152.0, "text": "This makes the smoke particles drift upward,"}, {"start": 1155.0, "text": "just like rising steam from the cauldron."}, {"start": 1158.0, "text": "Lastly, In the Output Phase, particles fade in and out over lifetime,"}, {"start": 1163.0, "text": "scale down as they rise, and shift color based on height."}, {"start": 1166.0, "text": "For rendering, Compute Graph uses a Shader Graph material."}, {"start": 1170.0, "text": "Here, I'm using one that draws a circle on a billboard for a rounder look."}, {"start": 1175.0, "text": "And that's it!"}, {"start": 1177.0, "text": "The particle effect looks beautiful in my scene."}, {"start": 1179.0, "text": "Thanks to the Compute Graph feature in Reality Composer Pro!"}, {"start": 1183.0, "text": "Next, I would like to share some enhancements to Shader Graph."}, {"start": 1186.0, "text": "Shader Graph is getting some powerful updates this year,"}, {"start": 1189.0, "text": "like the Subsurface Scattering effect"}, {"start": 1191.0, "text": "that you may have seen in the Jupiter environment"}, {"start": 1193.0, "text": "that improves the realism of the ice on the Moon's surface."}, {"start": 1197.0, "text": "In addition to Subsurface Scattering effect,"}, {"start": 1199.0, "text": "there are many other enhancements to Shader Graph this year."}, {"start": 1203.0, "text": "RealityKit PBR Surface 2 is now available in Shader Graph."}, {"start": 1207.0, "text": "It expands the original RealityKit PBR surface node"}, {"start": 1210.0, "text": "with new surface properties like sheen,"}, {"start": 1213.0, "text": "Subsurface Scattering, plus more accurate Diffuse and Occlusion Shading."}, {"start": 1218.0, "text": "Hair surface is a dedicated surface shader for rendering hair and fur."}, {"start": 1222.0, "text": "It models how light reflects along and scatters through fine strands"}, {"start": 1225.0, "text": "for realistic results."}, {"start": 1228.0, "text": "Portal surface and Portal Geometry Modifier are also available in Shader Graph."}, {"start": 1232.0, "text": "You can now modify the per-pixel opacity of a Portal surface"}, {"start": 1235.0, "text": "and drive vertex-animated portal geometry,"}, {"start": 1238.0, "text": "giving you much more flexibility over how portals look and behave."}, {"start": 1242.0, "text": "If you are new to Shader Graph, I recommend you go over Niel's session,"}, {"start": 1246.0, "text": "\"Explore materials in Reality Composer Pro.\""}, {"start": 1249.0, "text": "Those were some exciting new features I covered in my session."}, {"start": 1253.0, "text": "I showed you how to bring a scene to life using visual, node-based tools"}, {"start": 1256.0, "text": "in Reality Composer Pro 3"}, {"start": 1258.0, "text": "to supercharge your workflow with building character animations,"}, {"start": 1261.0, "text": "defining complex behaviors,"}, {"start": 1263.0, "text": "to even adding interactivity and particle effects to your scene."}, {"start": 1267.0, "text": "And this is just scratching the surface of what you can do"}, {"start": 1270.0, "text": "with Reality Composer Pro 3."}, {"start": 1272.0, "text": "Before I wrap up, I highly encourage you to download Reality Composer Pro 3"}, {"start": 1277.0, "text": "from developer.apple.com and start building your own interactive experience."}, {"start": 1282.0, "text": "For a deeper dive, there are also some great related sessions to check out."}, {"start": 1286.0, "text": "\"Design No-Code Games with Reality Composer Pro 3\""}, {"start": 1289.0, "text": "goes deeper into building games with the Script Graph."}, {"start": 1292.0, "text": "And \"Explore Advances in RealityKit\" covers the RealityKit features"}, {"start": 1296.0, "text": "that power many of the tools shown today."}, {"start": 1299.0, "text": "Thanks for watching,"}, {"start": 1300.0, "text": "and I can't wait to see what you build with Reality Composer Pro!"}]}