Recent discussion about the perils of doors in gamedev reminded me of a bug caused by a door in a game you may have heard of called "Half Life 2". Are you sitting comfortably? Then I shall begin.
Once upon a time, I worked at Valve on virtual reality. This was in 2013 around the time the Oculus DK1 emerged, and Joe Ludwig and I decided that the best way to figure out how VR would work in a real game context was to port a real game to it and see what happened.

We picked Team Fortress 2 as the game - the reason why is a whole different story I won't go into here. TF2 used the Source 1 engine, and as it happened two Valve games also using that same version of the engine were Half Life 2 and Portal 1. So as a side-effect they also got to work in VR.

Well, Portal 1 "worked" - but all the tricks with perspective when you went through a portal were of course a nauseating disaster - it was pretty unplayable.

But HL2 did actually work pretty well. Joe spent a lot of time making the boat sequences work in a reasonable way.

There's a sequence of stacking boxes near the start that is somewhat infuriating in the original - the stack keeps falling over - but in VR it's really easy to place them well.

Also, whacking the manhacks with your crowbar goes from being a panicked flailing in flatscreen, to being an elegant one-swing home-run hit in VR.

Luckily, there was some other excuse to reissue HL2 anyway (see https://developer.valvesoftware.com/wiki/Source_2013) and the VR version worked pretty well, so we put the VR support on a command-line, labelled it "beta", rebuilt the whole of HL2 and prepared to ship it.
Source 2013 - Valve Developer Community

Of course we've played a bunch of HL2 by this point, testing all the VR stuff works. But we just skipped to the relevant chapters - we never actually played through from the start. And I hadn't played it through in a while, so I thought I'd do that in VR, start to finish. If I discovered anything that still didn't work, I could at least document it in the release notes.
So I started it up, selected new game, played the intro section. It's a fairly well-known section - you arrive at the train station with a message from Breen, a guard makes you pick up a can, and then you have to go into a room and... uh... I got stuck. I wasn't dead, I just couldn't go anywhere. I was stuck in a corridor with a guard, and nowhere to go. Bizarre.

What is meant to happen is a guard (spoiler alert - it's actually Barney in disguise) bangs on a door, the door opens, he says "get in", and then the game waits for you to enter the room before the script proceeds.

But in this case the door sort of rattled, but didn't open, and then locked shut again. So you can't get in the room, and the gate closed behind you, so you can't go do anything else. The guard waits forever, pointing at the locked door, and you're stuck.

I checked a video online, wondering if my memory was faulty - nope, the door's meant to open automatically, and you walk in. https://www.youtube.com/watch?v=y_3vMUOayyc&t=215s (at 3:40). But... now it doesn't!
Half Life 2 opening scene, first 5 minutes - in Full HD

YouTube
Oh dear. We can't ship this. I get some other folks, including some folks who worked on HL2 originally, and yep - it's broken. And it's broken when you're not in VR either - so it's not something Joe and I broke. But nobody knows why - none of the relevant code has changed.
Someone even goes back in the source history and compiles the original game as it shipped - nope, that original version is also broken. How can this possibly be? At this point people are freaking out - this isn't a normal bug - it appears to have traveled backwards in time and infected the original!
After about a day remembering how to use the debugging and replay tools, someone smart (sorry, I don't remember who) figured out what was going wrong.
If you watch the video, when the door unlocks and then opens, there's a second guard standing inside the room to the left of the opening door. That guard is actually standing very slightly too close - the very corner of his bounding box intersects the door's path as it opens. So what's happening is the door starts to open, slightly nudges into the guard's toe, bounces back, closes, and then automatically locks. And because there's no script to deal with this and re-open the door, you're stuck.
Once we'd figured this out, the fix was simple - move the guard back about a millimeter. Easy. But it took a lot of work to find because people had to dust off old memories of how the debugging tools worked, etc.
OK cool now we can ship the game phew. But why did this EVER work? The guard's toe was in the way in the original version as well. As I say, we went back in time and compiled the original as-shipped source code - and the bug happened there as well. It's always been there. Why didn't the door slam closed again? How did this ever ship in the first place?
So this kicked off an even longer bug-hunt. The answer was (as with so many of my stories) good old floating point. Half Life 2 was originally shipped in 2004, and although the SSE instruction set existed, it wasn't yet ubiquitous, so most of HL2 was compiled to use the older 8087 or x87 maths instruction set. That has a wacky grab-bag of precisions - some things are 32-bit, some are 64-bit, some are 80-bit, and exactly which precision you get in which bits of code is somewhat arcane.
But ten years later in 2013, SSE had been standard in all x86 CPUs for a while - the OS depended on it being there, so you could rely on it. So of course by default the compilers use it - in fact you have to go out of your way to make them emit the old (slightly slower) x87 code. SSE uses a much more well-defined precision of either 32 or 64 bit according to what the code asks for - it's much more predictable.

So problem solved, right? 80 bits of precision means the collision didn't happen, but in 32 bits of precision it does, and that's your problem, more bits better, QED, right? Well not quite.

The guard's toe overlaps in both cases - a few millimeters is still significantly larger than ANY of the possible precisions. In both the SSE and x87 versions, the door hits the guard's toe. So far, both agree.

This collision is actually properly modelled - a big innovation of HL2 was the extensive use of a real physics engine. The door and the guard are both physical objects, both have momentum, they impart an impulse on each other, and although the door hinge is frictionless, the guard's boots have some amount of friction with the floor.
On both versions, the door has just enough momentum to rotate the guard very slightly. The guard's friction on the floor is not quite enough to oppose this, and he rotates a tiny fraction of a degree. On the x87 version, this tiny rotation is enough to move his toe out of the way, the collision is resolved, and the door continues to swing open. All is well.
But on the SSE version, a whole bunch of tiny precisions are very slightly different, and a combination of the friction on the floor and the mass of the objects means the guard still rotates from the collision, but now he rotates very slightly less far.
@TomF That's mental. Almost too realistic.
@TomF ha, that was my assumption when reading the prior posts - either fast-math or x87
@TomF lol it's always floating point precision, isn't it? The recent Sonic 1,2,3 16:9 remakes ditched the old 16.16 fixed point math of the originals for a floating point vector system for collision, and people suddenly say "it's not accurate" when, in fact, it's *more* accurate, just that the original used a ton of hacks and bugs that created bizarre edge cases.
@TomF at this point in the story every cell in my body screamed x87 ahaha
@TomF HL2 confirmed to be haunted. You woke the ghost from its slumber and now it's stuck in VR lol
@TomF
Door stuck!! DOOR STUCK!!!
@TomF this screenshot out of context really goes hard
@TomF So you means stubbing your toe on a door frame hurts like hell *and* breaks games ?

@TomF Brilliant story! I didn't realise you'd worked on this.

HL2 VR on DK1 is how I learnt that vr nausea can last for many hours, and no you absolutely can't push through it.

Totally worth it though!

@TomF oh, also I was fully expecting this story to involve VR locomotion breaking critical path level scripting. Fallout VR was a total nightmare to play because of that.
@Farbs It is how we learned it, too! We put about 30 Valve people through a battery of questions before and after playing TF2 in DK1 for a fixed amount of time. I did all the interviews, and by the end of the week I asked about "nausea" so many times I'd given myself a Pavlovian response to the word that stayed with me for about 5 years afterwards.
@Farbs @TomF It really didn't help that DK1 was only 60Hz and there was really no good mitigation for input->display latency yet either. But yeah, I'd play for 10 minutes and be sick for an hour or more.
@Felice @Farbs Nah, we did pretty good latency mitigation. The problem was no positional tracking - rotational only. You'd be surprised how important that was - even the centimeter or so of parallax as you rotate your head is really important. I spent a while trying to refine our "neck model" but by then we had the DK2 tracking almost figured out.

@TomF @Farbs Oo, yeah, you're right, of course. I totally forgot DK1 didn't do positional tracking. I remember wishing it could. I mean, it made sense, since motion sensors totally weren't up to the job, all kinds of drift as I recall. Thus lighthouses and now inside-out tracking.

That's good to know. I really haven't dipped my toe back into VR since those days. I assumed it'd be be much better these days because of high refresh and misc mitigations, but that alone suggests it'll be 𝘸𝘢𝘺 better.

@Felice @TomF Yeah, positional tracking made a huge, huge difference even on CV1.

Of course it added a million layers of gameplay headaches too though (what do you do when the player just straight up walks through a wall? How do you balance for different play area sizes etc).

I remember clicking on a video where someone showed off their Space Pirate Trainer score, and they basically just jogged laps around a room the size of a squash court while I was stuck trying not to fully extend my arms.

@Felice @Farbs DK2 was already so much better than DK1. It had positional tracking, 90Hz, low-persistence, far better contrast, and we had done Real Optics rather than dialling in a bunch of magic polynomials by eye. We really knew we'd cracked it then - everything after was fairly small increments.

@TomF I'm still on Quest 2 and FWIW yes those awesome improvements made all the difference between nauseating curio and immersive and fun experience (especially with the touch controllers), but also inside out tracking, no cables, and being a self contained console I can just leave in my living room made all the difference between thing I never get around to and thing I actually use.

I'm still waiting on a killer app tho. A Beat Saber rpg maybe.

@TomF @Felice @Farbs My DK1 had position tracking... since I'm one of the people who stuck a Razer Hydra controller in the headband. :)
@kojack @Felice @Farbs "Now I have two problems" :-)
@TomF Do you know why HL:A doesn’t have melee combat? The very first thing I did when I started playing was pick up an old pipe and try to smack a headcrab. I was a bit disappointed when it didn’t work.

@Nucu No idea, sorry. HL:A was after my time.

My guess is they tried it and it just didn't feel satisfying? I've not seen a melee combat system that worked that well. Doesn't stop people trying (nor should they!). Beat Saber is deliberately NOT that - it's laser beams through jelly cubes :-)

@TomF the difference b/w Half-Life, Fortress & Team Fortress “Unforeseen Consequences: A Half-Life Documentary” <https://youtube.com/watch?v=BQLEW1c-69c>
Unforeseen Consequences: A Half-Life Documentary

YouTube

@TomF for the interested: “Black Mesa: The 16 Year Project to Remake Half-Life”

#NoClip <https://youtube.com/watch?v=G_TcAxAKCAI>

Black Mesa: The 16 Year Project to Remake Half-Life | Noclip Documentary

YouTube

@TomF this also confirms my suspicion that #Valve is "slowly baking products to perfection" cuz it took them 12 years to announce the #SteamFrame...

  • But then again, everyone I know loves the #SteamBeck and noone's weeping a tear for #SmachZ

https://www.youtube.com/watch?v=CBrPTVi-BfQ

STEAM DECK: The Handheld PC Has Finally Arrived

YouTube

@TomF

Thanks for taking the time to write this 

@TomF

That was really fascinating. I'm not a programming person or into game development, and it was still really interesting to hear all about the problem and the process.

@TomF @JoelFromNYC check out this thread.
@aburtch
Wow, what a journey.
@TomF wow amazing story haha
@TomF ah right, the eternal lesson “but the code is the same!” — well, the compiler is not! (and in this case, parts of ISA are not the same either)
@TomF сс @nillerusr you definitely know what they're talking about :)
@TomF thank you! Very very interesting! Bug hunting can be highly challenging.

@TomF i really enjoyed this thread which feels kind of @foone problems (always use the right legacy compiler lol).

It also sheds good light on how software development works in general, at least as far as I experienced it over the last decades. And with a great story too!

Good times have been had

@TomF
Hands down one of the most interesting threads I've ever read on the Fedi 😁
@TomF heh, in the beginning I thought You're going to talk about the bug which is favored by plentybof speedrunners of HalfLife. The ones which add health instead of substracting on damage :)))