-
Xcode로 Reality Composer Pro 3 기능 확장하기
Reality Composer Pro 3로 어떻게 더 크고 야심 찬 공간 프로젝트를 빌드할 수 있는지 확인해 보세요. 맞춤형 구성요소를 편집할 수 있는 프로젝트별 플러그인을 생성하고, 맞춤형 시스템을 실행하며, 고유한 ScriptGraph 노드를 빌드하여 공간 제작 워크플로를 완벽하게 제어하는 방법을 알아보세요.
챕터
- 0:00 - Introduction
- 2:00 - Extending the editor
- 4:51 - Custom components and systems
- 10:32 - Controlling the water surface
- 13:19 - Custom animation actions
- 17:12 - Custom Script Graph nodes
- 21:16 - Next steps
리소스
관련 비디오
WWDC26
-
비디오 검색…
안녕하세요, 저는 Niklas입니다 이 세션에서는 플러그인으로 Reality Composer Pro를 확장하는 방법을 보여드리겠습니다 아티스트와 콘텐츠 제작자가 에디터에서 직접 작업할 수 있도록 에셋을 에디터에서 바로 다룰 수 있게 됩니다 빠른 반복 작업과 다양한 3D 앱 및 게임 제작이 가능합니다 이 기능은 올해 말에 제공될 예정입니다
이것은 Reality Composer Pro 3입니다 RealityKit을 위한 Apple의 최신 게임 및 3D 콘텐츠 에디터입니다 이 업데이트 버전은 더 큰 씬을 지원합니다 콘텐츠를 빠르게 반복할 수 있는 아티스트 친화적인 워크플로우와 헤드셋에서 씬을 미리 볼 수 있는 기능도 포함됩니다
Reality Composer Pro 3 사용 방법은 다음 세션에서 더 자세히 알아볼 수 있습니다 "Reality Composer Pro 3로 공간 씬을 더 빠르게 반복하세요" 또 다른 추천 세션도 있습니다 "Reality Composer Pro 3로 코딩 없이 게임 디자인하기" 이 세션에서는 코드 없이 게임을 빌드하는 방법을 보여드립니다 Reality Composer Pro의 비주얼 스크립팅 도구인 Script Graph를 활용합니다 이번 발표에서는 코드로 무엇을 할 수 있는지 보여드리겠습니다 Xcode에서 플러그인을 빌드하는 방법을 보여드리겠습니다 프로젝트별 콘텐츠를 Reality Composer Pro 3에 노출할 수 있습니다 커스텀 컴포넌트가 에디터 내에 표시됩니다 아티스트와 디자이너가 조정할 수 있습니다 예를 들어 아티스트가 수면 높이를 바꾸거나 회전 속도를 조절하면 가마솥이 실시간으로 반응합니다 앱을 빌드하고 배포하지 않아도 됩니다
먼저 에디터를 확장하는 일반적인 메커니즘을 살펴보겠습니다 그런 다음 이를 사용하는 방법을 보여드리겠습니다 커스텀 컴포넌트와 커스텀 시스템을 에디터에서 실행하는 방법입니다 커스텀 애니메이션을 추가하는 방법도 보여드리겠습니다 시퀀서 타임라인에 추가합니다 마지막으로 커스텀 노드를 만드는 방법을 보여드리겠습니다 Script Graph를 위한 것입니다 먼저 일반적인 메커니즘부터 살펴보겠습니다 Reality Composer Pro를 확장하는 방법과 팀 작업 시 어떻게 동작하는지 알아봅니다 Chaparral Village 게임에서 작업하겠습니다 이 게임은 개발자, 아티스트, 디자이너 팀이 만들었습니다 이 게임에는 Reality Composer Pro 프로젝트와 Xcode 프로젝트가 모두 있습니다 에디터 프로젝트는 주로 아티스트와 디자이너가 사용합니다 경험의 콘텐츠를 만드는 데 활용합니다 Xcode 프로젝트는 엔지니어가 최종 앱을 빌드하는 데 사용됩니다 아티스트가 에디터에서 커스텀 데이터를 만들 수 있는 플러그인도 포함됩니다
Reality Composer Pro 프로젝트와 Xcode 프로젝트는 연결되어 있습니다 에디터 내에서 직접 앱을 실행할 수 있습니다
자신의 프로젝트에도 이 연결을 설정할 수 있습니다 창 상단의 시뮬레이션 바를 사용하세요 에디터 프로젝트와 Xcode 프로젝트는 같은 git 저장소에 함께 있습니다 아티스트와 엔지니어는 로컬에서 변경하고 커밋 및 푸시합니다 나머지 팀원들과 공유하기 위해서입니다
Reality Composer Pro 3에서 파일을 가져오면 내부 데이터 형식으로 변환됩니다 JSON 파일로 디스크에 저장됩니다 git의 내장 도구를 사용해 변경 사항을 병합할 수 있습니다 에디터에는 커스텀 병합 도구도 함께 제공됩니다 표준 git 병합보다 충돌이 적게 파일을 병합할 수 있습니다 Reality Composer Pro 3에서 앱으로 데이터를 가져오려면 RealityKit의 직렬화 형식인 Reality File로 내보냅니다
이 모든 것이 어떻게 연결되는지 보여주는 그림입니다 Xcode 프로젝트는 최종 게임 앱을 빌드하는 데 사용됩니다 Reality Composer Pro 3용 플러그인 프레임워크도 빌드합니다 Reality Composer Pro 3는 다양한 3D 씬을 설정하는 데 사용됩니다 게임의 오브젝트들도 포함됩니다 RCPCustomComponents.framework는 개발자가 만든 컴포넌트와 시스템을 에디터에서 사용 가능하게 합니다
아티스트와 레벨 디자이너가 편집할 수 있게 됩니다 동작 방식을 확인하고 콘텐츠를 인터랙티브하게 개선합니다
마지막으로 Reality Composer Pro 3에서 만든 씬은 Reality File로 내보내집니다 앱에 링크되어 로드됩니다
코드가 업데이트되면 개발자가 새 플러그인 프레임워크를 빌드합니다 팀 전체가 사용하고 새 앱도 포함됩니다 콘텐츠가 변경되면 새 reality file을 내보내 최종 앱에서 테스트합니다 Xcode 프로젝트에는 두 가지 스키마가 설정되어 있습니다 ChaparralVillage는 실제 앱을 빌드합니다 그리고 RCPCustomComponents는 Reality Composer Pro 3용 플러그인을 빌드합니다 프로젝트의 모든 커스텀 컴포넌트와 커스텀 시스템은 이 두 스키마 간에 공유됩니다 어떻게 동작하는지 살펴보겠습니다 플러그인 시스템을 사용해 커스텀 컴포넌트를 만들겠습니다 Reality Composer Pro에 노출시킬 것입니다 아티스트와 협력해 이 가마솥에 이펙트를 만들겠습니다 게임에서 가마솥은 포션을 섞는 데 사용됩니다 수면 높이를 제어할 수 있게 하고 싶습니다 재료를 추가할 때 올라가고 내려갈 수 있도록 소용돌이 효과도 추가하고 싶습니다 포션을 섞을 때 물이 회전하는 것을 볼 수 있게 합니다 먼저 수면 높이 설정부터 시작하겠습니다
Script Graph로도 구현할 수 있습니다 이런 모습이 될 것입니다 업데이트 이벤트에서 수면 엔티티를 가져옵니다 특정 위치로 이동시킵니다 더 고급 기능이 필요하다면 커스텀 컴포넌트를 사용하는 것이 좋을 수 있습니다 Script Graph 대신에 말이죠 Script Graph와 커스텀 Swift 코드는 비슷한 작업을 할 수 있습니다 어떤 것을 사용할지는 개인 취향에 달려 있습니다 하지만 너무 큰 Script Graph는 유지 관리가 어렵습니다 그래서 코드로 전환하는 것이 좋은 이유가 될 수 있습니다 코드를 사용하면 다른 Apple API와도 상호작용할 수 있습니다 Script Graph에서 사용할 수 없는 SwiftUI 같은 것들도요 가마솥의 경우 수면 높이를 다른 시스템과 연결하고 싶습니다 수면에 떠다니는 재료처럼 다른 시스템들과 연동합니다 그래서 코드로 작성하는 것이 맞습니다 이를 위해 먼저 간단한 컴포넌트를 만들겠습니다 가마솥의 수면 높이를 저장합니다 수면 높이를 저장하는 단일 프로퍼티가 있습니다
Component 프로토콜 외에도 Cauldron은 Codable도 구현합니다 이 컴포넌트를 표현하는 데 필요합니다 Reality Composer Pro 3에서 Reality File에 직렬화하기 위해서입니다 더 고급 컴포넌트의 경우 에디터에 표시되지 않아야 하는 런타임 프로퍼티가 있으면 CodingKeys를 구현하는 것도 좋을 수 있습니다 하지만 이 간단한 컴포넌트의 경우 모든 프로퍼티를 직렬화하고 싶으므로 필요하지 않습니다 다음으로 수면 높이를 설정하는 커스텀 시스템을 만들겠습니다 시스템 업데이트에서 Cauldron 컴포넌트가 있는 엔티티를 찾습니다 그런 다음 물 메쉬 자식 엔티티를 찾습니다 물 메쉬의 위치를 조정합니다 Cauldron 컴포넌트에 설정된 수면 높이를 기반으로 합니다 그 다음 Reality Composer Pro 3가 커스텀 컴포넌트와 해당 시스템을 사용할 수 있도록 해야 합니다 이를 위해 플러그인 클래스를 만들어야 합니다 RealityComposerProPlugin 프로토콜을 구현합니다 이 프로토콜은 RealityComposerPro Swift 패키지에서 제공됩니다 이 패키지는 Xcode 프로젝트에 자동으로 추가됩니다 에디터에서 연결하면 시뮬레이션 툴바의 Xcode로 실행 옵션을 사용하면 됩니다 이 클래스의 setup 메서드에서 Reality Composer Pro에서 받은 context를 사용합니다 컴포넌트와 시스템을 등록합니다 이렇게 하면 에디터에서 이 컴포넌트와 시스템을 사용할 수 있게 됩니다
Reality Composer Pro 3가 플러그인을 생성할 수 있게 해야 합니다 createRealityComposerProPlugin() 함수를 구현하면 됩니다 플러그인을 만들고 반환합니다 이 함수가 클래스를 raw pointer로 반환하는 것을 확인할 수 있습니다 DLL 인터페이스에서 이 함수를 내보내야 하기 때문입니다 C 함수로 표시해야 합니다 내보낸 이름도 지정해야 합니다 플러그인 로더가 찾을 수 있도록 하기 위해서입니다 이 모든 것이 실제로 어떻게 동작하는지 살펴보겠습니다 먼저 waterLevel 프로퍼티로 Cauldron 컴포넌트를 만들겠습니다
그런 다음 프로퍼티 값을 기반으로 물 평면의 위치를 설정하는 시스템을 추가합니다 프로퍼티 값을 기반으로 합니다
마지막으로 컴포넌트와 시스템을 등록하겠습니다 Reality Composer Pro에 등록합니다
이제 플러그인 스키마를 빌드해 동적 라이브러리를 만들 수 있습니다
이제 에디터에서 프로젝트를 열 수 있습니다 이 프로젝트에는 플러그인이 있어서 Reality Composer Pro가 신뢰 여부를 물어봅니다 Trust를 선택해 플러그인을 로드합니다
플러그인 로드를 수락하면 에디터가 가져온 컴포넌트를 보여줍니다
프로젝트 빌드 설정으로 이동하면 가져온 컴포넌트와 시스템도 표시됩니다 이 설정 패널에서 커스텀 플러그인 디렉토리를 지정할 수도 있습니다
가져온 컴포넌트는 프로젝트의 Custom Components 폴더에 있습니다 컴포넌트를 가져오고 Reality Composer Pro 3가 인식하게 되면 Cauldron 엔티티에 추가할 수 있습니다
에디터에서 수면 높이 프로퍼티를 변경하면 수면이 반응하는 것을 볼 수 있습니다 커스텀 시스템이 에디터 내에서 실행되고 있습니다 플러그인 메커니즘을 통해 프로퍼티 값을 기반으로 수면 높이를 변경합니다 아티스트와 디자이너는 에디터에서 프로퍼티를 세밀하게 조정할 수 있습니다 앱을 재빌드하거나 재실행할 필요가 없습니다
시스템을 디버그하고 싶다면 코드에 브레이크포인트를 설정하고 에디터 애플리케이션에 연결하면 됩니다
코드가 실행되면 Xcode 디버거에서 멈추게 됩니다 로직을 확인할 수 있습니다
기본 수면이 작동하게 되었으니 소용돌이 효과를 추가해 한 단계 더 발전시키겠습니다 플레이어가 포션을 섞기 위해 가마솥을 저을 때 수면이 소용돌이 모양으로 변하게 하고 싶습니다 수면 모양을 바꾸기 위해 테크 아티스트가 이 소용돌이 셰이더를 만들었습니다 Reality Composer Pro 3의 Shader Graph 시스템을 사용했습니다 Shader Graph에는 회전 속도 같은 파라미터가 있습니다 그 파라미터를 기반으로 소용돌이 모양을 만듭니다 이 파라미터들을 제어하고 싶습니다 커스텀 컴포넌트에서 제어합니다 이를 위해 먼저 프로퍼티를 추가합니다 소용돌이 모양을 안내하는 프로퍼티입니다 그런 다음 이전의 cauldron 시스템을 수정해야 합니다 이 파라미터들이 Shader Graph로 전달되도록 합니다 먼저 Shader Graph 머티리얼을 가져옵니다 그런 다음 헬퍼 함수를 사용합니다 수면 모양을 계산합니다 Cauldron 프로퍼티를 기반으로 합니다 계산된 모양을 사용해 Shader Graph 파라미터를 설정합니다 마지막으로 이 머티리얼을 모델에 다시 적용합니다 실제로 어떻게 동작하는지 살펴보겠습니다 먼저 Cauldron에 새 프로퍼티를 추가하겠습니다
그런 다음 수면을 계산하는 함수를 작성하겠습니다
마지막으로 셰이더 파라미터를 설정하도록 시스템을 업데이트하고 플러그인을 다시 빌드합니다
플러그인을 다시 빌드할 때마다 변경 사항을 반영하려면 Reality Composer Pro를 다시 시작해야 합니다 Reality Composer Pro가 프로젝트를 신뢰할지 다시 묻습니다 이 다이얼로그를 더 이상 표시하지 않으려면 "다시 묻지 않기" 체크박스를 선택하세요
다음으로 커스텀 컴포넌트의 변경 사항을 보여주는 다이얼로그가 나타납니다 모두 괜찮아 보이므로 수락하겠습니다
Cauldron 컴포넌트로 돌아가면 새 프로퍼티가 표시됩니다
수면 높이에 대한 기본값을 설정하겠습니다 소용돌이 계수도 함께 설정합니다
이제 회전 속도에 다양한 값을 시도해 보겠습니다 회전 속도를 높이면 소용돌이가 더 깊어집니다
다음으로 애니메이션 시스템에서 플러그인을 사용하는 방법을 알아보겠습니다 애니메이션 시퀀서는 커스텀 애니메이션 액션을 지원합니다 플러그인에서 정의할 수 있습니다 그런 다음 시퀀서 타임라인에 추가합니다 가마솥의 수면 높이를 설정하는 커스텀 액션을 만들겠습니다 이를 위해 EntityAction 프로토콜을 구현해야 합니다 Reality File에 저장하려면 Codable이어야 합니다
내 액션은 두 가지 파라미터를 받습니다 시작 수위와 수면의 끝 수위입니다 두 값 사이를 애니메이션화할 수 있습니다
EntityAction 프로토콜에서 애니메이션된 값 타입을 Transform으로 반환해야 합니다 애니메이션 실행자에서 엔티티에 접근하기 위해 필요합니다 액션을 실행하는 코드도 작성해야 합니다 애니메이션이 실행될 때 수면 높이를 업데이트합니다
이를 위해 엔티티 액션에 정적 subscribe() 함수를 만듭니다 플러그인 로딩 코드에서 호출할 것입니다
이 함수에서 EntityAction의 subscribe 메서드를 사용합니다 .updated 이벤트를 구독합니다 RealityKit이 애니메이션을 실행할 때 호출됩니다 커스텀 애니메이션 액션을 수행하는 데 사용합니다 경과된 애니메이션 시간을 0과 1 사이의 정규화된 숫자로 가져옵니다
그런 다음 현재 수면 높이를 계산합니다 정규화된 시간을 사용해 시작과 끝 수면 높이 사이를 보간합니다 엔티티에서 cauldron 컴포넌트를 가져와 수면 높이를 업데이트합니다 마지막으로 수정된 cauldron 컴포넌트를 엔티티에 다시 설정합니다 마지막 단계는 이 커스텀 애니메이션을 등록하는 것입니다 Reality Composer Pro 3에 등록합니다
커스텀 컴포넌트와 커스텀 시스템과 마찬가지로 context에 액션을 등록해야 합니다 에디터가 인식할 수 있도록 합니다
앞서 만든 subscribe 함수도 호출해야 합니다 애니메이션 업데이트 시 액션이 실행되도록 합니다 실제로 어떻게 동작하는지 살펴보겠습니다 먼저 커스텀 엔티티 액션을 정의하겠습니다
그런 다음 이 액션을 구현하는 코드를 추가합니다
마지막으로 에디터에 이 액션을 등록하고 플러그인을 다시 빌드합니다
에디터를 다시 시작하고 프로젝트를 열면 새 액션이 가져와졌음을 알려줍니다
이 액션을 사용하는 애니메이션을 만들어 보겠습니다 먼저 에디터에서 새 시퀀스를 만들겠습니다
그런 다음 시퀀스를 열고 내 애니메이션의 루트 엔티티를 설정합니다 가마솥이 포함된 씬으로 설정합니다 이를 위해 CauldronWorld라는 씬을 준비했습니다
다음으로 시퀀스에 애니메이션 트랙을 추가합니다 이 트랙에 사용할 엔티티로 가마솥을 선택합니다
이제 왼쪽 패널에서 SetWaterLevelAction을 드래그합니다 트랙 타임라인으로 드래그해 가마솥에서 실행되는 액션을 만듭니다 인스펙터에서 이 액션을 펼쳐 파라미터를 설정합니다 가마솥 수면 높이의 시작과 종료 값입니다 시작 값을 0.3으로, 종료 값을 0.5로 설정하겠습니다 이제 애니메이션을 재생할 수 있습니다 커스텀 액션을 기반으로 수면 높이가 변하는 것을 볼 수 있습니다
아티스트와 디자이너는 Script Graph를 사용해 게임플레이와 인터랙티비티를 만들 수 있습니다 코드를 작성하지 않고 Reality Composer Pro 3 프로젝트에서 활용합니다 기본 제공 스크립트 노드가 많은 것을 처리해 줍니다 한 단계 더 발전시키고 싶다면 플러그인으로 커스텀 노드를 추가할 수 있습니다 디자이너가 Script Graph에서 활용할 수 있습니다 커스텀 컴포넌트를 Script Graph에 노출하는 가장 빠른 방법은 @Scriptable 매크로를 사용하는 것입니다 이를 위해 먼저 RealityKitScripting을 가져와야 합니다 그리고 RealityKitScriptingMacros 모듈도요 이 매크로가 정의된 곳입니다 RealityComposerPro Swift 패키지와 마찬가지로 이 패키지도 Xcode 프로젝트를 만들 때 자동으로 설정됩니다 Reality Composer Pro 내에서 만들면 됩니다 그런 다음 컴포넌트 struct에 @Scriptable 매크로를 태그합니다 schema 변수로 확장됩니다 컴포넌트를 설명하는 스크립팅 시스템에 등록할 수 있게 해줍니다 다른 모든 등록과 마찬가지로 이는 플러그인의 setup 함수에서 이루어집니다 스크립팅 모듈은 메인 스레드에서 등록해야 합니다
먼저 프로젝트를 위한 스크립팅 configuration을 만듭니다 configuration의 이니셜라이저에서 모든 스크립팅 모듈의 목록을 반환해야 합니다
Cauldron schema를 담는 단일 모듈을 만들겠습니다 이 schema는 @Scriptable 매크로로 생성됩니다 그런 다음 RealityKitScripting에 configuration을 추가합니다 실제로 어떻게 동작하는지 살펴보겠습니다 먼저 스크립팅 모듈을 가져오겠습니다 그리고 Cauldron 컴포넌트에 @Scriptable 매크로를 추가합니다
그런 다음 스크립팅 모듈을 에디터에 등록하는 코드를 추가하고 플러그인을 다시 빌드합니다
Script Graph를 만들어 보겠습니다 Cauldron 컴포넌트의 새 커스텀 노드를 활용합니다 Cauldron 엔티티에 Scripting 컴포넌트를 추가하겠습니다
새 컴포넌트를 더블클릭해 Script Graph 에디터를 엽니다 사용자가 키보드 키를 누르면 수면 높이가 변경되도록 만들겠습니다 update 노드를 추가하겠습니다 이 노드는 씬이 업데이트될 때마다 실행됩니다
다음으로 If 노드를 추가해 키 입력과 연결합니다 키를 누를 때마다 노드가 실행되도록 합니다
If 노드에서 true 커넥터를 연결합니다 가마솥의 수면 높이를 설정합니다
이제 "a" 키를 누르면 가마솥의 수면 높이가 0.25로 설정됩니다 다른 키를 연결해 다른 수면 높이를 설정하겠습니다 전체 그래프를 복사하고 붙여넣기 하겠습니다
복사본에서 키를 "z"로, 수면 높이를 0.5로 변경합니다
시뮬레이션 뷰를 열어서 테스트해 볼 수 있습니다 "a"와 "z" 키를 누르면 수면 높이가 오르내립니다
이번 세션에서 많은 내용을 다뤘습니다 Xcode를 사용해 간단한 플러그인을 만드는 방법을 보여드렸습니다 에디터의 기능을 확장하는 방법입니다 앱 데이터를 다루고 에디터 내에서 코드를 실행할 수 있습니다 더 알아보려면 다음을 추천합니다 "RealityKit의 발전 사항 탐색" 세션을 확인해 보세요 RealityKit의 최신 추가 사항을 알아볼 수 있습니다 다음 세션도 추천합니다 "Reality Composer Pro 3로 공간 워크플로우 강화하기" 세션도 있습니다 에디터로 생산성을 높이는 방법을 다룹니다 새 Reality Composer Pro 3로 여러분이 만들 놀라운 경험들이 기대됩니다 시청해 주셔서 감사합니다!
-
-
6:08 - Cauldron component
// Add a component to represent the water level import RealityKit public struct Cauldron: Component, Codable { public var waterLevel: Float enum CodingKeys: CodingKey { case waterLevel } } -
6:42 - CauldronSystem
// Add a system to control the water level import RealityKit public struct CauldronSystem: System { let query = EntityComponentQuery(Cauldron.self) public init(scene: Scene) {} public func update(context: SceneUpdateContext) { for (entity, cauldron) in context.entities(matching: query) { guard let water = entity.findEntity(named: "Cauldron_Water_mesh") else { continue } water.setPosition(SIMD3<Float>(0, 1, 0) * cauldron.waterLevel, relativeTo: entity) } } } -
7:00 - RCPCustomComponentsPlugin
// Make sure that Reality Composer Pro 3 knows about the Cauldron and CauldronSystem import RealityComposerPro final class RCPCustomComponentsPlugin: RealityComposerProPlugin { public func setup(context: any RealityComposerProContext) { context.registerComponent(Cauldron.self) context.registerSystem(CauldronSystem.self) } } @_cdecl("createRealityComposerProPlugin") public func createRealityComposerProPlugin() -> UnsafeMutableRawPointer { return RCPCustomComponentsPlugin().passRetained() } -
10:49 - Cauldron component with vortex properties
// Properties to control water surface import RealityKit public struct Cauldron: Component, Codable { public var waterLevel: Float public var rotationSpeed: Float public var minWaterLevel: Float public var maxWaterLevel: Float public var vortexCoeff: Float } -
11:05 - CauldronSystem update with ShaderGraph
public func update(context: SceneUpdateContext) { for (entity, cauldron) in context.entities(matching: query) { guard let water = entity.findEntity(named: "Cauldron_Water_mesh") else { continue } water.setPosition(SIMD3<Float>(0, 1, 0) * cauldron.waterLevel, relativeTo: entity) guard var model = water.components[ModelComponent.self] else { continue } guard var mat = model.materials.first as? ShaderGraphMaterial else { continue } let surface = computeSurface(cauldron: cauldron) try? mat.setParameter(name: "Level Radius", value: .float(surface.levelRadius)) try? mat.setParameter(name: "Lowest Point", value: .float(cauldron.waterLevel - surface.lowestPoint)) try? mat.setParameter(name: "Height Change", value: .float(surface.heightChange)) try? mat.setParameter(name: "Level Coeff", value: .float(surface.levelCoeff)) try? mat.setParameter(name: "Is Level", value: .bool(surface.isLevel)) model.materials[0] = mat water.components.set(model) } } -
13:25 - SetWaterLevelAction
// Custom action for setting the water level of the Cauldron import RealityKit public struct SetWaterLevelAction: EntityAction, Codable { // Parameters for the action public let startWaterLevel: Float public let endWaterLevel: Float // Required by EntityAction protocol public var animatedValueType: (any AnimatableData.Type)? { Transform.self } } -
14:05 - SetWaterLevelAction subscribe
extension SetWaterLevelAction { static func subscribe() { Task { @MainActor in SetWaterLevelAction.subscribe(to: .updated) { event in let normalizedTime = (event.playbackController.time - event.startTime) / event.duration let action = event.action let currentLevel = action.startWaterLevel + Float(normalizedTime) * (action.endWaterLevel - action.startWaterLevel) guard let entity = event.targetEntity else { return } guard var cauldron = entity.components[Cauldron.self] else { return } cauldron.waterLevel = currentLevel entity.components.set(cauldron) } } } } -
14:56 - RCPCustomComponentsPlugin with action
// Make sure that Reality Composer Pro 3 knows about the SetWaterLevelAction import RealityComposerPro final class RCPCustomComponentsPlugin: RealityComposerProPlugin { public func setup(context: any RealityComposerProContext) { context.registerComponent(Cauldron.self) context.registerSystem(CauldronSystem.self) context.registerAction(SetWaterLevelAction.self) SetWaterLevelAction.subscribe() } } @_cdecl("createRealityComposerProPlugin") public func createRealityComposerProPlugin() -> UnsafeMutableRawPointer { return RCPCustomComponentsPlugin().passRetained() } -
17:32 - Cauldron with @Scriptable macro
// Expose Cauldron to Script Graphs import RealityKit import RealityKitScripting import RealityKitScriptingMacros @Scriptable public struct Cauldron: Component, Codable { public var waterLevel: Float public var rotationSpeed: Float public var minWaterLevel: Float public var maxWaterLevel: Float public var vortexCoeff: Float } -
18:08 - Register scripting module
// Register scripting module public func setup(context: any RealityComposerProContext) { context.registerComponent(Cauldron.self) context.registerSystem(CauldronSystem.self) context.registerAction(SetWaterLevelAction.self) SetWaterLevelAction.subscribe() Task { @MainActor in let config = RKS.Configuration(id: "ChaparralVillage") .onInitialize { _ in [ Module("ChaparralVillage") { Cauldron.SchemaProvider.schema } ] } try! RKS.addConfiguration(config) } }
-
-
- 0:00 - Introduction
An overview of the Reality Composer Pro 3 plugin system, showing how Xcode and the editor share a project to let engineers and artists collaborate — with custom components, systems, animation actions, and Script Graph nodes all running live inside the editor.
- 2:00 - Extending the editor
Learn how the Reality Composer Pro 3 plugin system works: how the editor and Xcode share a single git repository, how custom Swift code is compiled into a dynamic library, and how the editor loads and trusts plugins at runtime.
- 4:51 - Custom components and systems
Build a Cauldron component and CauldronSystem using RealityKit, expose them to the editor via a RealityComposerProPlugin, and see the water level property update in real time as artists adjust values in the inspector.
- 10:32 - Controlling the water surface
Extend the Cauldron component with vortex shader properties and update the system to drive a ShaderGraphMaterial at runtime, enabling artists to control vortex depth and rotation speed directly from the Reality Composer Pro 3 inspector.
- 13:19 - Custom animation actions
Implement the EntityAction protocol to create a SetWaterLevelAction that animates the cauldron water level on the sequencer timeline, subscribe to animation update events to interpolate the level, and register the action with the editor plugin.
- 17:12 - Custom Script Graph nodes
Use the @Scriptable macro to expose a custom component to Reality Composer Pro 3 Script Graphs, register a scripting module in the plugin setup, and see the generated nodes appear in the Script Graph editor for no-code artist workflows.
- 21:16 - Next steps
Recap of the plugin capabilities covered — custom components, systems, animation actions, and Script Graph nodes — with recommendations to explore the Explore Advances in RealityKit and Supercharge Your Spatial Workflows sessions.