스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
iOS, macOS, visionOS용 RealityKit API 알아보기
RealityKit의 새로운 크로스 플랫폼 API로 iOS, macOS, visionOS를 위한 몰입감 넘치는 앱을 빌드하는 방법을 알아보세요. 새로운 호버 효과, 조명 및 그림자, 포털 크로스, 빌보드 기능을 살펴보고, 이러한 기능의 실제 예시를 선보입니다.
챕터
- 0:00 - Introduction
- 2:44 - Hover effects and input
- 9:05 - Force effects and joints
- 17:42 - Dynamic lights
- 20:17 - Portal enhancements
- 25:29 - Cross-platform capabilities
리소스
관련 비디오
WWDC24
WWDC23
WWDC21
-
다운로드
안녕하세요, Yidi입니다 RealityKit 팀 엔지니어죠 이 세션에서는 새로운 RealityKit API를 소개할 텐데요 공간 컴퓨팅 앱 개발을 위한 API입니다
고성능 3D 시뮬레이션과 렌더링이 가능한 프레임워크로 iOS, iPadOS, macOS visionOS에서 사용할 수 있습니다 3D 콘텐츠가 실제 환경과 매끄럽게 어우러질 수 있도록 다양한 기능을 제공해 몰입형 공간 컴퓨팅 앱과 게임을 제작할 수 있도록 지원합니다 Apple Vision Pro 출시 이후 많은 분들로부터 놀라운 피드백을 받고 있습니다 멋진 제안을 보내 주시고 기능을 요청해 주셔서 진심으로 감사드리며 보내 주신 피드백 중 많은 부분이 RealityKit에 새로운 기능으로 반영되었다는 소식을 전하게 되어 정말 기쁩니다 이 세션에서는 이러한 기능으로 Spaceship 게임을 만들겠습니다 이 세션에 링크된 샘플 프로젝트를 다운로드해 따라하실 수 있습니다 이 게임은 우주선 장난감을 가지고 노는 느낌을 재현했습니다 게임은 격납고에서 시작합니다 격납고는 플레이어가 우주선을 가까이에서 볼 수 있는 안전한 장소입니다 그런 다음 플레이어는 우주선 조종법을 배웁니다 사용자의 실제 환경에서 양손을 입력으로 사용합니다 비행 조종에 익숙해지면 플레이어는 우주로 날아가 소행성 지대를 탐색하고 귀중한 우주 화물을 배달할 수 있습니다 그리고 먼 행성으로 이동하는 포털을 통해 비행할 수도 있습니다 이 게임을 빌드하면서 여러 새로운 RealityKit API를 소개하겠습니다 먼저 호버 효과 사용법을 살펴보고 3D 모델과 상호작용하는 방법과 핸드 트래킹으로 핵심 입력 메커니즘 빌드 방법을 알아봅니다 다음으로 포스 효과와 조인트로 피직스 시뮬레이션을 추가합니다 다이나믹 라이팅을 추가해 씬에 조명을 비추고 그림자를 사용해 플레이어가 거리를 인식할 수 있도록 합니다 그런 다음 포털 API를 사용해 먼 우주 공간으로 통하는 포털을 열고 새로운 포털 기능을 사용해 우주선을 날려보겠습니다
마지막으로 RealityKit의 크로스 플랫폼 기능과 게임을 다른 Apple 플랫폼으로 쉽게 가져올 수 있는 방법을 안내합니다 정말 흥미진진한 소개 시간이 될 것입니다 바로 시작하겠습니다!
호버 효과와 입력입니다 visionOS에서는 앱의 콘텐츠를 윈도우, 볼륨, 공간에 표시합니다 게임은 격납고에 있는 우주선을 볼륨 스타일로 보여주며 시작합니다
플레이어는 간단한 드래그 제스처로 우주선을 회전시키면서 가까이에서 살펴볼 수 있습니다 시스템은 또한 이 볼륨의 베이스 플레이트를 제공해 플레이어가 바라보는 방향에 대한 시각적 피드백을 보여 줍니다 하지만 베이스 플레이트와 달리 우주선은 바라볼 때 시각적 하이라이트가 표시되지 않음을 알 수 있습니다 HoverEffectComponent를 추가해서 우주선을 바라볼 때 은은한 스포트라이트 효과가 표시되도록 해 봅시다 이렇게 하면 상호작용에 따라 반응한다는 느낌을 줄 수 있습니다 게임의 아트 스타일에 맞게 효과를 조절하고 싶다면 어떻게 할까요? 좋은 방법이 있습니다! 올해 RealityKit에 도입된 새로운 API를 사용하면 호버 효과를 맞춤화할 수 있습니다 방금 본 기본 스포트라이트 효과 외에도 새로운 스타일이 2개 더 있습니다 바로 하이라이트와 셰이더입니다 하이라이트 스타일은 전체 메시에 균일한 하이라이트를 적용합니다 스포트라이트 또는 하이라이트 스타일을 사용할 때 색조의 색상과 강도를 사용자 지정할 수도 있으며 새로운 셰이더 스타일은 셰이더 그래프 머티리얼과 통합해 더 많은 가능성을 제공합니다 색조 색상으로 하이라이트 효과를 더하겠습니다 우주선의 모양에 어울리도록 해 보죠 또한 거슬리지 않게 눈에 띄도록 강도를 조정하겠습니다 이를 위해 HighlightHoverEffectStyle을 만들고 아티스트가 정한 노란색으로 선택 강도를 0.8로 설정합니다 그런 다음 이 스타일로 HoverEffectComponent를 만들어 우주선 엔티티에 추가합니다 이렇게 하면 엔티티에 간단하게 하이라이트 호버 효과가 추가됩니다
새로운 맞춤화 기능의 스포트라이트와 하이라이트는 3D 콘텐츠에 호버 효과를 빠르고 쉽게 추가하는 방법을 제공하지만 새로운 셰이더 스타일은 훨씬 더 강력하고 유연해 Reality Composer Pro에서 셰이더 그래프 머티리얼을 사용해 고급 시각 효과를 구성할 수 있습니다 이 기능을 사용해 플레이어가 우주선을 바라볼 때 우주선 창에 불이 들어오는 맞춤 호버 효과를 추가했습니다 우주선 모델과 정말 잘 어울리고 멋지게 보이는 효과네요 이 효과를 위해 셰이더 그래프의 새 HoverState 노드를 사용했습니다 HoverState 노드에는 강도 값 등 여러 입력이 제공됩니다 플레이어가 우주선을 볼 때 강도 값은 0에서 1까지로 애니메이션됩니다 Reality Composer Pro의 셰이더 그래프 머티리얼이 기본 API입니다 HoverState 노드를 추가하고 강도 값을 Mix 노드에 제공해서 우주선을 볼 때 이미시브 컬러를 페이드인할 수 있도록 했습니다 마지막으로 Mix 노드의 출력을 PBRSurface의 이미시브 컬러에 연결하면 됩니다
코드에서 호버 스타일을 셰이더에 기본 입력으로 업데이트하기만 하면 됩니다 HoverState 노드를 사용해 다양한 효과를 낼 수 있습니다 예를 들어, 제 동료 Adrian은 공간 드로잉 앱을 제작하면서 셰이더 스타일 호버 효과로 3D 브러시를 따라 보랏빛이 퍼지는 애니메이션을 만들었습니다 이 샘플에 대한 자세한 내용은 올해 WWDC의 ‘RealityKit으로 공간 드로잉 앱 빌드하기‘ 세션에서 확인하실 수 있습니다 HoverEffectComponent는 3D 오브젝트를 볼 때 풍부한 시각적 피드백을 주는 강력한 방법을 제공하며 이 작업은 사용자의 개인정보를 침해하지 않고도 가능합니다 올해엔 SwiftUI에서도 맞춤형 호버 이펙트 API가 생깁니다 ‘visionOS에서 맞춤형 호버 효과 제작하기‘ 세션에서 자세히 알아보세요
다음으로 게임의 입력 메커니즘을 정의하겠습니다
플레이어가 우주선을 비행할 준비가 되면 볼륨을 벗어나 혼합 몰입형 공간으로 들어갑니다
여기서는 양손을 사용해 우주선을 제어합니다 왼손은 우주선의 비행 속도를 제어합니다 엄지와 검지 손가락 끝을 가까이할수록 우주선이 더 빨리 날아갑니다 오른손은 우주선의 방향을 제어합니다 오른손을 위로 기울이면 우주선도 위로 기울어집니다 그리고 왼쪽으로 돌리면 우주선도 왼쪽으로 돌아갑니다
3D 공간에서 플레이어의 손을 트래킹해 이 입력을 구현합니다 visionOS 1에서는 ARKit으로 앱에 커스텀 핸드 트래킹을 추가할 수 있었습니다 올해 RealityKit에는 새로운 Spatial Tracking API가 도입되어 이 작업이 더욱 쉬워졌습니다
SpatialTrackingSession은 핸드 트래킹에 대한 플레이어 동의를 얻고 설정이 완료되면 RealityKit 앵커 엔티티로 플레이어의 손을 트래킹할 수 있습니다 왼손에 앵커 엔티티 두 개를 생성합니다 하나는 검지 손가락 끝에 하나는 엄지손가락 끝에 둡니다
맞춤형 시스템의 업데이트 함수 내에서 Entity.position API를 사용해 앵커 엔티티의 위치를 쿼리합니다 두 앵커 엔티티 사이의 거리를 계산하고 맞춤형 함수를 통해 거리를 스로틀 값에 매핑해 거리가 짧을수록 더 큰 스로틀을 생성합니다 마지막으로 이 스로틀 값으로 우주선을 가속할 수 있습니다 우주선의 전진 방향을 따라 포스 벡터를 계산하고 우주선 엔티티에 포스를 더합니다 오른손 컨트롤의 경우 구현은 방금 본 코드와 유사합니다 자세한 구현은 이 세션에 링크된 샘플 코드를 확인하세요
이제 왼손과 오른손을 위한 맞춤형 제스처가 모두 준비되었고 플레이어는 손을 컨트롤러로 우주선을 조종할 수 있습니다!
좋아요! SpatialTrackingSession API에 대한 자세한 내용은 Adrian의 ‘RealityKit으로 공간 드로잉 앱 빌드하기’ 세션에도 있습니다 이제 플레이어가 조종할 수 있는 우주선이 생겼으니 조종 경험을 조금 더 재미있게 만들어 봅시다 이를 위해 새로운 포스 이펙트와 피직스 조인트 API를 사용합니다 플레이어가 조종 기술을 연습할 수 있도록 우주에 행성과 소행성을 추가했지만 정지된 물체 사이를 지나다니기는 조금 심심하게 느껴집니다 소행성들이 행성 주위를 공전하게 만드는 건 어떨까요? 천체에 적용되는 실제 물리학의 작동 방식을 모방해서요 포스 이펙트 API로 이러한 시뮬레이션을 도입할 수 있습니다 포스 이펙트는 볼륨을 정의하고 해당 볼륨의 피직스 바디에 지속적으로 포스를 적용합니다 행성의 경우 필요한 포스 이펙트는 소행성을 가운데로 끌어당기는 효과입니다
RealityKit에서는 네 가지의 포스 이펙트가 내장되어 있습니다 필요한 것이 있는지 보겠습니다 일정한 방사형 이펙트는 모든 피직스 바디에 중심을 향한 일정한 포스를 적용합니다 소용돌이 이펙트는 축을 중심으로 피직스 바디를 순환시키는 포스를 적용합니다 드래그 이펙트는 속도에 비례하는 포스를 적용해 볼륨이 있는 피직스 바디의 속도를 늦춥니다 난기류 이펙트는 피직스 바디에 임의의 포스를 적용합니다 원하는 것과 제일 비슷한 것은 일정한 방사형 이펙트지만 행성이 모든 소행성에 완전히 같은 크기의 포스를 적용하는 것은 원하지 않습니다 포스의 크기가 행성으로부터의 거리에 따라 달라졌으면 합니다 RealityKit에서 맞춤형 포스 이펙트를 정의하면 가능합니다
Gravity라는 클래스를 정의했는데 맞춤형 포스 이펙트의 로직을 포함하는 클래스입니다 모든 맞춤형 포스 이펙트는 ForceEffectProtocol을 준수하는데 세 가지 요구 사항이 있습니다 parameterTypes, forceMode 업데이트 함수죠
ParameterTypes은 물리 엔진에 이 포스 이펙트 계산에 필요한 매개변수를 알려 줍니다 중력 이펙트의 경우 위치와 거리가 필요합니다 forceMode는 이펙트의 포스 벡터가 물리 엔진에서 해석되는 방식을 제어합니다 중력의 경우 포스로 설정하면 됩니다
마지막으로 업데이트 함수는 실제 포스 벡터를 계산합니다 매개변수 구조체는 포스 계산에 필요한 정보를 제공합니다
먼저 거리와 위치의 감싸기를 해제하겠습니다 그런 다음 이 포스 이펙트의 영향을 받는 모든 피직스 바디를 루프시킵니다 우리의 경우에는 행성 주변의 소행성입니다 맞춤형 함수를 정의하겠습니다 포스 벡터를 계산할 때 주어진 거리와 위치 값을 사용하는 함수입니다 매개변수 구조체에 포스를 설정해 결과를 출력하겠습니다 물리 엔진은 이 포스를 받아 피직스 바디에 적용합니다 좋아요, 이제 맞춤형 포스 이펙트가 생겼습니다 이제 씬에서 활성화하겠습니다
먼저 Gravity 인스턴스가 있는 ForceEffect 오브젝트를 생성합니다 여기선 spatialFalloff를 설정해 피직스 바디가 영향받는 거리를 반경 8미터 이내로 설정합니다 그리고 소행성에만 영향을 미치도록 마스크를 설정합니다
마지막으로 행성 엔티티에 중력 이펙트를 추가하는 ForceEffectComponent를 사용합니다
중력 이벤트를 한번 볼까요!
음, 중력 효과가 작동하긴 하지만 소행성이 중심을 향해 똑바로 당겨지고 있습니다 궤도 운동을 하는 게 아니네요 이 문제를 해결하려면 소행성에 궤도 궤적을 따르는 초기 속도를 부여해야 합니다 행성의 중력이 소행성을 행성 쪽으로 끌어당깁니다 속도가 중력의 끌어당김을 상쇄해 궤도 운동을 달성합니다
소행성을 생성할 때 궤도 속도를 계산하겠습니다 소행성의 반경과 행성으로부터의 각도를 사용하면 초기 속도를 계산할 수 있습니다 그런 다음 PhysicsMotionComponent를 통해 초기 속도를 소행성에 설정합니다 이제 어떻게 되는지 보겠습니다
좋아요! 소행성이 마침내 행성 궤도를 돌고 있습니다 포스 이펙트 API의 능력으로 맞춤형 포스 이펙트 하나로 궤도 움직임 구현이 가능했습니다 이제 충분히 도전적인 소행성 장애물 코스를 만들었으니 우주선 뒤에 트레일러를 달겠습니다 플레이어가 코스를 비행하면서 우주 화물을 운반할 수 있겠죠
우주선에 트레일러를 추가하는 가장 쉬운 방법은 트레일러 엔티티를 우주선의 자식 개체로 만드는 것입니다 하지만 이 방식을 사용하면 우주선과 트레일러의 연결이 매우 뻣뻣하게 느껴집니다 피직스 조인트를 사용하면 더 재미있게 만들 수 있습니다 조인트는 컨스트레인트를 통해 두 피직스 바디를 서로 연결합니다
회전은 허용하고 이동은 제한하는 조인트를 만들겠습니다 실제 트레일러가 움직이는 방식을 시뮬레이션할 수 있습니다 이 조인트를 사용하면 견인이 더 사실적이고 재미있게 느껴집니다
조인트를 만들려면 엔티티에 핀을 추가해야 합니다 핀은 엔티티에 상대적 위치와 방향을 정의합니다 조인트 하나가 정확히 두 개의 핀을 연결합니다 우주선의 핀은 뒤쪽에 있고 트레일러의 핀은 앞에 있습니다
두 핀 사이의 이동을 0으로 제한하는 조인트가 필요하지만 세 축 모두에 회전을 위한 공간도 남겨두고 싶습니다
RealityKit은 여러 가지 내장된 조인트를 제공합니다 조인트의 두 번째 엔티티는 컨스트레인트가 없이 세 축 중 아무 축이나 따라 자유롭게 이동, 회전할 수 있습니다 내장된 조인트는 두 번째 엔티티의 이동 또는 회전 방법에 컨스트레인트를 적용합니다 한번 살펴보겠습니다
고정된 조인트는 이동과 회전을 모두 허용하지 않습니다 구체형 조인트는 이동을 허용하지 않지만 Y축과 Z축 중심의 제한된 회전과 X축 중심의 자유 회전을 허용합니다
회전형 조인트는 구체형 조인트와 비슷하지만 더 제한적입니다 X축을 중심으로만 회전할 수 있습니다 프리즘 조인트는 슬라이드 조인트라고도 합니다 X축을 따라가는 이동만 가능합니다 마지막으로 거리 조인트는 세 축 모두에서 자유 이동하지만 두 바디 사이의 거리가 주어진 범위 내에 있어야 합니다
구체형 조인트가 우주선과 트레일러에 필요한 것과 가장 근접해 보입니다 이 조인트는 X축을 따라 회전을 전혀 제한하지 않는게 다릅니다 하지만 괜찮아요! 맞춤형 조인트 유형을 사용하면 필요한 것을 만들 수 있습니다
방법을 알아보겠습니다 Reality Composer Pro로 우주선에 Hook 엔티티를 추가했습니다 핀이 있어야 할 위치를 정의하므로 전환을 하드 코딩할 필요가 없습니다 코드에서 hookEntity를 찾아 우주선을 기준으로 위치를 가져옵니다
그런 다음 우주선 엔티티에 hookPin을 생성합니다 여기에 pins.set API를 사용하고 hookOffset을 핀 위치로 사용합니다 트레일러의 핀에도 똑같이 합니다
다음으로 두 핀을 연결하는 맞춤형 조인트를 만들겠습니다
맞춤형 조인트를 사용하면 세 축을 중심으로 각도 모션을 개별적으로 제한할 수 있습니다 각도 모션을 작은 범위로 제한하도록 설정하고 X 주위의 각도 모션을 조금 더 제한해서 트레일러가 위아래로 너무 많이 회전하지 않도록 하겠습니다
각도 모션과 같이 세 축을 따라 선형 모션을 개별 제어합니다 이동은 필요하지 않으므로 세 축을 따라 선형 모션을 모두 고정하도록 설정하겠습니다
마지막으로 조인트를 피직스 시뮬레이션에 추가합니다
맞춤형 피직스 조인트를 사용하면 이제 트레일러가 물리 법칙에 맞게 우주선을 따라 움직입니다 멋지게 보이네요! 다음으로 플레이어의 조종 경험을 개선할 수 있도록 우주선에 헤드라이트를 추가하겠습니다 헤드라이트는 주변 오브젝트에 빛을 비출 뿐만 아니라 그림자를 드리우기도 하므로 장애물에서 얼마나 멀리 떨어져 있는지 알 수 있습니다 이를 위해 다이나믹 라이팅과 그림자를 사용할 수 있습니다 올 해 visionOS에 추가된 기능이죠 RealityKit 조명은 세 개 있습니다 스포트라이트, 원뿔 모양의 볼륨으로 오브젝트를 비춥니다 각도, 거리, 감쇠를 맞춤화할 수 있습니다 방향성 조명은 씬의 모든 오브젝트를 비춥니다 포인트 라이트는 오브젝트에 적용
감쇠 반경과 감쇠 지수를 맞춤화할 수 있습니다
세 가지 모두 색상 및 강도 맞춤화를 지원하지만 스포트라이트와 방향성 조명만 그림자를 드리울 수 있습니다 조명과 그림자를 도입할 때는 앱의 성능을 자주 확인하는 것이 좋습니다 렌더링에 컴퓨팅 용량이 많이 소요될 수 있거든요
우주선 전면에 스포트라이트를 부착해 봅시다 강력한 헤드라이트가 있으면 플레이어가 우주선에 어떤 물체가 가까이 있는지 알 수 있습니다 조명과 그림자는 두 가지 방법으로 추가할 수 있습니다 코드에서 Swift API를 사용하거나 Reality Composer Pro로 조명 조정 동작 UI를 사용하는 방법이 있습니다 Swift 코드에서 조명을 추가하는 방법을 살펴보겠습니다 우주선의 후크를 위해 Reality Composer Pro에서 엔티티를 설정한 방법과 비슷합니다 조명 변형을 정의하기 위해 새 헤드라이트 엔티티를 더했습니다 코드의 우주선 엔티티 계층 구조에서 헤드라이트 엔티티를 찾아 스포트라이트를 연결합니다
스포트라이트는 노란색 색조로 구성됩니다 강도를 1만 루멘으로 설정하고 감쇠 반경을 6으로 설정합니다 이 값이 우리 씬에 어울립니다
스포트라이트가 그림자를 드리울 수 있도록 엔티티에 그림자 컴포넌트도 추가하겠습니다
결과를 살펴보겠습니다 이제 헤드라이트와 그림자를 통해 우주선이 소행성에 위험할 정도로 가깝다는 것을 쉽게 볼 수 있습니다
다이내믹 스포트라이트와 방향성 조명이 비추는 모든 오브젝트는 기본적으로 그림자를 드리웁니다 일부 오브젝트에 그림자가 드리워지지 않게 하려면 해당 오브젝트에 DynamicLightShadowComponent를 추가하고 castsShadow를 ‘false’로 합니다 이 동영상의 소행성은 castsShadow가 비활성화된 것입니다 게임 플레이가 벌써 재미있어지네요 더 추가하고 싶은 게 있습니다 바로 우주선을 먼 우주 공간으로 워프시키는 포털이죠 포털 API를 사용해 이 기능을 구현하겠습니다 새롭고 흥미로운 기능이 많이 추가된 API죠 여러분의 피드백 덕분입니다! 포털은 메시 표면으로 다른 세계로의 창을 열어줍니다 이 월드의 모든 엔티티는 포털 지오메트리가 마스킹합니다 이 행성을 둘러싼 소행성이 원형의 포털 표면 내부에만 렌더링되고 있죠
포털을 만드는 자세한 방법은 WWDC23의 ‘RealityKit으로 공간 컴퓨팅 앱 강화하기’ 세션을 참고하세요 visionOS 1에서 오브젝트는 완전히 포털 내부 또는 외부에 있습니다 이번 RealityKit 릴리스에는 포털 크로싱 기능이 추가되어 오브젝트가 포털 표면을 매끄럽게 가로질러서 포털 안으로 들어가거나 밖으로 나올 수 있습니다 이 동영상에는 우주선 두 대가 있습니다 왼쪽에 있는 우주선은 포털 크로싱이 비활성화되어 있어 포털 밖으로 나가면 마스킹됩니다 오른쪽 우주선은 포털 크로싱이 활성화되어 있어 포털 밖으로 매끄럽게 날아갈 수 있습니다 포털 크로싱을 활성화하려면 두 곳에서 설정이 필요합니다 먼저 포털 컴포넌트를 생성할 때 크로싱 모드를 설정합니다 크로싱을 활성화하기 위해 모드를 평면으로 설정하거나 크로싱을 비활성화하려면 비활성화로 설정합니다 평면을 사용하기기로 하면 포털 지오메트리와 일치하는지 확인합니다 게임에서 포털과 일치하는 평면은 포지티브 Z-평면입니다 포털 크로싱 외에도 포털에 대한 클리핑 평면을 정의할 수 있습니다 이 평면도 포지티브 Z-평면으로 설정합니다
또 다른 설정은 우주선 엔티티에 관한 것입니다 포털 월드의 엔티티는 기본적으로 포털 크로싱이 비활성화입니다 포털 크로싱을 활성화하기 위해 포털 크로싱 컴포넌트를 추가하겠습니다 끝났습니다 이제 우주선이 포털로 날아갈 수 있습니다
음... 우주선이 포털을 통과하는 모습을 자세히 보니 이상한 부분이 하나 있습니다 포털을 건너가는 평면에서 조명이 매우 거칠게 전환됩니다 우주선의 날개를 보면 알 수 있습니다
포털 내부와 외부의 조명 환경이 다르기 때문에 빛이 거칠게 차단되는 것입니다 포털 크로싱이 활성화된 모델은 포털 내부에 있을 때는 맞춤형 ImageBasedLightComponent에서 조명을 받습니다 별 필드 이미지를 예로 들어 보겠습니다
모델이 포털 외부에 있을 때 추가 조명을 받는 위치는 실제 환경의 조명을 근사화하는 환경 프로브입니다
오브젝트가 포털을 막 통과하는 경우 이 프로브는 포털 내부와 외부에 동시에 존재합니다 내부 부분의 조명은 ImageBasedLightComponent에서 제공되고 바깥쪽 부분은 두 출처에서 조명을 받게 됩니다 바로 별 필드와 환경 프로브이죠
조명 전환을 더 매끄럽게 하려면 EnvironmentLightingConfigurationComponent를 사용할 수 있습니다 이 컴포넌트는 엔티티가 환경 프로브에서 받는 조명의 양 특히 포털 외부의 부분에서 받는 조명의 양을 제어합니다 이 컴포넌트는 environmentLightingWeight 값을 노출합니다 값이 1이면 오브젝트가 환경 프로브에서 전체 조명을 받고 값이 0이면 오브젝트가 조명을 받지 못한다는 의미입니다 우주선이 포털 외부에 있을 때 environmentLightingWeight를 1로 설정하면 외부 조명을 받게 할 수 있습니다 우주선이 포털에 접근할수록 이 값을 1에서 0으로 서서히 줄여서 우주선이 포털을 통과하기 시작하면 포털 월드 내부에서만 조명을 받게 할 수 있습니다 이렇게 하려면 코드에서 EnvironmentLightingConfigurationComponent를 생성합니다 우주선의 포털 표면으로부터의 거리를 추적하고 맞춤형 함수를 사용해 거리 값을 환경 조명 가중치 값에 매핑하도록 하겠습니다 거리가 작아지면 즉 우주선이 포털에 가까워지면 가중치를 줄이겠습니다 우주선이 움직일 때마다 가중치를 다시 계산하고 컴포넌트를 우주선 엔티티로 업데이트해야 합니다 코드를 작동시킵니다
좋아요! 이제 우주선이 포털 표면에 접근하면 조명이 부드럽게 전환됩니다 EnvironmentLightingConfigurationComponent는 앱의 조명을 구성하는 강력한 방법입니다 앱이 포털을 사용하지 않아도 유용합니다
새로운 포털 기능의 작동 방식을 자세히 알아보려면 developer.apple.com에서 PortalComponent에 대한 문서를 참고하시기 바랍니다
좋습니다! 이제 우리는 visionOS에서 완벽하게 실행되는 Spaceship 게임을 만들었습니다 손 기반 입력, 포스 이펙트 조인트, 조명과 그림자 포털이 모두 함께 작동하고 있습니다 여러 플랫폼에서 이 게임을 체험할 수 있다면 정말 멋지겠죠? 이번 RealityKit 릴리스를 통해 이제 visionOS 공간 컴퓨팅 경험을 iOS, iPadOS macOS로 매끄럽게 가져올 수 있습니다 이제 최소한의 코드 변경만으로 다른 Apple 플랫폼을 위한 경험을 빌드할 수 있으며 이러한 작업에 도움이 될 수 있는 많은 RealityKit 기능을 추가해 원활한 경험을 지원해 드립니다 여기에는 RealityView ShaderGraph, 파티클 이미터, 포털 호버, 텍스트 등이 있습니다 또한 이것은 여러분에게 크로스 플랫폼 툴과 파이프라인을 개발해 앱 개발을 가속할 수 있는 좋은 기회입니다 이제 크로스 플랫폼 기능 중 일부를 사용해 게임을 iPadOS로 가져옵니다 말씀드린 것과 같은 광범위한 크로스 플랫폼 지원으로 Spaceship 게임의 대부분의 코드는 전혀 변경할 필요가 없습니다 호버 효과, 포스 이펙트, 조인트 조명과 그림자, 포털 교차 등을 위해 작성한 모든 코드는 모두 동일하게 유지할 수 있습니다 그렇다면 무엇을 바꿔야 할까요?
visionOS에서는 플레이어 주위의 별도 공간에 UI를 둘 수 있습니다 iPadOS에서는 UI를 화면에 바로 배치합니다 두 번째로 visionOS에서는 ImmersiveSpace로 공간 경험의 시작점을 삼습니다 iPadOS에서는 RealityView를 통해 공간 경험을 화면에 직접 표시할 수 있습니다
RealityView에는 iOS, iPadOS macOS를 위한 개선 사항이 있으며 카메라 모드를 위한 컨트롤 포스트 프로세싱 등이 있습니다 카메라 피드를 배경으로 삼아 월드 트래킹을 사용하고 싶습니다 RealityView의 카메라 모드를 월드 트래킹으로 설정하겠습니다
마지막으로 visionOS에서는 입력이 핸드 트래킹 기반입니다 iPadOS에서는 멀티터치 제스처가 이 플랫폼의 이점과 잘 어울리는 입력 방법으로 알맞을 것입니다 따라서 새로운 멀티터치 컨트롤 뷰로 멀티터치 기반 입력으로 전환하겠습니다 왼쪽에는 스로틀 제어를 위한 슬라이더가 있고 오른쪽에는 피치 앤 롤을 위한 가상 조이스틱이 있습니다 이는 양손의 역할을 분리해 visionOS 입력 방식과 아주 잘 매핑됩니다 이렇게 하면 Spaceship 게임이 iPad에서도 작동합니다 모든 RealityKit 기능이 여기서도 작동합니다 visionOS에서의 방법과 비슷하죠 격납고 보기로 이동하고 동일한 드래그 제스처로 우주선과 상호작용할 수 있으며 물리적 환경에서 우주선을 조종하는 것도 월드 트래킹과 카메라 피드를 배경으로 해 비슷합니다 플랫폼 간 기능 패리티를 지원하는 RealityKit을 사용하면 visionOS, iOS, iPadOS, macOS에서 앱을 쉽게 실행할 수 있습니다
좋습니다! 풍부한 기능의 게임을 만들었으며 visionOS뿐만 아니라 iPadOS에서도 잘 작동합니다 게임의 시뮬레이션과 렌더링 측면 구축에 집중했지만 아직 Spaceship 게임의 사운드는 없는 상태입니다 제 동료인 James가 이 게임을 위한 공간 음향 제작법을 설명합니다 세션 제목은 ‘RealityKit 오디오로 공간 컴퓨팅 앱 향상하기’로 RealityKit의 오디오 API를 사용하는 방법뿐만 아니라 공간 음향 제작을 위한 모범 사례도 다룹니다 이 외에도 정말 다양한 RealityKit 기능들이 있습니다 이 세션에서는 모두 다룰 시간이 없었죠 몇 가지를 간단히 소개하겠습니다 LowLevelMesh와 LowLevelTexture는 메시와 텍스처 리소스 구성, 업데이트용 하위레벨 액세스를 제공합니다 애니메이션 시스템에도 새로운 기능이 많이 추가되었습니다 Reality Composer Pro의 애니메이션 타임라인 생성 기능 등이 있죠 BillboardComponent는 엔티티가 항상 사용자를 향하게 하는 개인정보 보호 방식을 도입했습니다 PixelCast는 렌더링 기반 접근으로 픽셀 단위로 완벽하게 엔티티를 선택할 수 있습니다 세분화 표면을 사용하면 조밀한 메시를 만들지 않고도 매끄러운 표면을 렌더링할 수 있습니다 developer.apple.com에서 자세히 확인하실 수 있습니다 와우! 기능이 정말 많네요! 배운 내용을 요약하겠습니다 먼저 우주선에 맞춤형 호버 이펙트를 추가하고 새로운 공간 추적 API를 사용해 우주선을 조종하는 커스텀 손동작 기반 제어 메커니즘을 만들었습니다 포스 이펙트와 조인트를 사용해 씬에 피직스를 추가하고 재미도 추가했습니다 그리고 다이내믹 라이트와 그림자로 생생한 경험을 만들었습니다 우주선을 먼 우주로 보내기 위해 포털 크로싱도 사용했습니다 마지막으로 RealityKit의 크로스 플랫폼 API 지원으로 Spaceship을 iPad에서도 실행할 수 있도록 했습니다 ‘RealityKit으로 공간 드로잉 앱 빌드하기’ 세션과 ‘RealityKit 오디오로 공간 컴퓨팅 앱 향상하기’ 세션도 확인해 올해 RealityKit에 추가된 다른 많은 기능도 알아보시기 바랍니다 이 기능들을 활용해 여러분이 만들어낼 멋진 경험이 기대가 됩니다 시청해 주셔서 감사합니다!
-
-
4:24 - Add a highlight HoverEffectComponent
// Add a highlight HoverEffectComponent let highlightStyle = HoverEffectComponent.HighlightHoverEffectStyle(color: .lightYellow, strength: 0.8) let hoverEffect = HoverEffectComponent(.highlight(highlightStyle)) spaceship.components.set(hoverEffect)
-
5:55 - Add a shader effect
// Add a shader effect let hoverEffect = HoverEffectComponent(.shader(.default)) spaceship.components.set(hoverEffect)
-
8:04 - Control acceleration with left hand
// Control acceleration with left hand class HandTrackingSystem: System { func update(context: SceneUpdateContext) { let indexTipPosition = indexTipEntity.position(relativeTo: nil) let thumbTipPosition = thumbTipEntity.position(relativeTo: nil) let distance = distance(indexTipPosition, thumbTipPosition) let throttle = computeThrottle(with: distance) let force = spaceship.transform.forward * throttle spaceship.addForce(force, relativeTo: nil) } }
-
10:50 - Adding a gravity force effect
// Adding a gravity force effect struct Gravity: ForceEffectProtocol { var parameterTypes: PhysicsBodyParameterTypes { [.position, .distance] } var forceMode: ForceMode = .force func update(parameters: inout ForceEffectParameters) { guard let distances = parameters.distances, let positions = parameters.positions else { return } for i in 0..<parameters.physicsBodyCount { let force = computeForce(distances[i], positions[i]) parameters.setForce(force, index: i) } } }
-
12:14 - Activating the gravity force effect
// Activating the gravity force effect let gravity = ForceEffect(effect: Gravity(), spatialFalloff: SpatialForceFalloff(bounds: .sphere(radius: 8.0)), mask: .asteroids) planet.components.set(ForceEffectComponent(effects: [gravity]))
-
13:11 - Using PhysicsMotionComponent
// Calculate initial velocity of the asteroid using radius and angle let velocity = calculateVelocity(radius, angle) let physicsMotion = PhysicsMotionComponent(linearVelocity: velocity) asteroid.components.set(physicsMotion)
-
16:19 - // Add a custom joint
// Add a custom joint guard let hookEntity = spaceship.findEntity(named: "Hook") else { return } let hookOffset: SIMD3<Float> = hookEntity.position(relativeTo: spaceship) let hookPin = spaceship.pins.set(named: "Hook", position: hookOffset) let trailerPin = trailer.pins.set(named: "Trailer", position: .zero) var joint = PhysicsCustomJoint(pin0: hookPin, pin1: trailerPin) joint.angularMotionAroundX = .range(-.pi * 0.05 ... .pi * 0.05) joint.angularMotionAroundY = .range(-.pi * 0.2 ... .pi * 0.2) joint.angularMotionAroundZ = .range(-.pi * 0.2 ... .pi * 0.2) joint.linearMotionAlongX = .fixed joint.linearMotionAlongY = .fixed joint.linearMotionAlongZ = .fixed try joint.addToSimulation()
-
19:12 - // Add a spotlight with shadow
// Add a spotlight with shadow guard let lightEntity = spaceship.findEntity(named: "HeadLight") else { return } lightEntity.components.set(SpotLightComponent(color: .yellow, intensity: 10000.0, attenuationRadius: 6.0)) lightEntity.components.set(SpotLightComponent.Shadow())
-
20:01 - Disable shadow
// Disable shadow let component = DynamicLightShadowComponent( castsShadow: false) entity.components.set(component)
-
21:36 - Enable portal crossing
// Enable portal crossing portal.components.set(PortalComponent(target: portalWorld, clippingMode: .plane(.positiveZ), crossingMode: .plane(.positiveZ))) spaceship.components.set(PortalCrossingComponent())
-
24:33 - Configure environmental lighting on the spaceship
// Configure environmental lighting on the spaceship var lightingConfig = EnvironmentLightingConfigurationComponent() let distance: Float = computeShipDistanceFromPortal() lightingConfig.environmentLightingWeight = mapDistanceToWeight(distance) spaceship.components.set(lightingConfig)
-
27:21 - World tracking camera
// World tracking camera RealityView { content in #if os(iOS) content.camera = .worldTracking #endif }
-
27:59 - Multi-touch control views
// Multi-touch control views #if os(iOS) struct MultiTouchControlView : View { var body: some View { HStack { ThrottleControlView() Spacer() PitchRollControlView() } } #endif
-
-
찾고 계신 콘텐츠가 있나요? 위에 주제를 입력하고 원하는 내용을 바로 검색해 보세요.
쿼리를 제출하는 중에 오류가 발생했습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.