Week 2: Let There Be Lights

I spent six hours developing an interaction framework... to turn off a light.

Control panel that controls the lights in the cabin, currently hovered over by the user so that a strong orange outline appears around the panel.
Press me!

Welcome to indie game dev, where any task can become an perilous adventure. This week's goal was straightforward: make interactive systems. Click a switch, turn off a light. How hard could it be?

Twelve hours later, I'd built a complete interaction system with raycast detection, blueprint interfaces, post-process material highlighting, and somehow punched holes in the fabric of reality itself. And yes, at the end of it all, I can turn off a light.

The Plan

My Week 2 checklist was innocent enough:

  • Add a movement system so I can be in the ship
  • Create some sort of system to identify things you can interact with
  • Build basic panel opening/closing mechanics
  • Create simple item pickups

I figured I'd start small. Make a light switch. Use a pre-made asset. Just wire it up. This should be eaaaaasy. Unreal had other ideas.

Building the Foundation

First, I needed a character controller so I could walk around the ship. Easy enough. I stole the FirstPersonCharacter from UE5's First Person template and made a few adjustments so I wouldn't get stuck between console panels. Just a few minutes of migrating the assets from one project to another and I was able to move around the cabin.

Then came interaction detection. I set up a periodic raycast to check what the player is looking at. When it hits something interactable, that object gets highlighted with a glowing outline. Fortunately this was a thing I'd done before: I set up a post-process material that could render objects to the Custom Depth buffer. It took a minute to remember the hiccups: Unreal likes to convert some Vector4s to Vector3s silently, for example. But still, easy enough.

Light Switch

I had a control panel in the scene already as well as some ceiling lights from my asset pack and decided these would be my test subjects: make the switch interactable and use that interaction to change a material parameter in the lighting panel's material.

Just one problem. The material was built using Unreal's Material Layer system. I kept trying to set the parameter but each time Unreal would say "sure thing boss" only to silently set some other parameter I didn't even know existed.

Hours of "why isn't this working" later, I found an old forum post someone had about how to set parameters on layered materials and I had my answer. Five more minutes, click. Lights off. Click. Lights on. Victory!

Picture of inside of ship cabin with all lights off. The stars of space shine through the front glass, and panel lights are visible on the chairs whose outlines are only dim silhouettes.
It's hard to explain, but this is a significant technological achievement.

Fuses

But I wasn't going to stop there. Running Late needs panels to open, components to grab. I needed pickup mechanics.

I decided to throw in a fusebox that the player can open, with fuses to pick up and plug into empty slots. Some of the interaction system from the light switch should carry over, but a bunch of new challenges arose. First, the fusebox needed multiple interaction zones: one for the door, one for the empty fuse slot. I extended my interaction interface to handle hit components, so the system could tell which part of an object you're clicking on. I animated the door with a Timeline. Everything was working.

Then came the pickup system. When you interact with a loose fuse, it adds it to your inventory and attaches the model to your camera so you can move around with the fuse. Now I just needed to be able to plug it in.

Fusebox on interior wall, next to airlock door with lighting inset into the door. The lights from the door create enough light to see the fusebox.
The fusebox has lighting from the door lights on the left so you can find it in the dark.

The Cosmic Void

The immediate issue now was that I can outline an object but I don' have a way to outline invisible objects. I'm sure there must be one, but translucent materials don't write to the Custom Depth buffer, so they can't be outlined with the post-process material I have. Masked materials with zero opacity don't render either. I banged my head against the editor.

Finally, at 3 AM, I discovered a hack: an unlit masked material with black emissive color and full opacity mask. This creates what I can only describe as holes punched in the universe. Inky black voids that still render to the depth buffer and can be outlined. When you hover over an "empty" slot, you see the glowing outline of the void. When you place the fuse, the void material swaps to a normal fuse material, and it looks like you actually inserted something real.

Fuse with non-fuse material applied, such that it looks like a void where space has been punched through and all one can see is the darkness of the end of all things.
It's so weirrrrd...

It's cursed, but it works. Good enough!

The Full Loop

By the end of Week 2, I had a complete repair interaction:

  • Open the fusebox
  • Pick up a fuse
  • Hover over an empty slot
  • Interact to place the fuse

This is the beginning of the core concept of the game. Something breaks, you scour the ship for parts, and you try to get it to work. Will there be jumper cables that let you put a solid wire where a fuse should go? Maybe!

This week might sound like technical overkill for simple interactions, but it's an important basis for the whole game.

Next Up

Week 3 is about fleshing out the first full system: Oxygen. Clogged filters, O2 tracking, the works. Time to put this interaction framework through its paces.