1 điểm bởi GN⁺ 2025-11-24 | 1 bình luận | Chia sẻ qua WhatsApp
  • Một lỗi kỳ lạ đã được phát hiện ở cảnh đầu của Half-Life 2, nơi cánh cửa không mở khiến tiến trình bị chặn lại
  • Nguyên nhân là khi cửa mở, đầu mũi chân của người bảo vệ đứng bên trong va chạm với quỹ đạo của cánh cửa, khiến cửa đóng lại rồi bị khóa
  • Cùng một va chạm này cũng tồn tại trong mã nguồn gốc, nhưng kết quả khác nhau do chênh lệch độ chính xác giữa phép toán dấu phẩy động x87 năm 2004phép toán SSE năm 2013
  • Trong môi trường x87, một chuyển động xoay rất nhỏ đẩy bàn chân lệch đi nên va chạm được giải quyết, nhưng trong SSE thì lượng xoay không đủ nên cửa bị đóng lại
  • Đây là một ví dụ tiêu biểu cho thấy độ chính xác dấu phẩy động và khác biệt trình biên dịch có thể ảnh hưởng đến hành vi thực tế của trò chơi như thế nào

Lỗi được phát hiện trong quá trình port Half-Life 2 sang VR

  • Năm 2013, trong lúc Valve thử nghiệm port Team Fortress 2 sang VR, họ cũng khiến Half-Life 2Portal 1 dùng cùng engine có thể chạy được trên VR
    • Portal 1 gây chóng mặt đến mức gần như không thể chơi trong VR vì hiện tượng méo góc nhìn
    • Half-Life 2 thì hoạt động tương đối tốt, và cảm giác nhập vai đặc trưng của VR được tăng cường ở các phân cảnh đi thuyền, xếp thùng và chiến đấu với manhack
  • Trong lúc thử nghiệm, một nhà phát triển chơi toàn bộ game bằng VR từ đầu đến cuối thì phát hiện ra trạng thái không thể tiếp tục ở cảnh ga tàu đầu game

Phân tích nguyên nhân cửa không mở

  • Trong kịch bản gốc, người bảo vệ (thực ra là Barney) gõ cửa rồi nói “vào đi”, sau đó khi người chơi bước vào phòng thì trò chơi sẽ chuyển sang đoạn script tiếp theo
  • Nhưng trong tình huống lỗi, cánh cửa lạch cạch rồi tự khóa và đóng hẳn lại, người bảo vệ tiếp tục chỉ vào cửa còn người chơi thì bị mắc kẹt
  • Ngay cả khi build lại mã nguồn gốc của Half-Life 2 thì vấn đề tương tự vẫn xảy ra, gây ra sự bối rối như thể một lỗi sinh ra do quay ngược thời gian

Nguyên nhân gốc: thay đổi trong cách tính toán dấu phẩy động

  • Vào thời điểm phát hành năm 2004, Half-Life 2 sử dụng tập lệnh toán học x87, với cấu trúc trộn lẫn độ chính xác 32, 64 và 80 bit
  • Trong các bản build từ năm 2013 trở đi, tập lệnh SSE được dùng mặc định, nên độ chính xác tính toán được giới hạn rõ ràng ở 32 bit hoặc 64 bit
  • Ở cả hai môi trường, cánh cửa và đầu mũi chân của người bảo vệ đều va chạm, nhưng kết quả khác nhau do chênh lệch cực nhỏ trong tính toán của engine vật lý
    • Trên x87, khi va chạm xảy ra người bảo vệ xoay đi một chút xíu, khiến bàn chân rời khỏi cửa và cửa mở ra
    • Trên SSE, mức xoay giảm đi rất nhỏ nên bàn chân vẫn chạm vào cửa, làm cửa đóng lại và bị khóa

Cách sửa và giải quyết

  • Sau khi xác định được vấn đề, lỗi được khắc phục bằng một chỉnh sửa đơn giản: dịch vị trí của người bảo vệ lùi lại khoảng 1 mm
  • Quá trình debug cũng tốn khá nhiều thời gian, bao gồm cả việc phải học lại cách dùng các công cụ cũ
  • Trường hợp này cho thấy khác biệt về độ chính xác và thay đổi trong thiết lập trình biên dịch có thể làm thay đổi cách mã cũ vận hành

Phản ứng từ cộng đồng

  • Các nhà phát triển đồng cảm với nhận xét rằng “vấn đề lúc nào cũng là do độ chính xác dấu phẩy động
  • Một số người nhắc đến trường hợp thay đổi tính toán va chạm trong các bản remake của Sonic 1, 2 và 3 để chỉ ra điểm tương đồng
  • Cùng với bài học rằng “mã thì giống nhau nhưng trình biên dịch thì khác”, đây được xem là một ví dụ gợi nhắc về sự khó khăn trong việc duy trì mã legacy
  • Những nhà phát triển khác cũng liên hệ điều này với lý do vì sao trong Fallout 4 và các game khác, NPC được thiết kế để không đi xuyên qua cửa
  • Nhìn chung, nhiều người xem đây là một trong những câu chuyện lỗi thú vị nhất

