Communitygithub.com

dembsky/PropMotion

Habilidad para Claude Code: haz que un objeto 3D actúe en tu app SwiftUI. Escenarios SceneKit, coreografía precocinada, física artesanal, sombras reales.

¿Qué es PropMotion?

PropMotion es una habilidad para agentes de IA como Claude Code, diseñada para integrar un único objeto 3D decorativo y animado en una aplicación SwiftUI utilizando SceneKit. Su enfoque principal es la creación de un 'actor de producto' pulido sobre un escenario transparente de SceneKit, con entradas, salidas, lanzamientos, sombras y hápticos. La habilidad es ideal para proyectos que necesitan un elemento 3D vistoso sin la complejidad de un mundo interactivo completo, para lo cual recomienda RealityKit. Proporciona recetas detalladas para configurar la vista, la cámara, la iluminación y la coreografía mediante animaciones horneadas, evitando las trampas comunes que pueden costar días de depuración. Incluye referencias extensas sobre animación, física manual, gestos y secuenciación de múltiples escenarios, todo documentado con ejemplos de código Swift y patrones de producción.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add dembsky/PropMotion

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace PropMotion?

Haz que un objeto 3D actúe en tu aplicación SwiftUI. Patrones de producción para una tarea específica y común: un actor de producto pulido sobre un escenario transparente de SceneKit: entradas, salidas, lanzamientos, sombras, hápticos y las trampas silenciosas que cuestan días.

Cuándo usar SceneKit

Sé honesto sobre la posición del framework:

  • SceneKit está en modo de mantenimiento. Para aplicaciones nuevas con necesidades 3D pesadas (pipelines de assets, USD/USDZ, RA, mundos grandes) prefiere RealityKit.
  • SceneKit sigue siendo el camino más rápido para un actor 3D decorativo dentro de una app SwiftUI: una SCNView transparente se compone sobre cualquier diseño SwiftUI, los modificadores de shader de geometría son una sola cadena MSL, la interoperabilidad con CoreAnimation es madura, y todo esto funciona en vistas UIKit simples sin configuración de sesión.
  • Si el elemento 3D es un objeto héroe con movimiento coreografiado, las recetas de esta habilidad se aplican directamente. Si es un mundo interactivo completo, detente y considera RealityKit primero.

La receta del escenario central

Un escenario es: SCNView transparente, un coordinador @MainActor que posee el grafo de escena, una cámara a la altura de los ojos de una persona de pie, un montaje de tres luces más una luz de sombra dedicada, una gota de contacto y un receptor de sombras. El actor actúa mediante animaciones de fotogramas clave horneadas.

struct ProductStage: UIViewRepresentable {
    let item: Item

    // La clave debe cambiar SOLO cuando la escena deba cambiar visiblemente.
    private var stateKey: String { "\(item.id)" }

    func makeCoordinator() -> Coordinator { Coordinator() }

    func makeUIView(context: Context) -> SCNView {
        let view = SCNView()
        view.backgroundColor = .clear   // el escenario se compone sobre SwiftUI
        view.isOpaque = false
        view.antialiasingMode = .multisampling4X
        view.scene = context.coordinator.buildScene()
        view.pointOfView = context.coordinator.cameraNode
        context.coordinator.install(item)
        context.coordinator.markState(stateKey)
        // Calentamiento del primer fotograma, encendido de dos llaves: compilar shaders fuera
        // de la ruta crítica, aparcar al actor fuera del escenario y controlar la primera
        // entrada con AMBAS un retardo mínimo y la finalización de prepare.
        context.coordinator.parkOffstage()
        if let scene = view.scene {
            view.prepare([scene]) { _ in
                DispatchQueue.main.async { context.coordinator.markPipelinesWarm() }
            }
        }
        context.coordinator.scheduleFirstEntrance()
        return view
    }

    func updateUIView(_ view: SCNView, context: Context) {
        // Diferenciación de clave de estado: las re-renderizaciones de SwiftUI nunca deben repetir entradas.
        guard context.coordinator.stateKey != stateKey else { return }
        context.coordinator.markState(stateKey)
        context.coordinator.transition(to: item)
    }
}

