Montaje del fósil - JRuizGil/MeltTheDeep GitHub Wiki

Montaje del fósil

TDD · Documento técnico

Origen de la mecánica

El diseño de coger, girar, voltear y encajar viene de mi segunda propuesta, Piece by Piece. Es solo el diseño: el código lo he escrito de nuevo para este proyecto. Cómo se vive la mecánica desde el lado del jugador está en El fósil; esta página cuenta cómo funciona por dentro.

Datos

Clase Tipo Qué contiene
BoneDefinition ScriptableObject Id, id de socket, lado (para huesos con pareja), tamaño para la apertura de la aspiradora, volumen en el tanque y malla
SkeletonDefinition ScriptableObject Sockets con su pose relativa al armazón y la mejora secreta que desbloquea
FossilInventory Clase C# Huesos recogidos pero sin montar, y huesos montados

Cada hueso sabe cuál es su socket por id. El armazón no deduce nada de la forma del hueso: lo que tiene que encajar en cada hueco lo dicen los datos.

El taller

En la superficie, junto a la tienda, los huesos recogidos se instancian sobre una mesa al lado del armazón vacío. Cuando subo un hueso nuevo, aparece en la mesa con una pose cualquiera. Todo lo que ocurre a partir de ahí lo gestionan GrabController, SnapValidator y FossilAssembly.

Coger y mover

GrabController lanza un raycast contra la capa Bones. Si da en un hueso, lo paso a cinemático y lo muevo en cada FixedUpdate con Rigidbody.MovePosition y Rigidbody.MoveRotation, suavizando hacia un punto delante de la cámara. No lo emparento a la cámara. Moverlo con el Rigidbody y no con el Transform hace que la física lo trate como un cuerpo en movimiento: empuja a los otros huesos de la mesa en lugar de atravesarlos.

Girar y voltear

Q y E giran el hueso 90° alrededor del eje de la cámara, redondeado al eje del mundo más cercano. Redondear evita que un giro inclinado deje el hueso en un ángulo raro que luego no se pueda corregir. La rotación se interpola durante 0,15 s. F voltea el hueso 180° alrededor del eje horizontal.

Antes de girar lanzo un Rigidbody.SweepTest. Si el giro haría que el hueso chocara con la mesa o con otro hueso, lo rechazo y el hueso se queda como estaba. SweepTest barre una traslación y no comprueba la orientación final, así que es una aproximación que reviso en Sandbox_Fossil con los huesos más grandes. Las poses del armazón las diseño para que se alcancen con giros de 90° y volteos, de modo que el jugador nunca necesita una orientación que los controles no permitan.

Validar el encaje

SnapValidator es una clase estática sin dependencias de escena, para poder probarla con tests. Valida por identidad del hueso, no por forma: comprueba el socket que le corresponde a ese hueso y no otro. El encaje es correcto cuando se cumplen dos condiciones:

  1. La distancia entre el hueso y su socket es menor de 0,15 m.
  2. El ángulo entre su rotación y la del socket es menor de 10°.

Las parejas, como las aletas delanteras o las traseras, tienen un socket izquierdo y otro derecho separados. Una aleta derecha nunca valida en el socket izquierdo, aunque su forma sea idéntica a la de la izquierda reflejada. Y una cara equivocada de un hueso correcto queda a unos 180° de la rotación esperada, muy por encima de los 10° de tolerancia.

La silueta del socket, que se dibuja con un material fantasma, aparece cuando el hueso está a menos de 0,4 m de su socket y además con la orientación correcta. Así la silueta ayuda sin regalar la solución: no muestra dónde va un hueso mal girado.

Soltar

Cuando suelto el hueso, ocurre una de dos cosas.

Si es correcto, pasa a su pose de socket en 0,2 s con una interpolación, queda cinemático, se emparenta al armazón y se lanza el evento BoneMounted, que escuchan el audio y la interfaz.

Si no es correcto, el hueso vuelve a ser dinámico, cae, resbala hasta apoyarse en la mesa y suena el resbalón (Sonido con FMOD). No hay penalización ni contador de fallos: puedo cogerlo y probar de nuevo las veces que quiera.

Recompensas

Solo hay una recompensa, y es completar el esqueleto. Cuando FossilInventory tiene montadas las 8 piezas, lanza el evento SkeletonCompleted. Ese evento desbloquea en la tienda una mejora secreta de la pistola, que todavía tengo que decidir, y deja el fósil expuesto en el taller. Montar huesos sueltos no cambia ninguna estadística.

Guardado

La partida guarda los ids de los huesos recogidos y los de los montados. Al cargar, FossilAssembly coloca los montados directamente en sus sockets y deja el resto en la mesa.

Pruebas

Las pruebas EditMode cubren la matemática de la validación: acepta una posición y un ángulo dentro de la tolerancia, rechaza los que se pasan y rechaza un hueso del lado contrario. Las pruebas PlayMode montan un hueso en Sandbox_Fossil y comprueban que encaja, y que un hueso mal colocado resbala y vuelve a la mesa. La lista completa está en Guardado, rendimiento y pruebas.