En mi juego tengo un gran catálogo de equipo: armaduras, armas y escudos. Las combinaciones entre estos pueden ser realmente inmensas.
Además de eso, el jugador tiene la opción de cambiar en el juego a un conjunto diferente de combinación de armadura y arma. Al final, para resolver esto, he usado la siguiente estructura de objeto.
Cada vez que cambio las armas, activo/desactivo los GameObjects necesarios. Las animaciones se establecen de esta manera:
Ahora, el problema es crear la animación. Primero consideré pre-renderizar programáticamente todas las combinaciones, pero mi catálogo es tan grande que crearía 100, si no 1000, de animaciones. Así que opté por una solución diferente. Crear en el tiempo de juego la animación, una vez que supe qué equipo seleccionaría el jugador. Para eso, creé un script para encargarme de eso. El problema es que he estado usando las API de UnityEditor y ahora me doy cuenta de que la compilación no funcionará. Específicamente debido a 2 clases diferentes: EditorCurveBinding y ObjectReferenceKeyframe .
Estos son algunos fragmentos de cómo estaba usando estas clases al crear las animaciones:
static EditorCurveBinding GetEditorCurveBinding(string path = "") { EditorCurveBinding spriteBinding = new EditorCurveBinding(); spriteBinding.type = typeof(SpriteRenderer); spriteBinding.path = path; spriteBinding.propertyName = "m_Sprite"; return spriteBinding; } static ObjectReferenceKeyframe GetKeyframe(float time, Sprite sprite) { ObjectReferenceKeyframe keyframe = new ObjectReferenceKeyframe(); keyframe.time = time / FRAMERATE; keyframe.value = sprite; return keyframe; } Ahora, el problema con la curva, creo que logré resolverlo, reemplazándolo con este código, reemplazando EditorCurveBinding con AnimationCurve :
AnimationClip clip = ... AnimationCurve curve = new AnimationCurve(); clip.SetCurve(path, typeof(SpriteRenderer), "m_Sprite", curve); Pero no tengo idea de cómo configurar los sprites para cada animación. Pensé que usar curve.AddKey podría ser útil, pero no he visto ninguna forma de agregar un sprite allí.
¿Cómo podría volver a escribir ese código para evitar usar UnityEditor ?
Personalmente, evitaría por completo el Animador y las Animaciones incorporados, ya que esta herramienta tiene el propósito muy limitado de animar un solo objeto de una manera predefinida (por ejemplo, para una escena).
Además de eso, el jugador tiene la opción de cambiar en el juego a un conjunto diferente de combinación de armadura y arma. Al final, para resolver esto, he usado la siguiente estructura de objeto.
Como probablemente sepa, esto es muy ineficiente en términos de memoria y disminuirá el rendimiento (los objetos deshabilitados aún tienen una sobrecarga de CPU marginal). Y aumentará el tiempo de carga y el tiempo de instanciación de nuevos objetos.
Debido a que Animator no tiene API para acceder a su interior y tipo de animación y, en general, no puede hacer casi nada con él, excepto indicarle que reproduzca o detenga . Dado que entiendo que su animación está "basada en Sprite" y no "basada en Transformación", ¡cualquier idea sensata es simplemente ineficiente!
La mejor solución contra la que me comprometo es la siguiente:
public class AnimationController : MonoBehaviour { public int AnimationIndex; public Sprite[] AnimationSprites; public SpriteRenderer SpriteRenderer; private void Update() { SpriteRenderer.sprite = AnimationSprites[AnimationIndex]; } }Dado que ya necesitamos tener una estructura personalizada que administre nuestros sprites, es posible que deseemos optimizar todo, dado que no estamos usando casi ninguna de las funciones de Animator, podríamos escribir un controlador personalizado que reemplazaría a Animator en este caso. ¡Esto debería mejorar significativamente el rendimiento ya que Animator es muy pesado!
// MonoBehaviour is optional here public class SpriteRendererAnimationHandler { // More fields that would control the animation timing public Sprite[] AnimationSprites; public SpriteRenderer SpriteRenderer; public void OnAnimationUpdate(int index) { var resolvedIndex = ResolveIndex(index); SpriteRenderer.sprite = AnimationSprites[resolvedIndex]; } private int ResolveIndex(int index) { // Resolve animation index to sprite array index } } // One controller per character - or global per game that synchronize all animations to locked FPS 12. public class AnimationController : MonoBehaviour { private List<SpriteRendererAnimationHandler> Handlers = new List<SpriteRendererAnimationHandler>(); public void FixedUpdate() { foreach (var handler in Handlers) { // Calculate animation index int calculatedAnimationIndex = ...; handler.OnAnimationUpdate(calculatedAnimationIndex); } } }