Las piezas, en orden de construcción:

  1. Banderas de vista transparente (backgroundColor = .clear, isOpaque = false), MSAA 4x. La pantalla anfitriona proporciona el fondo; la escena no tiene caja.
  2. El coordinador posee la jerarquía de nodos, descompuesta un nodo por preocupación de movimiento (viaje, elevación, guiñada, giro), para que las animaciones independientes nunca peleen por una sola transformación.
  3. Cámara: projectionDirection = .horizontal para que el tamaño del actor siga el ancho del escenario; posición elevada con una ligera inclinación hacia abajo se lee como un observador de pie. Mantenla estática; una cámara en movimiento se lee como sintética.
  4. Luces: clave cálida, relleno bajo frío, borde duro, ambiente solo como valor de suelo, más una luz direccional separada que proyecta sombras apuntada desde detrás-encima del actor para que nunca perturbe la escultura visible.
  5. Contacto con el suelo: un plano de degradado oscuro suave (la gota de contacto) debajo del actor más un plano receptor .shadowOnly invisible para la sombra real.
  6. Los materiales reflectivos muestrean un mapa de entorno programático pequeño, no una foto. Mantén la zona detrás de la cámara oscura.
  7. Toda coreografía es CAKeyframeAnimation horneada, protegida por tokens de generación para que cualquier nuevo compás anule el trabajo pendiente.

Detalle completo con código: references/stage-recipe.md

Las trampas que más tiempo cuestan

TrampaSolución
Las sombras diferidas nunca se renderizan cuando MSAA está activado, sin errores en consolaUsa shadowMode = .forward más un receptor .shadowOnly. Depura cualquier sombra faltante primero dando a la escena un suelo visible de Lambert gris.
El primer fotograma de una SCNView nueva compila pipelines de Metal en medio de tu animación de entradaprepare([scene]) en segundo plano, aparca al actor fuera del escenario, retrasa la primera entrada. Nunca inicies una animación en el fotograma uno.
fillMode = .forwards + isRemovedOnCompletion = false fija la presentación, y la eliminación es por objetoUn clearAnimations central que barre el nodo, cada geometría hija, las luces y las acciones en ejecución, llamado desde cada punto de entrada.
El metal real de frente se renderiza como un agujero gris o negroUn espejo visto de frente refleja la zona de entorno detrás de la cámara. Mantén la base pintada aprobada y añade una capa aditiva delgada con su propio mapa de reflexión.
Alternar castsShadow provoca una penumbra borrosa en un fotograma; shadowBias y categoryBitMask de la luz se ignoran para sombras direccionales hacia adelanteMantén castsShadow permanentemente activado y anima el alfa de shadowColor, sincronizado con el movimiento.
Un retardo de calentamiento fijo aún tartamudea en dispositivos fríos y el Simulador; el primer fotograma de un efecto de partículas compila su propio pipeline y cae exactamente cuando se disparaEncendido de dos llaves: controla la entrada con el retardo mínimo Y el controlador de finalización de prepare. Calienta los pipelines de partículas con una ráfaga de opacidad cero que coincida con las banderas del efecto real.
El formato predeterminado de UIGraphicsImageRenderer hereda la escala de pantalla, inflando cada textura generada 9 veces en píxeles - mortal para texturas re-renderizadas en vivo (grabado por pulsación de tecla)Fija la escala del formato del renderizador a 1 y dimensiona el lienzo a la proyección en pantalla del actor; combina reorientaciones de múltiples entradas en una renderización por pase de actualización.
Reproducir el movimiento de un objeto real a partir de fotos produce rigs seguros que fallan lateralmente - cada solución revela un nuevo errorLas fotos fijas contienen poses, no trayectorias o mecanismos; los ajustes de pose final no determinan la trayectoria. Modela la trayectoria: un rig de calibración con controles de pose directos, el propietario creando fotogramas clave contra el objeto físico.
Un movimiento con fotogramas clave tartamudea rítmicamente en sus fotogramas clave y sobrevive a todas las correcciones de renderizado y temporizaciónLas sacudidas están horneadas en la curva: la base uniforme de Catmull-Rom en fotogramas clave espaciados de manera desigual acelera la velocidad en cada nudo. Interpola con tangentes Hermite ponderadas por intervalo (o una cúbica natural) sobre fases basadas en distancia, y controla con una verificación de continuidad numérica.
Una sub-malla cortada de un modelo más grande se mide como si fuera el objeto completo, sin ningún error en ninguna parteEl corte recortó solo el búfer de índices; el búfer de vértices aún contiene todos los vértices del original. Mide solo los vértices referenciados por los índices de la sub-malla.
Una imagen cuadrada asignada a scene.lightingEnvironment se ignora silenciosamente - cero reflejos, todos los materiales de espejo se renderizan en negro, sin salida en consolaPinta el mapa de entorno en un diseño de cubemapa reconocido, lo más fácil es un lienzo esférico 2:1 (1024x512). Solo material.reflective acepta un mapa de esfera cuadrado.

