1 puntos por GN⁺ 2025-11-24 | 1 comentarios | Compartir por WhatsApp
  • En una escena temprana de Half-Life 2, se descubrió un extraño bug en el que una puerta no se abre y detiene el progreso
  • La causa es que, al abrirse la puerta, la punta del pie del guardia que está dentro choca con la trayectoria de la puerta, lo que hace que la puerta se cierre de nuevo y se bloquee
  • El mismo choque ya existía en el código original, pero el resultado cambia por la diferencia de precisión entre las operaciones de punto flotante x87 de 2004 y las operaciones SSE de 2013
  • En el entorno x87, una rotación mínima empuja ligeramente el pie y resuelve la colisión, pero en SSE la rotación no alcanza y la puerta termina cerrándose
  • Este caso muestra de forma ejemplar cómo la precisión de punto flotante y las diferencias del compilador pueden afectar el comportamiento real de un juego

Bug descubierto durante el proceso de portar Half-Life 2 a VR

  • En 2013, durante un experimento en Valve para portar Team Fortress 2 a VR, también lograron ejecutar en VR Half-Life 2 y Portal 1, que usan el mismo motor
    • Portal 1 provocaba tanto mareo en VR por la distorsión de la perspectiva que era prácticamente injugable
    • Half-Life 2 funcionaba relativamente bien, y la inmersión propia de VR mejoraba escenas como el bote, apilar cajas y el combate contra manhacks
  • Durante las pruebas, un desarrollador jugó todo el juego en VR y encontró un estado de progreso bloqueado en la escena inicial de la estación de tren

Análisis de la causa por la que la puerta no se abre

  • En la secuencia original, el guardia (en realidad Barney) golpea la puerta, dice “entra” y, cuando el jugador entra a la sala, avanza el siguiente script
  • Sin embargo, en la situación con el bug, la puerta tiembla, se bloquea y termina cerrándose por completo; el guardia sigue señalando la puerta y el jugador queda atrapado
  • Incluso al recompilar el código fuente original de Half-Life 2 ocurría el mismo problema, lo que generó confusión porque parecía un bug surgido al viajar en el tiempo

Causa raíz: cambio en la forma de operar con punto flotante

  • Cuando Half-Life 2 salió en 2004, usaba el conjunto de instrucciones matemáticas x87, con una estructura donde se mezclaban precisiones de 32, 64 y 80 bits
  • En los builds posteriores a 2013, el conjunto de instrucciones SSE pasó a usarse por defecto, aplicando una precisión de cálculo claramente limitada a 32 o 64 bits
  • En ambos entornos, la puerta y la punta del pie del guardia chocan, pero el resultado cambia por pequeñas diferencias de cálculo en el motor físico
    • En x87, al producirse la colisión, el guardia rota apenas un poco y el pie se aparta de la puerta, así que la puerta se abre
    • En SSE, la rotación se reduce mínimamente, el pie sigue tocando y la puerta vuelve a cerrarse y bloquearse

Corrección y solución

  • Tras identificar el problema, lo resolvieron con un cambio simple: mover la posición del guardia unos 1 mm hacia atrás
  • El proceso de depuración tomó bastante tiempo, incluido volver a aprender a usar herramientas antiguas
  • Este caso muestra que las diferencias de precisión y los cambios en la configuración del compilador pueden alterar el comportamiento de código antiguo

Reacción de la comunidad

  • Los desarrolladores coincidieron con frases como “el problema siempre es la precisión de punto flotante
  • Algunos mencionaron casos similares de cambios en el cálculo de colisiones en los remakes de Sonic 1, 2 y 3
  • Junto con la lección de que “el código es el mismo, pero el compilador es distinto”, se evaluó como un caso que recuerda la dificultad de mantener código legado
  • Otros desarrolladores conectaron esto con la razón por la que en juegos como Fallout 4 se diseñó para que los NPC no atravesaran puertas
  • En general, muchos lo consideraron “una de las historias de bugs más interesantes”

1 comentarios

 
GN⁺ 2025-11-24
Comentarios en Hacker News
  • Cuando antes trabajaba en desarrollo de juegos, recuerdo que en ciertas PC fallaban assertions solo por errores de cálculo del FPU
    La causa era que un software de entrada manuscrita inyectaba DLL en todos los procesos y hacía reset del modo del FPU a su valor predeterminado
    Al final movimos el código de configuración del FPU de la fase de inicialización al loop de eventos, para evitar el impacto de DLL de terceros

    • Gran trabajo de rastreo. El estado global del FPU de verdad ha causado muchísimos dolores de cabeza
  • Uno de mis objetivos es lograr que Valve use Nix
    Creo que se verá más atractivo ahora que el soporte para Windows está avanzando
    Si eso pasa, sería posible reproducir por completo no solo el código fuente original, sino también el toolchain y las dependencias de esa época, y probablemente sería mucho más fácil encontrar la causa raíz de bugs como este

  • Me recuerda al meme de “DOOR STUCK”
    Video relacionado

  • Me pregunto si la “beta de Half-Life 2 VR” realmente se puede jugar
    Si sí, no sé por qué no me enteré; si no, me pregunto por qué todavía no existe
    También me gustaría muchísimo probar Portal VR. Dicen que marea bastante, pero yo soy inmune al mareo en VR, así que valdría la pena intentarlo

    • No sé sobre la beta, pero hay un excelente mod de conversión de HL2 VR que puedes disfrutar ahora mismo
      Tiene tanta calidad que hizo que volviera a jugar HL2 después de mucho tiempo
    • También existe un mod VR de Portal 2. Lo jugué completo y, sorprendentemente, fue bastante cómodo
  • Cuando se cambia de x87 a SSE, es común que algunos cálculos se rompan
    En TF2 pasó lo mismo: en el build de Linux se usaba SSE, así que el cálculo de la munición salía un poco distinto

    • Sorprende que usaran float para calcular la munición
    • En realidad, la única diferencia visible era el valor de metal del Engineer
      Las cajas pequeñas daban +40 o +41, y eso cambiaba según el OS del servidor
      Era divertido averiguar qué OS usaba cada vez que te conectabas a un servidor nuevo
  • Si un juego ya se rompe solo con cambiar de x87 a SSE, impresiona que la traducción de x86 a ARM funcione tan bien

    • El FPU x87 es prácticamente la única unidad de punto flotante extraña
      Usa registros de 80 bits, así que tiene más precisión, pero se comporta de formas raras, como perder precisión cuando hace spill a memoria
    • Por diferencias de precisión, los valores pueden variar apenas un poco, y eso a veces termina causando problemas como la colisión de puertas
      Hace tiempo, al depurar un sintetizador por software, también me topé con un bug de precisión parecido
      La simulación de un circuito RC tenía que acercarse a 0 para que cambiara el estado, pero en ciertos CPU los valores denormal no se flush-eaban y la condición nunca se cumplía
      Al final ajusté el umbral más o menos a 0.7 y 0.01, y así terminó funcionando bien en todas las plataformas
  • Como meta-comentario, si hiciera un clon de Twitter, le pondría una función para banear de inmediato a quien intente bloguear en varios párrafos

    • Comparten este enlace que despliega ese hilo en una sola página
    • Hay quien opina que, aunque no exista esa opción de publicación, eso no hará que los hilos desaparezcan
    • También hubo la propuesta contraria: crear una plataforma donde sea obligatorio escribir al menos dos párrafos y donde un LLM verifique el contenido