1 bình luận

 
GN⁺ 2025-11-24
Bình luận trên Hacker News
  • Hồi trước khi còn làm phát triển game, tôi nhớ đã gặp lỗi assertion fail do tính toán FPU chỉ xảy ra trên một số PC nhất định
    Nguyên nhân là phần mềm nhập liệu bằng bút đã inject DLL vào mọi tiến trình và reset chế độ FPU về mặc định
    Cuối cùng, chúng tôi chuyển phần mã cấu hình FPU từ giai đoạn khởi tạo sang vòng lặp sự kiện để tránh ảnh hưởng từ DLL bên thứ ba

    • Truy vết quá đỉnh. Trạng thái FPU toàn cục đúng là đã gây ra vô số cơn đau đầu
  • Một trong những mục tiêu của tôi là khiến Valve dùng Nix
    Tôi nghĩ điều này sẽ còn hấp dẫn hơn khi hỗ trợ Windows đang được triển khai
    Như vậy không chỉ mã nguồn gốc mà cả toolchain và dependencies của thời điểm đó cũng có thể được tái tạo hoàn toàn, nên có lẽ sẽ dễ lần ra nguyên nhân gốc của những lỗi kiểu này hơn nhiều

  • Làm tôi nhớ đến meme “DOOR STUCK”
    Video liên quan

  • Tôi tự hỏi liệu “Half-Life 2 VR beta” có thật sự chơi được không
    Nếu có thì tại sao tôi lại không biết, còn nếu không thì tại sao đến giờ vẫn chưa có
    Tôi cũng rất muốn thử Portal VR. Mọi người bảo nó gây say nặng, nhưng tôi miễn nhiễm với say VR nên rất đáng để thử

    • Không rõ bản beta, nhưng có một mod chuyển đổi HL2 VR rất tuyệt và có thể chơi ngay bây giờ
      Mức độ hoàn thiện cao đến mức khiến tôi chơi lại HL2 sau một thời gian dài
    • Cũng có mod Portal 2 VR. Tôi đã chơi hết và bất ngờ là trải nghiệm khá thoải mái
  • Khi chuyển từ x87 sang SSE, một số phép tính bị hỏng là chuyện khá thường gặp
    TF2 cũng từng gặp như vậy: ở bản build Linux, game dùng SSE nên cách tính đạn dược hơi khác một chút

    • Nghe thật bất ngờ khi họ dùng float để tính đạn dược
    • Khác biệt thực sự dễ thấy chỉ là ở chỉ số metal của Engineer
      Hộp nhỏ cho +40 hoặc +41, và điều đó khác nhau tùy theo OS của server
      Mỗi lần vào server mới, khá vui khi đoán xem nó đang chạy OS nào
  • Chỉ đổi từ x87 sang SSE thôi mà game đã hỏng, nên thật kỳ lạ khi chuyển đổi x86→ARM lại hoạt động tốt đến vậy

    • Chỉ riêng x87 FPU là một đơn vị số thực dấu phẩy động kỳ quặc
      Nó dùng thanh ghi 80-bit nên có độ chính xác cao hơn, nhưng lại có hành vi lạ như mất độ chính xác khi spill ra bộ nhớ
    • Vì khác biệt về độ chính xác nên các giá trị có thể lệch đi rất rất nhỏ, và điều đó đôi khi dẫn đến vấn đề như va chạm với cánh cửa
      Trước đây khi debug một software synthesizer, tôi cũng từng gặp lỗi độ chính xác tương tự
      Mô phỏng mạch RC cần trạng thái đổi khi tiến gần về 0, nhưng trên một số CPU nhất định thì giá trị denormal không bị flush nên điều kiện không bao giờ thỏa mãn
      Cuối cùng tôi chỉnh ngưỡng đại khái thành 0.7 và 0.01 thì mọi thứ hoạt động tốt trên mọi nền tảng
  • Nói ngoài lề một chút, tôi định làm một bản sao Twitter với tính năng ban ngay nếu ai đó đăng blog theo kiểu nhiều đoạn văn

    • Chia sẻ liên kết mở toàn bộ thread đó trên một trang
    • Có ý kiến cho rằng việc thiếu tùy chọn đăng như vậy không có nghĩa là thread sẽ biến mất
    • Ngược lại, cũng có đề xuất làm một nền tảng bắt buộc phải viết ít nhất hai đoạn, đồng thời LLM sẽ kiểm chứng nội dung