Mapa de referencias

  • references/stage-recipe.md: el escenario completo, configuración de vista, coordinador, jerarquía de nodos, cámara, montaje de luces, gota de contacto y receptor, mapas de entorno programáticos y texturas, partículas de impacto en un escenario, modificadores de shader en actores del escenario (la trampa uniforme del espacio lineal), manteniendo la identidad SwiftUI del escenario (trampas de remontaje y tormenta de actualizaciones).
  • references/first-frame-and-warmup.md: el tartamudeo de compilación de pipeline de Metal en el primer dibujo y ambas curas, calentamiento con una entrada retardada (actualizado a encendido de dos llaves controlado por la finalización de prepare), o mantener la escena montada caliente y reorientarla; calentamiento de pipeline de partículas; probar la cura con señales y trazas de tartamudeo en el dispositivo.
  • references/shadows-and-lights.md: cada trampa silenciosa de sombras, la combinación confiable forward + shadowOnly, animar la visibilidad de la sombra, el presupuesto de luz neutra, metal de frente.
  • references/baked-animation.md: por qué los fotogramas clave horneados superan a los temporizadores, la hoja de referencia para diseñar compases multifásicos antes de hornearlos, clasificación de costuras (C1 vs impulsos de contacto), diseñar peso, muestreo denso, contabilidad de limpieza, tokens de generación, robar un nodo en medio de la animación, rodar sin deslizar, rodar a lo largo de trayectorias en el suelo (dirección, puesta en escena en espacio de pantalla, trazas de depuración), canales más allá de las transformaciones (pesos de morpher, valores de lente, uniformes de shader), resortes como material de autoría, una propiedad un propietario.
  • references/motion-from-reference.md: reproducir el movimiento de un objeto real - lo que las fotos fijas y el video pueden y no pueden decirte, modelar la trayectoria en lugar del mecanismo, el rig de calibración (el propietario posa al actor y guarda fotogramas clave), parametrización de distancia e interpolación ponderada por intervalo de poses guardadas a mano, la trampa uniforme de Catmull-Rom, puertas de continuidad numérica, bucles de estado coseno sin costuras con salidas de la fase actual, medir sub-mallas recortadas.
  • references/physics-without-engine.md: el integrador de paso fijo hecho a mano horneado a fotogramas clave, paredes y suelo como números simples, hápticos impulsados por contacto, un vuelco de pivote de borde, y por qué esto supera a SCNPhysics para escenas coreografiadas.
  • references/gestures-and-haptics.md: arrastrar para agarrar sin prueba de impacto, abrazaderas suaves mientras se sostiene, velocidad de liberación, hápticos de impacto, compases programados que sobreviven a dedos vivos (reintentos limitados, sondeos con token, protectores de gestos de actor oculto, robo cierra el contrato de retención), Reducir Movimiento como taxonomía, acceso VoiceOver a un escenario invisible, coexistir con gestos SwiftUI.
  • references/sequencing-stages.md: dirigir varios escenarios como una película - un reloj maestro con compases como datos, trampas de deriva de tiempo real, cortes en movimiento después de que la salida se borre, premontar el siguiente escenario para calentamiento, un escenario que sobrevive a su propio corte (humo persistente), reubicar la línea de tiempo en una interacción del usuario, un líder de grabación, verificar cortes fotograma a fotograma.
  • references/modeling-actors.md: construir objetos héroe creíbles a partir de primitivas - proporciones del mundo real antes de ajustar a ojo, anillos para caras empotradas, siluetas de tubo más toro, legibilidad de patrón radial, inclinación por instancia para caras cóncavas, espacios abiertos, características de relieve como geometría (nunca pintura), albedo de metal satinado en escenarios oscuros, controlar actores que llegan como archivos.
  • references/camera-choreography.md: la cámara como el artista - el rig de órbita, vuelos de revelación horneados, enfoque que sigue al carro, arrastrar-órbita con inercia y volver a casa, reflexiones SCNFloor como conexión a tierra, puesta en escena mate bajo luces de acento, restricciones para rigs de seguimiento (y por qué nunca van sobre el actor).
  • references/instancing-and-swarms.md: docenas de actores a la vez - una geometría para el enjambre, pilas basadas en ranuras en lugar de física, parábolas resueltas hacia atrás desde el punto de aterrizaje, caída mezclada a una pose de reposo, aleatoriedad con semilla, escalonamiento por programación, notas de presupuesto.
  • references/multi-actor-physics.md: varios actores en una simulación horneada - N vectores de estado en un reloj, colisiones por pares (separar, luego intercambiar al acercarse), el agarre de congelar-el-mundo, prueba de impacto de qué dedo tocó el actor, listas de contacto por actor para compresión y hápticos.

