{"id":8584,"date":"2025-12-25T07:43:02","date_gmt":"2025-12-25T12:43:02","guid":{"rendered":"https:\/\/stepinto.vision\/?p=8584"},"modified":"2025-12-25T07:43:03","modified_gmt":"2025-12-25T12:43:03","slug":"realitykit-basics-entity-observation","status":"publish","type":"post","link":"https:\/\/stepinto.vision\/example-code\/realitykit-basics-entity-observation\/","title":{"rendered":"RealityKit Basics: Entity Observation"},"content":{"rendered":"\n<p>Starting in visionOS 26, we can observe changes to component data on entities.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Overview<\/h2>\n\n\n\n<p>Since visionOS 1, we\u2019ve been able to update RealityKit entities based on changes to data in SwiftUI. We commonly do this with the update closure on RealityView. Starting with visionOS 26 it is possible for SwiftUI to observe changes to RealityKit entities. We now have two-way communication between these frameworks.<\/p>\n\n\n\n<p>To explore this, we&#8217;ll create a scene that orbits a subject around a central point. There are four way points we can collide with. We&#8217;ll animate the subject with a timeline that runs continuously. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"633\" data-attachment-id=\"8592\" data-permalink=\"https:\/\/stepinto.vision\/example-code\/realitykit-basics-entity-observation\/attachment\/step-example-138-03\/\" data-orig-file=\"https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?fit=2962%2C1832&amp;ssl=1\" data-orig-size=\"2962,1832\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"step-example-138-03\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?fit=1024%2C633&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?resize=1024%2C633&#038;ssl=1\" alt=\"\" class=\"wp-image-8592\" srcset=\"https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?resize=1024%2C633&amp;ssl=1 1024w, https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?resize=300%2C186&amp;ssl=1 300w, https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?resize=768%2C475&amp;ssl=1 768w, https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?resize=1536%2C950&amp;ssl=1 1536w, https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?resize=2048%2C1267&amp;ssl=1 2048w, https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?resize=1200%2C742&amp;ssl=1 1200w, https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-03.png?w=2580&amp;ssl=1 2580w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">The demo scene in Reality Composer Pro<\/figcaption><\/figure>\n\n\n\n<p>When we reach one, we&#8217;ll capture the name of the way point and store it in a custom component.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#000000;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#000000;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>fileprivate struct WaypointTracker: Component, Codable {\n    public var waypoint: String = \"not set\"\n    public init() {}\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki light-plus\" style=\"background-color: #FFFFFF\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #0000FF\">fileprivate<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">struct<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #267F99\">WaypointTracker<\/span><span style=\"color: #000000\">: Component, Codable {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">public<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> waypoint: <\/span><span style=\"color: #267F99\">String<\/span><span style=\"color: #000000\"> = <\/span><span style=\"color: #A31515\">&quot;not set&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">public<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">init<\/span><span style=\"color: #000000\">() {}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#000000;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#000000;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>_ = content.subscribe(to: CollisionEvents.Began.self, on: subject)  { collisionEvent in\n        subject.components&#91;WaypointTracker.self&#93;?.waypoint = collisionEvent.entityB.name\n        print(\"Waypoint Collision: \\(subject.components&#91;WaypointTracker.self&#93;!.waypoint)\")\n    }<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki light-plus\" style=\"background-color: #FFFFFF\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #001080\">_<\/span><span style=\"color: #000000\"> = content.<\/span><span style=\"color: #795E26\">subscribe<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">to<\/span><span style=\"color: #000000\">: CollisionEvents.<\/span><span style=\"color: #001080\">Began<\/span><span style=\"color: #000000\">.self, <\/span><span style=\"color: #795E26\">on<\/span><span style=\"color: #000000\">: subject)  { collisionEvent <\/span><span style=\"color: #AF00DB\">in<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        subject.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">&#91;WaypointTracker.self&#93;?.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #000000\"> = collisionEvent.<\/span><span style=\"color: #001080\">entityB<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #795E26\">print<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #A31515\">&quot;Waypoint Collision: <\/span><span style=\"color: #0000FF\">\\(<\/span><span style=\"color: #000000FF\">subject.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000FF\">&#91;WaypointTracker.<\/span><span style=\"color: #000000\">self<\/span><span style=\"color: #000000FF\">&#93;<\/span><span style=\"color: #000000\">!<\/span><span style=\"color: #000000FF\">.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #0000FF\">)<\/span><span style=\"color: #A31515\">&quot;<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    }<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>We can observe changes by using a new <a href=\"https:\/\/developer.apple.com\/documentation\/realitykit\/entity\/observable-swift.struct\/\">observable interface<\/a> on Entity. We can access common values like position, transform, or children.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#000000;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#000000;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>entity.observable.position\nentity.observable.transform\nentity.observable.children<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki light-plus\" style=\"background-color: #FFFFFF\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #000000\">entity.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">position<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">entity.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">transform<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">entity.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">children<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>We can also observe chances in components, including custom components.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#000000;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#000000;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>entity.observable.components&#91;WaypointTracker.self&#93;?.waypoint<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki light-plus\" style=\"background-color: #FFFFFF\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #000000\">entity.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">&#91;WaypointTracker.self&#93;?.<\/span><span style=\"color: #001080\">waypoint<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>We can observe this component directly in a SwiftUI view.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#000000;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#000000;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>WaypointMap(waypoint: .constant(subject.observable.components&#91;WaypointTracker.self&#93;?.waypoint ?? \"Not Found\"))<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki light-plus\" style=\"background-color: #FFFFFF\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #795E26\">WaypointMap<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">waypoint<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #795E26\">constant<\/span><span style=\"color: #000000\">(subject.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">&#91;WaypointTracker.self&#93;?.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #000000\"> ?? <\/span><span style=\"color: #A31515\">&quot;Not Found&quot;<\/span><span style=\"color: #000000\">))<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Or we can listen for changes to it. This would give us a chance to apply side effects such as saving changes in a data store.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#000000;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#000000;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>\/\/ A place to capture the data\n@State var observedWaypoint: String = \"Not Set\"\n\n\/\/ Listen for changes\n    .onChange(of: subject.observable.components&#91;WaypointTracker.self&#93;?.waypoint) { _, newValue in\n        if let newValue = newValue {\n            \/\/ Apply any side effects here\n            print(\"Observed Waypoint: \\(newValue), applying side effects...\")\n            self.observedWaypoint = newValue\n        }\n    }\n\n\/\/ Later\nWaypointMap(waypoint: $observedWaypoint)<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki light-plus\" style=\"background-color: #FFFFFF\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #008000\">\/\/ A place to capture the data<\/span><\/span>\n<span class=\"line\"><span style=\"color: #0000FF\">@State<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> observedWaypoint: <\/span><span style=\"color: #267F99\">String<\/span><span style=\"color: #000000\"> = <\/span><span style=\"color: #A31515\">&quot;Not Set&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #008000\">\/\/ Listen for changes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    .<\/span><span style=\"color: #795E26\">onChange<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">of<\/span><span style=\"color: #000000\">: subject.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">&#91;WaypointTracker.self&#93;?.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #000000\">) { <\/span><span style=\"color: #001080\">_<\/span><span style=\"color: #000000\">, newValue <\/span><span style=\"color: #AF00DB\">in<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #AF00DB\">if<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">let<\/span><span style=\"color: #000000\"> newValue = newValue {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #008000\">\/\/ Apply any side effects here<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #795E26\">print<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #A31515\">&quot;Observed Waypoint: <\/span><span style=\"color: #0000FF\">\\(<\/span><span style=\"color: #000000FF\">newValue<\/span><span style=\"color: #0000FF\">)<\/span><span style=\"color: #A31515\">, applying side effects...&quot;<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #0000FF\">self<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">observedWaypoint<\/span><span style=\"color: #000000\"> = newValue<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #008000\">\/\/ Later<\/span><\/span>\n<span class=\"line\"><span style=\"color: #795E26\">WaypointMap<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">waypoint<\/span><span style=\"color: #000000\">: $observedWaypoint)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>See also<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2025\/274\">Better together: SwiftUI and RealityKit<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.apple.com\/documentation\/realitykit\/entity\/observable-swift.struct\/\">Entity.Observable<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/stepinto.vision\/labs\/lab-063-first-look-at-entity-observation\/\" data-type=\"post\" data-id=\"5025\">Lab 063 \u2013 First look at Entity Observation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/stepinto.vision\/example-code\/collisions-physics-collision-events\/\" data-type=\"post\" data-id=\"3735\">Collisions &amp; Physics: Collision Events<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/stepinto.vision\/learn-visionos\/#behaviors-timelines-and-entity-actions\">Behaviors, Timelines, and Entity Actions<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Video Demo<\/h2>\n\n\n\n\t\t<figure class=\"wp-block-jetpack-videopress jetpack-videopress-player\" style=\"\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <div class=\"jetpack-video-wrapper\"><iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='720' height='405' src='https:\/\/videopress.com\/embed\/VbgPZ70r?cover=1&amp;autoPlay=0&amp;controls=1&amp;loop=0&amp;muted=0&amp;persistVolume=1&amp;playsinline=0&amp;preloadContent=metadata&amp;useAverageColor=1&amp;hd=0' frameborder='0' allowfullscreen data-resize-to-parent=\"true\" allow='clipboard-write'><\/iframe><script src='https:\/\/v0.wordpress.com\/js\/next\/videopress-iframe.js?m=1739540970'><\/script><\/div><\/div>\n\t\t\t\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<h2 class=\"wp-block-heading\">Example Code<\/h2>\n\n\n\n<!--more-->\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#000000;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#000000;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>struct Example138: View {\n\n    @State var collisionSubjectBegan: EventSubscription?\n    @State var subject = Entity()\n    @State var observedPosition: SIMD3&lt;Float> = .zero\n    @State var observedWaypoint: String = \"Not Set\"\n\n    init() {\n        WaypointTracker.registerComponent()\n    }\n\n    var body: some View {\n        RealityView { content in\n\n            guard let scene = try? await Entity(named: \"EntityObservationDemo\", in: realityKitContentBundle) else { return }\n            content.add(scene)\n            guard let subject = scene.findEntity(named: \"Subject\") else { return }\n            subject.components.set(WaypointTracker())\n            self.subject = subject\n\n            \/\/ This scene uses a timeline to animate the subject around the scene.\n            \/\/ We'll use this collision to update the custom component so we can observe changes from it\n            collisionSubjectBegan = content\n                .subscribe(to: CollisionEvents.Began.self, on: subject)  { collisionEvent in\n                    subject.components&#91;WaypointTracker.self&#93;?.waypoint = collisionEvent.entityB.name\n                    print(\"Waypoint Collision: \\(subject.components&#91;WaypointTracker.self&#93;!.waypoint)\")\n                }\n        }\n        \/\/ Listen for changes, peform side effects, and apply the data to state\n        .onChange(of: subject.observable.position) { _, newValue in\n            \/\/ Apply any side effects here\n            self.observedPosition = newValue\n        }\n        .onChange(of: subject.observable.components&#91;WaypointTracker.self&#93;?.waypoint) { _, newValue in\n            if let newValue = newValue {\n                \/\/ Apply any side effects here\n                print(\"Observed Waypoint: \\(newValue), applying side effects...\")\n                self.observedWaypoint = newValue\n            }\n        }\n        .ornament(attachmentAnchor: .scene(.bottomFront), ornament: {\n            VStack(alignment: .leading, spacing: 10) {\n                \/\/ Example 1: Direct usage of the observed data in SwiftUI views\n                Vector3Display(title: \"Direct Usage\", vector: subject.observable.position)\n\n                HStack(spacing: 10) {\n                    WaypointMap(waypoint: .constant(subject.observable.components&#91;WaypointTracker.self&#93;?.waypoint ?? \"Not Found\"))\n                    Spacer(minLength: 0)\n                }\n\n                Divider()\n                    .padding(.vertical, 2)\n\n                \/\/ Example 2: Observing state that is updated using onChange\n                Vector3Display(title: \"onChange Examples\", vector: observedPosition)\n\n                HStack(spacing: 10) {\n                    WaypointMap(waypoint: $observedWaypoint)\n                    Spacer(minLength: 0)\n                }\n            }\n            .padding()\n            .background(.black)\n            .clipShape(.rect(cornerRadius: 12))\n\n        })\n        .onDisappear {\n            collisionSubjectBegan?.cancel()\n            collisionSubjectBegan = nil\n        }\n    }\n}\n\nfileprivate struct WaypointMap: View {\n\n    @Binding var waypoint: String\n\n    private var symbolName: String {\n        switch waypoint.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() {\n        case \"left\":\n            return \"circle.grid.cross.left.filled\"\n        case \"right\":\n            return \"circle.grid.cross.right.filled\"\n        case \"front\":\n            return \"circle.grid.cross.down.filled\"\n        case \"back\":\n            return \"circle.grid.cross.up.filled\"\n        default:\n            return \"questionmark.circle\"\n        }\n    }\n\n    var body: some View {\n        HStack(spacing: 8) {\n            Image(systemName: symbolName)\n                .font(.system(size: 22, weight: .semibold))\n                .contentTransition(.symbolEffect(.replace))\n                .animation(.easeInOut(duration: 0.25), value: symbolName)\n\n            Text(waypoint)\n                .font(.system(size: 14, weight: .medium, design: .rounded))\n        }\n    }\n}\n\nfileprivate struct WaypointTracker: Component, Codable {\n    public var waypoint: String = \"not set\"\n    public init() {}\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki light-plus\" style=\"background-color: #FFFFFF\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #0000FF\">struct<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #267F99\">Example138<\/span><span style=\"color: #000000\">: View {<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">@State<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> collisionSubjectBegan: EventSubscription?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">@State<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> subject = <\/span><span style=\"color: #795E26\">Entity<\/span><span style=\"color: #000000\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">@State<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> observedPosition: SIMD3&lt;<\/span><span style=\"color: #267F99\">Float<\/span><span style=\"color: #000000\">&gt; = .<\/span><span style=\"color: #001080\">zero<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">@State<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> observedWaypoint: <\/span><span style=\"color: #267F99\">String<\/span><span style=\"color: #000000\"> = <\/span><span style=\"color: #A31515\">&quot;Not Set&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">init<\/span><span style=\"color: #000000\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        WaypointTracker.<\/span><span style=\"color: #795E26\">registerComponent<\/span><span style=\"color: #000000\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> body: some View {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        RealityView { content <\/span><span style=\"color: #AF00DB\">in<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">guard<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">let<\/span><span style=\"color: #000000\"> scene = <\/span><span style=\"color: #AF00DB\">try<\/span><span style=\"color: #000000\">? <\/span><span style=\"color: #AF00DB\">await<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #795E26\">Entity<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">named<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #A31515\">&quot;EntityObservationDemo&quot;<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #795E26\">in<\/span><span style=\"color: #000000\">: realityKitContentBundle) <\/span><span style=\"color: #AF00DB\">else<\/span><span style=\"color: #000000\"> { <\/span><span style=\"color: #AF00DB\">return<\/span><span style=\"color: #000000\"> }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            content.<\/span><span style=\"color: #795E26\">add<\/span><span style=\"color: #000000\">(scene)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">guard<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">let<\/span><span style=\"color: #000000\"> subject = scene.<\/span><span style=\"color: #795E26\">findEntity<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">named<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #A31515\">&quot;Subject&quot;<\/span><span style=\"color: #000000\">) <\/span><span style=\"color: #AF00DB\">else<\/span><span style=\"color: #000000\"> { <\/span><span style=\"color: #AF00DB\">return<\/span><span style=\"color: #000000\"> }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            subject.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">set<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">WaypointTracker<\/span><span style=\"color: #000000\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #0000FF\">self<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">subject<\/span><span style=\"color: #000000\"> = subject<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #008000\">\/\/ This scene uses a timeline to animate the subject around the scene.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #008000\">\/\/ We&#39;ll use this collision to update the custom component so we can observe changes from it<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            collisionSubjectBegan = content<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                .<\/span><span style=\"color: #795E26\">subscribe<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">to<\/span><span style=\"color: #000000\">: CollisionEvents.<\/span><span style=\"color: #001080\">Began<\/span><span style=\"color: #000000\">.self, <\/span><span style=\"color: #795E26\">on<\/span><span style=\"color: #000000\">: subject)  { collisionEvent <\/span><span style=\"color: #AF00DB\">in<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                    subject.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">&#91;WaypointTracker.self&#93;?.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #000000\"> = collisionEvent.<\/span><span style=\"color: #001080\">entityB<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">name<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                    <\/span><span style=\"color: #795E26\">print<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #A31515\">&quot;Waypoint Collision: <\/span><span style=\"color: #0000FF\">\\(<\/span><span style=\"color: #000000FF\">subject.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000FF\">&#91;WaypointTracker.<\/span><span style=\"color: #000000\">self<\/span><span style=\"color: #000000FF\">&#93;<\/span><span style=\"color: #000000\">!<\/span><span style=\"color: #000000FF\">.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #0000FF\">)<\/span><span style=\"color: #A31515\">&quot;<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #008000\">\/\/ Listen for changes, peform side effects, and apply the data to state<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        .<\/span><span style=\"color: #795E26\">onChange<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">of<\/span><span style=\"color: #000000\">: subject.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">position<\/span><span style=\"color: #000000\">) { <\/span><span style=\"color: #001080\">_<\/span><span style=\"color: #000000\">, newValue <\/span><span style=\"color: #AF00DB\">in<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #008000\">\/\/ Apply any side effects here<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #0000FF\">self<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">observedPosition<\/span><span style=\"color: #000000\"> = newValue<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        .<\/span><span style=\"color: #795E26\">onChange<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">of<\/span><span style=\"color: #000000\">: subject.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">&#91;WaypointTracker.self&#93;?.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #000000\">) { <\/span><span style=\"color: #001080\">_<\/span><span style=\"color: #000000\">, newValue <\/span><span style=\"color: #AF00DB\">in<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">if<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">let<\/span><span style=\"color: #000000\"> newValue = newValue {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #008000\">\/\/ Apply any side effects here<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #795E26\">print<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #A31515\">&quot;Observed Waypoint: <\/span><span style=\"color: #0000FF\">\\(<\/span><span style=\"color: #000000FF\">newValue<\/span><span style=\"color: #0000FF\">)<\/span><span style=\"color: #A31515\">, applying side effects...&quot;<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #0000FF\">self<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">observedWaypoint<\/span><span style=\"color: #000000\"> = newValue<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        .<\/span><span style=\"color: #795E26\">ornament<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">attachmentAnchor<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #795E26\">scene<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #001080\">bottomFront<\/span><span style=\"color: #000000\">), <\/span><span style=\"color: #795E26\">ornament<\/span><span style=\"color: #000000\">: {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #795E26\">VStack<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">alignment<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #001080\">leading<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #795E26\">spacing<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">10<\/span><span style=\"color: #000000\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #008000\">\/\/ Example 1: Direct usage of the observed data in SwiftUI views<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #795E26\">Vector3Display<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">title<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #A31515\">&quot;Direct Usage&quot;<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #795E26\">vector<\/span><span style=\"color: #000000\">: subject.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">position<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #795E26\">HStack<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">spacing<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">10<\/span><span style=\"color: #000000\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                    <\/span><span style=\"color: #795E26\">WaypointMap<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">waypoint<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #795E26\">constant<\/span><span style=\"color: #000000\">(subject.<\/span><span style=\"color: #001080\">observable<\/span><span style=\"color: #000000\">.<\/span><span style=\"color: #001080\">components<\/span><span style=\"color: #000000\">&#91;WaypointTracker.self&#93;?.<\/span><span style=\"color: #001080\">waypoint<\/span><span style=\"color: #000000\"> ?? <\/span><span style=\"color: #A31515\">&quot;Not Found&quot;<\/span><span style=\"color: #000000\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                    <\/span><span style=\"color: #795E26\">Spacer<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">minLength<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">0<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #795E26\">Divider<\/span><span style=\"color: #000000\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                    .<\/span><span style=\"color: #795E26\">padding<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #001080\">vertical<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #098658\">2<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #008000\">\/\/ Example 2: Observing state that is updated using onChange<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #795E26\">Vector3Display<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">title<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #A31515\">&quot;onChange Examples&quot;<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #795E26\">vector<\/span><span style=\"color: #000000\">: observedPosition)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                <\/span><span style=\"color: #795E26\">HStack<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">spacing<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">10<\/span><span style=\"color: #000000\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                    <\/span><span style=\"color: #795E26\">WaypointMap<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">waypoint<\/span><span style=\"color: #000000\">: $observedWaypoint)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                    <\/span><span style=\"color: #795E26\">Spacer<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">minLength<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">0<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            .<\/span><span style=\"color: #795E26\">padding<\/span><span style=\"color: #000000\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            .<\/span><span style=\"color: #795E26\">background<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #001080\">black<\/span><span style=\"color: #000000\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            .<\/span><span style=\"color: #795E26\">clipShape<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #795E26\">rect<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">cornerRadius<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">12<\/span><span style=\"color: #000000\">))<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        })<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        .<\/span><span style=\"color: #001080\">onDisappear<\/span><span style=\"color: #000000\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            collisionSubjectBegan?.<\/span><span style=\"color: #795E26\">cancel<\/span><span style=\"color: #000000\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            collisionSubjectBegan = <\/span><span style=\"color: #0000FF\">nil<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #0000FF\">fileprivate<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">struct<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #267F99\">WaypointMap<\/span><span style=\"color: #000000\">: View {<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">@Binding<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> waypoint: <\/span><span style=\"color: #267F99\">String<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">private<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> symbolName: <\/span><span style=\"color: #267F99\">String<\/span><span style=\"color: #000000\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #AF00DB\">switch<\/span><span style=\"color: #000000\"> waypoint.<\/span><span style=\"color: #795E26\">trimmingCharacters<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">in<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #001080\">whitespacesAndNewlines<\/span><span style=\"color: #000000\">).<\/span><span style=\"color: #795E26\">lowercased<\/span><span style=\"color: #000000\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #AF00DB\">case<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;left&quot;<\/span><span style=\"color: #000000\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">return<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;circle.grid.cross.left.filled&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #AF00DB\">case<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;right&quot;<\/span><span style=\"color: #000000\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">return<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;circle.grid.cross.right.filled&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #AF00DB\">case<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;front&quot;<\/span><span style=\"color: #000000\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">return<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;circle.grid.cross.down.filled&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #AF00DB\">case<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;back&quot;<\/span><span style=\"color: #000000\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">return<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;circle.grid.cross.up.filled&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #AF00DB\">default<\/span><span style=\"color: #000000\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #AF00DB\">return<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #A31515\">&quot;questionmark.circle&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> body: some View {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        <\/span><span style=\"color: #795E26\">HStack<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">spacing<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">8<\/span><span style=\"color: #000000\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #795E26\">Image<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">systemName<\/span><span style=\"color: #000000\">: symbolName)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                .<\/span><span style=\"color: #795E26\">font<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #795E26\">system<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">size<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">22<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #795E26\">weight<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #001080\">semibold<\/span><span style=\"color: #000000\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                .<\/span><span style=\"color: #795E26\">contentTransition<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #795E26\">symbolEffect<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #001080\">replace<\/span><span style=\"color: #000000\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                .<\/span><span style=\"color: #795E26\">animation<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #795E26\">easeInOut<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">duration<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">0.25<\/span><span style=\"color: #000000\">), <\/span><span style=\"color: #795E26\">value<\/span><span style=\"color: #000000\">: symbolName)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #000000\">            <\/span><span style=\"color: #795E26\">Text<\/span><span style=\"color: #000000\">(waypoint)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">                .<\/span><span style=\"color: #795E26\">font<\/span><span style=\"color: #000000\">(.<\/span><span style=\"color: #795E26\">system<\/span><span style=\"color: #000000\">(<\/span><span style=\"color: #795E26\">size<\/span><span style=\"color: #000000\">: <\/span><span style=\"color: #098658\">14<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #795E26\">weight<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #001080\">medium<\/span><span style=\"color: #000000\">, <\/span><span style=\"color: #795E26\">design<\/span><span style=\"color: #000000\">: .<\/span><span style=\"color: #001080\">rounded<\/span><span style=\"color: #000000\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #0000FF\">fileprivate<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">struct<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #267F99\">WaypointTracker<\/span><span style=\"color: #000000\">: Component, Codable {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">public<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">var<\/span><span style=\"color: #000000\"> waypoint: <\/span><span style=\"color: #267F99\">String<\/span><span style=\"color: #000000\"> = <\/span><span style=\"color: #A31515\">&quot;not set&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">    <\/span><span style=\"color: #0000FF\">public<\/span><span style=\"color: #000000\"> <\/span><span style=\"color: #0000FF\">init<\/span><span style=\"color: #000000\">() {}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #000000\">}<\/span><\/span><\/code><\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Starting in visionOS 26, we can observe changes to component data on entities.<\/p>\n","protected":false},"author":93705089,"featured_media":8587,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_EventAllDay":false,"_EventTimezone":"","_EventStartDate":"","_EventEndDate":"","_EventStartDateUTC":"","_EventEndDateUTC":"","_EventShowMap":false,"_EventShowMapLink":false,"_EventURL":"","_EventCost":"","_EventCostDescription":"","_EventCurrencySymbol":"","_EventCurrencyCode":"","_EventCurrencyPosition":"","_EventDateTimeSeparator":"","_EventTimeRangeSeparator":"","_EventOrganizerID":[],"_EventVenueID":[],"_OrganizerEmail":"","_OrganizerPhone":"","_OrganizerWebsite":"","_VenueAddress":"","_VenueCity":"","_VenueCountry":"","_VenueProvince":"","_VenueState":"","_VenueZip":"","_VenuePhone":"","_VenueURL":"","_VenueStateProvince":"","_VenueLat":"","_VenueLng":"","_VenueShowMap":false,"_VenueShowMapLink":false,"_kadence_starter_templates_imported_post":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[1365],"tags":[],"class_list":["post-8584","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-example-code"],"jetpack_publicize_connections":[],"taxonomy_info":{"category":[{"value":1365,"label":"Example Code"}]},"featured_image_src_large":["https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-02.jpeg?fit=1024%2C576&ssl=1",1024,576,true],"author_info":{"display_name":"Joseph Simpson","author_link":"https:\/\/stepinto.vision\/author\/vrhermit\/"},"comment_info":0,"category_info":[{"term_id":1365,"name":"Example Code","slug":"example-code","term_group":0,"term_taxonomy_id":11,"taxonomy":"category","description":"Code snippets and examples of using common APIs throughout visionOS development","parent":0,"count":187,"filter":"raw","cat_ID":1365,"category_count":187,"category_description":"Code snippets and examples of using common APIs throughout visionOS development","cat_name":"Example Code","category_nicename":"example-code","category_parent":0}],"tag_info":false,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/stepinto.vision\/wp-content\/uploads\/2025\/12\/step-example-138-02.jpeg?fit=3840%2C2160&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/posts\/8584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/users\/93705089"}],"replies":[{"embeddable":true,"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/comments?post=8584"}],"version-history":[{"count":17,"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/posts\/8584\/revisions"}],"predecessor-version":[{"id":8608,"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/posts\/8584\/revisions\/8608"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/media\/8587"}],"wp:attachment":[{"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/media?parent=8584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/categories?post=8584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/stepinto.vision\/wp-json\/wp\/v2\/tags?post=8584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}