Animación de personajes en watchOS y visionOS
Por el equipo de Charmotion · Actualizado el

Ni Rive ni Lottie son compatibles oficialmente con watchOS: rive-ios declara iOS, visionOS, tvOS, macOS y Mac Catalyst, y lottie-spm declara iOS, macOS, tvOS y visionOS. En el Apple Watch, anima con PhaseAnimator o KeyframeAnimator de SwiftUI (watchOS 10+) o reproduce fotogramas prerrenderizados. En visionOS, ambos funcionan en una ventana normal de SwiftUI.
Puntos clave
- Package.swift de rive-ios: iOS 14, visionOS 1, tvOS 16, macOS 13.1, Mac Catalyst 14. Sin watchOS.
- El Package.swift de lottie-spm incluye iOS, macOS, tvOS y visionOS. Sin watchOS.
- En watchOS, usa los animadores de SwiftUI o una secuencia de fotogramas controlada por
TimelineView. - En visionOS, una mascota 2D va en una ventana u ornament de SwiftUI; RealityKit es para modelos 3D.
- Exporta los fotogramas desde el video con fondo transparente del mismo personaje para que Watch, teléfono y Vision Pro coincidan.
¿Rive es compatible con watchOS?
No oficialmente. Las plataformas del Package.swift de rive-ios son:
platforms: [.iOS("14.0"), .visionOS("1.0"), .tvOS("16.0"), .macOS("13.1"), .macCatalyst("14.0")]
Swift Package Manager no enlazará el paquete en un target de watchOS porque watchOS no está en esa lista. Algún resumen de la página de migración de Rive para Apple ha dado a entender en ocasiones que el nuevo runtime es compatible con watchOS, pero lo que Xcode aplica es el manifiesto publicado, así que planifica como si Rive no estuviera disponible en el Watch. Vuelve a revisar el manifiesto cuando actualices el paquete, ya que las listas de plataformas pueden cambiar entre versiones.
Lo mismo aplica al runtime heredado de Rive: ambos runtimes se distribuyen en un solo paquete con un único conjunto de plataformas. Si tu app de iPhone y tu app de Watch comparten un paquete Swift de componentes de interfaz, deja las vistas que usan Rive en un módulo del que solo dependan los targets de iOS (y visionOS); de lo contrario, la compilación del Watch no podrá resolver la dependencia.
¿Lottie es compatible con watchOS?
No. El manifiesto de lottie-spm, que Airbnb recomienda para Swift Package Manager, declara iOS, macOS, tvOS y visionOS. No hay ninguna entrada para watchOS.
| Opción | iOS | visionOS | watchOS |
|---|---|---|---|
| RiveRuntime (rive-ios) | 14.0+ | 1.0+ | No declarado |
| Lottie (lottie-spm) | Yes | Yes | No declarado |
| SwiftUI PhaseAnimator / KeyframeAnimator | 17.0+ | 1.0+ | 10.0+ |
| Secuencia de fotogramas con TimelineView de SwiftUI | Yes | Yes | Yes |
| AVKit VideoPlayer | Yes | Yes | Yes |
Para conocer las versiones mínimas exactas de Lottie, lee la línea platforms de la versión que fijes.
Existen forks antiguos y ports de la comunidad de Lottie para watchOS, pero no son el paquete de Airbnb y su mantenimiento es irregular. Para una app que piensas seguir actualizando, las opciones nativas de las filas inferiores son la elección de menor riesgo: vienen con el sistema, respetan los ajustes de accesibilidad y no requieren ninguna dependencia extra en el target del Watch.
¿Qué puedo usar en el Apple Watch en su lugar?
Tres opciones, de la más ligera a la más pesada:
- Animadores de SwiftUI sobre una imagen fija.
phaseAnimatorykeyframeAnimatorestán disponibles desde watchOS 10. Un rebote, una inclinación o un pulso sobre una sola pose no requieren más recursos que una imagen. Consulta PhaseAnimator vs KeyframeAnimator. - Una secuencia de fotogramas. Exporta un loop corto como PNG numerados, añádelos al catálogo de recursos de la app del Watch y recórrelos con
TimelineView. Así conservas el movimiento real del personaje (parpadeos, saludos) a costa del tamaño de la app. - Video. El
VideoPlayerde AVKit para SwiftUI está disponible en watchOS. Muestra los controles del reproductor y encaja mejor con un clip que el usuario elige ver que con una mascota ambiental.
Una vista con secuencia de fotogramas:
import SwiftUI
struct FrameSequence: View {
let frames: [String] // ["wave_00", "wave_01", ...] in the asset catalog
var fps: Double = 12
@Environment(\.accessibilityReduceMotion) private var reduceMotion
var body: some View {
if reduceMotion || frames.count < 2 {
Image(frames.first ?? "")
.resizable()
.scaledToFit()
} else {
TimelineView(.animation(minimumInterval: 1 / fps)) { context in
let tick = Int(context.date.timeIntervalSinceReferenceDate * fps)
Image(frames[tick % frames.count])
.resizable()
.scaledToFit()
}
}
}
}
// Usage
FrameSequence(frames: (0..<24).map { String(format: "wave_%02d", $0) })
.frame(width: 80, height: 80)
Mantén los loops cortos y ligeros: la pantalla del Watch es diminuta y cada fotograma aumenta el tamaño de la app. Reproduce la secuencia en un momento concreto (un entrenamiento completado, un recordatorio) en lugar de dejarla en loop todo el día.
¿Cómo exporto fotogramas para watchOS desde mi set de animaciones?
Parte de una fuente con fondo transparente para que el personaje quede limpio sobre el fondo negro del Watch. Con ffmpeg y un WebM VP9 con canal alfa:
# 12 fps, 160 px wide, keep transparency
ffmpeg -c:v libvpx-vp9 -i wave.webm -vf "fps=12,scale=160:-1" wave_%02d.png
Luego arrastra los PNG al catálogo de recursos del target del Watch. Consejos:
- Ajusta el tamaño a la pantalla. Exporta al tamaño en puntos más grande que muestres multiplicado por la escala de pantalla, no a la resolución de origen.
- Recorta el loop. Un loop de dos segundos a 12 cuadros por segundo son 24 imágenes; suele bastar para un reposo (idle) o un saludo.
- Elige una imagen fija para Reducir movimiento. El primer fotograma sirve también como pose estática.
Los sets de Charmotion en los planes de pago incluyen archivos WebM y MOV HEVC con alfa transparentes para cada animación, junto con el .riv que se usa en iPhone, así que los fotogramas del Watch salen exactamente del mismo movimiento que la app del teléfono.
¿Rive funciona en visionOS?
Sí. visionOS 1.0 está en la lista de plataformas de rive-ios, y el manifiesto de Lottie también incluye visionOS. En Vision Pro, una app de SwiftUI muestra sus vistas en ventanas, así que el mismo código que usas en iPhone funciona:
import SwiftUI
import RiveRuntime
struct MascotWindow: View {
@StateObject private var model = CharacterModel() // loads the .riv and keeps the view model instance
var body: some View {
RiveUIViewRepresentable(rive: model.rive)
.frame(width: 320, height: 320)
.padding(32)
.glassBackgroundEffect()
.task { await model.load() }
}
}
Aquí, CharacterModel es el controlador de Data Binding de Rive en SwiftUI: crea el Worker, el File, la instancia del view model y la máquina de estados vinculada. glassBackgroundEffect() es el material de vidrio de visionOS; omítelo en otras plataformas.
Prueba en el dispositivo además del simulador. El renderizado se basa en Metal en ambos runtimes, y el peso visual de un personaje plano flotando en una habitación es difícil de juzgar en la pantalla de una Mac.
En visionOS, ¿una mascota 2D debe ir en una ventana de SwiftUI o en RealityKit?
Mantén un personaje 2D en SwiftUI. RealityKit y Reality Composer Pro están hechos para contenido 3D: modelos, materiales y animación esquelética. Un personaje plano de Rive o Lottie colocado en RealityKit no gana nada y pierde la API sencilla basada en vistas.
| Ubicación | Úsala para |
|---|---|
| Dentro de la ventana principal | Onboarding, estados vacíos, avatar del asistente: igual que en iPhone |
| Ornament adjunto a una ventana | Un pequeño ayudante permanente junto a tu contenido |
| Ventana pequeña independiente | Un acompañante que el usuario puede mover |
| Entidad de RealityKit | Solo si el personaje es un modelo 3D real |
Reducir movimiento importa más en un visor, donde el movimiento ocupa más campo de visión. Lee @Environment(\.accessibilityReduceMotion) (disponible en visionOS 1) y pausa la animación o cámbiala por una pose fija; consulta Reducir movimiento en SwiftUI y UIKit.
Agrega una animación de personaje a una app de Apple Watch
- Elige el método. Usa un animador de SwiftUI sobre una pose fija para movimientos simples, o una secuencia de fotogramas para un movimiento de personaje real.
- Exporta los fotogramas. Ejecuta
ffmpeg -c:v libvpx-vp9 -i wave.webm -vf "fps=12,scale=160:-1" wave_%02d.pngsobre un WebM con fondo transparente. - Agrégalos al target del Watch. Arrastra los PNG al catálogo de recursos de la app del Watch.
- Reprodúcelos. Recorre las imágenes con
TimelineView(.animation(minimumInterval:))a la tasa de cuadros por segundo de la exportación. - Gestiona Reducir movimiento (Reduce Motion). Muestra el primer fotograma como imagen fija cuando
accessibilityReduceMotionsea verdadero.
Preguntas frecuentes
¿Puedo compartir el código de mi vista Rive de iOS con un target de watchOS?
No directamente, porque el paquete RiveRuntime no declara watchOS y no se enlaza en un target del Watch. Envuelve la mascota en tu propia vista con condicionales de plataforma: Rive en iOS y visionOS, una secuencia de fotogramas o un animador de SwiftUI en watchOS, todo alimentado por el mismo valor de mood.
¿Un GIF se reproduce en Apple Watch?
El Image de SwiftUI no anima GIF en ninguna plataforma de Apple. Decodifica los fotogramas del GIF en imágenes y recórrelas o, mejor aún, exporta fotogramas PNG desde una fuente con fondo transparente y reprodúcelos con TimelineView. Así controlas los cuadros por segundo, el tamaño y Reducir movimiento.
¿Lottie está disponible en visionOS?
Sí. El manifiesto de lottie-spm declara visionOS junto con iOS, macOS y tvOS, así que LottieView funciona en una ventana de SwiftUI en visionOS igual que en iPhone. El paquete de Rive también declara visionOS 1.0, de modo que ambos runtimes son opciones para un personaje 2D en una ventana u ornamento de visionOS.
Respuestas rápidas de esta guía
Fuentes
- rive-ios Package.swift, Rive (GitHub)
- lottie-spm Package.swift, Airbnb (GitHub)
- PhaseAnimator, Apple
- TimelineView, Apple
- VideoPlayer (AVKit for SwiftUI), Apple
- accessibilityReduceMotion, Apple
- Apple runtime (new and legacy), Rive