Lista de verificación de revisión

Antes de enviar un escenario, verifica:

  • backgroundColor = .clear e isOpaque = false en la SCNView; el escenario se compone sin caja o costura visible.
  • Ninguna animación comienza en el primer fotograma de la vista; prepare se ejecuta y la primera entrada se retrasa o la escena se mantiene montada caliente.
  • Las sombras usan modo hacia adelante con un receptor .shadowOnly; nada depende de sombras diferidas, shadowBias o control de categoryBitMask de luz.
  • Los planos con textura alfa (etiquetas, calcomanías) tienen castsShadow = false, o proyectarán sombras cuadradas.
  • Los cambios de visibilidad de sombra modifican el alfa de shadowColor; castsShadow nunca se alterna en tiempo de ejecución.
  • Si la escena debe renderizar una textura con fidelidad de color, el ambiente más la direccional multiplicado por cos(incidencia) suma neutro (1000) para una superficie plana; sin grises de luz recortados.
  • Cualquier imagen en lightingEnvironment (o background) usa un diseño de cubemapa reconocido - esférico 2:1, tira 6:1 o 1:6, o seis imágenes; una imagen cuadrada allí se ignora silenciosamente y los materiales reflectivos se renderizan en negro.
  • Cada continuación asíncrona (entradas retardadas, hápticos programados, transiciones encadenadas) captura un token de generación y lo vuelve a verificar antes de actuar.
  • Cualquier código que robe un nodo en animación captura valores de .presentation en el modelo antes de llamar a removeAllAnimations.
  • Las animaciones horneadas establecen el modelo a la pose final antes de addAnimation; nada depende de fillMode = .forwards sin una limpieza general.
  • Los compases multifásicos tienen un comentario de hoja de referencia encima de la función de pose que coincida con la estructura de límite de fase; los tiempos de fase y referencia viven en esa única estructura, nunca como literales en el bucle de muestra o en hápticos programados. Cada costura está clasificada: las costuras de diseño son C1, las costuras de impulso ocurren solo en eventos de contacto y cada una aterriza una referencia.
  • Los objetos rodantes esclavizan el giro a la distancia dividida por el radio; nada se desliza.
  • El movimiento copiado de un objeto real se crea como fotogramas clave a través de un rig de calibración (controles de pose directos, poses guardadas, el ojo del propietario).

Skills relacionados