Archive:
There’s a class of work that I very much reserve for days where I’m a bit tired, maybe hungover, and definitely not firing on all cylinders. Bug fixes, UI, some scaffold thing that’s a bit boring, achievements, stuff like that. I wasn’t feeling particularly awake this morning because we had a slightly boozy weekend visiting Neil and the team at the Retro Man Cave – which was excellent, by the way, highly recommend it – and trying not to get Wham’d, but it ended up being a surprisingly productive day… after a few coffees.
I added a Vertical Sync option to the settings screen, and pause screens to each of the mini-games – a slightly bigger job than I anticipated because they’re plug-ins, and needed their own code path to save the audio values – and then flashed my Switch dev kit to the latest firmware and did a bit of testing.
I had a brief look at Nintendo’s master submission list, and UE 5.4.4 is using a version of the SDK that’s going to fall off the list at the end of the year. I'll have to apply for a waiver when we submit, or bounce up to a new version of the engine. The latter might be worth doing, as I’ll get whatever improvements Epic made to the mobile renderer, but I’m still on the fence.
Performance in handheld mode is right on the margin. If I lower the internal resolution to 70% and let the up-scaler do its thing, Moonbas and Sandy’s hit a solid 30fps, bar the odd room. Willy’s is going to need some hacks, as that’s frequently down at 20.
The two point directional lighting is on all the time in Willy’s, even though most of the rooms have shadow planes to fake being indoors. I keep the main light on because it’s lighting the clouds, and once the camera’s unlocked, they’re visible. So I think the solution may be to add something to the Room Controller
class to indicate if a room’s indoors, then (on the Switch) fade out the exterior lighting when it’s not needed. The clouds aren’t rendered on the Switch, so bar a change of colour to the lower-hemisphere, no one will be missing much. Whilst I was poking about I turned off grass, bloom and ambient occlusion. You can’t really see them on that little screen. (Must remember to turn AO back on when the Switch is docked, though).
Another weird thing, I swear the character controller moves differently on the Switch. It doesn’t jump as high, and it feels a smidge slower. A couple of the rooms are way harder to do, which isn’t good.
Couldn’t stop myself, decided to tackle the perf issues on Switch. It wasn’t as simple as knocking out the directional lights while indoors, although that helped. After flicking through the various stat
screens, WorldTicks
was way larger than I expected, to the point of looking broken; CPU and GPU were both close to a frame. I had a scroll through dumpticks
– a nice debug command that spits out everything registered to Tick
, in a nice CSV format – and noticed a couple of things that were ticking when they shouldn’t. Easy fix, but the rest looked fine, so there weren’t any CPU hogs in there. But… there were an awful lot of Niagara particle systems registered. One for each paint pick-up, plus torches, and god knows what else. So I culled the Niagara systems from the paint pickups, tweaked all the max/min render distances of the interior spot-lights, and that was enough. Willy’s is bobbling along at 30fps.
A few rooms are dipping into the 20s, but I’m 100% sure there’s going to be a room-specific fix for each of those, I just need to play through and special case some things, which I can do after content complete.
And yeah. I’m 100% convinced that the character controller is moving more slowly, so I’ll have to add a hack to speed that up on the Switch. FFS.
Went to the gym and my car broke down, so the afternoon & evening were written off, trying to get it to a garage. FFS!
There was a hell of a storm this morning, which (aided by the cat) woke me up at 5am. By 6am I was chasing our recycling down the road, and by 7am I’d lost the will to live. So, today’s not been the best of days. I did add the last room to Moonbas, but it wasn’t the Paradroid styled thing I was going for. That ended up looking rubbish, probably due to my complete lack of sleep... Oh well, no point forcing it.
I do love these Spectrum stripes, though.
So much so, I added an Amstrad stripe to the Toaster Robot room, as well :D
I tried to make a start on the missing puzzle, after the Chimera section, but honestly, I was useless today. I’ve never been a morning person.
The missing puzzle turned out to be one of the most interesting things, from a code point of view, that I’ve ever made. The idea’s simple, there’s electricity coming in at one end of the room, and you have to route it via 9 rotating floor panels, to the other end of the room. To keep things simple, the floor panels can route the electric to one (or more) of the four cardinal compass directions (although, internally, I could pretty easily handle more outputs).
**IMAGE
I use a 4bit bitmask to define the path the electricity can take (North, East, South, West) and as the player rotates the panel, I rotate the bits in the mask.
I use another 4bit mask to indicate if the panel has a permanent input of electricity – from the wall in the room – and a third 4bit mask to indicate if it’s connected to an output – the wire on the other side of the room – a quick bit comparison of these three masks handles the fixed / input output cases for the puzzle.
If the panel is rotated, it’ll check for power from the fixed point, and it’ll ask its neighbours if they’re currently powered up. If either is true, it’ll check to see if the two paths connect, and then power up and down accordingly. Far from optimal in terms of how many checks the panels might end up doing between each other, but very clean and readable from a code point of view.
There was a little wrinkle. It’s possible to create orphaned panels – two or more panels that received power, but were no longer connected to input from the wall – and they’d power each other, indefinitely.
I didn’t want special-case code for panels that were connected to the input, and I didn’t want the panels to walk back, along every possible path, to see if their connection was valid. Instead, when a panel is rotated, it broadcasts a message through the GameplayMessage
subsystem telling all the panels to power down. This happens internally, and nothing is updated in the world. When the panel finishes rotating, it broadcasts again, and all the panels check to see if they’re connected, via the wall or their neighbour. It doesn’t matter which order these checks happen; eventually the panel connected to the wall realises that it has power, tells it neighbours, who tell their neighbours, who tell their neighbours... No more orphans.
Again, nowhere near optimal in terms of the number of calls, but me likey the code very much. It was one of those programming things where a bunch of small steps built-up into something nice. A fun few hours.
Annnd TIL that Unreal treats bitmasks as first class citizens. There’s a specific UPROPERTY
definition for them, and they appear in the editor as a nice dropdown. I can’t believe I didn’t know that! I love a good bitmask! My game state is a collection of bitmasks, as is the save game (I never serialise objects), but I’ve never exposed them to the editor in this way. Every day’s a school day. :)
Ah, turns out that UE 5.4.4’s Playstation SDK is no longer on the submissions list, either. So I’m doing it: jumping to 5.5.1…
CPU go Brrrrr.
No code changes required on my end, which was nice (but not unexpected, it’s very rare UE breaks my stuff during an upgrade), but I need to do a full test.
Made a build for all the skus – no catastrophes – and sat in front of the big telly for a 100% run. It’s the first time I’ve done a full run since I made the flow changes to Willy’s and Moonbas, and I’m a lot happier with it now. There’s far less traipsing through rooms that you’ve already seen… if you know where you’re going. But no one will when the first play, so I need to think about leaving a few more clues.
A full run took me 2.5 hours, which was a bit of a surprise. I could 100% the first game in 50 minutes, so this might end up being close to three hours by the time I finish off Sandy’s… I’m sooo not looking forward to that intermittent bug that only appears 2 hours in… Fingers crossed.
Found a lot of minor aesthetic / tweakie bugs, yesterday, and a couple of big ones. Smashed through all the simple bits and bobs, added some missing audio, changed the layout of the pause screen, updated the credits page to include Epic’s copyright line and a column for whoever does the PlayStation port. Couldn’t be arsed to do a full day, so stopped at 2pm and called it; It’s official Christmas.
Friends:
If you like any of my work, please consider checking out some of the fantastic games made by the following super talented people: