“Hi, my name is Stefan and I’m a senior game programmer based in Stockholm, Sweden, focusing mostly on gameplay, tools and shaders.
You can find all of my work samples here, there’s a CV page for all that serious stuff and an About page if you want to know more about me.
Welcome!”
Releases
GORN 2
GORN 2 is an extremely violent (and funny) gladiator game in VR, and the sequel to one of the best-selling VR games of all time. This was an absolute dream project to work on and I learned so, so much about reactive programming, dependency injection, physics and more! It also has mod support!
Unique Kills Crowdpleaser
Ranged Weapons
We had a system in place that I had developed earlier called DamageContext, which would allow us to glean information about a damage event:
- A weapon has an attached DamageContext component and things the DamageContext needs to be aware of:
- Colliders (even a regular collider, like the handle, can cause impact damage)
- Damage-causing components (like Piercing, used for arrowheads)
- When a body part impacts a collider, we check if the collider is associated with a DamageContext
- The body part may also receive damage events from components like Piercing, and these carry a refernce to the DamageContext
- The body part can then retrieve information from DamageContext like, “is the weapon this is attached to held by anyone, or was it recently held by anyone?”
- The weapon itself can also listen to its DamageContext to receive information about the damage events it was involved in, like “did I manage to kill anyone?”
My starting point was here then, creating a script that could listen to OnKill events and use DamageContext to figure out if the player was holding the weapon. Except, when I tested it the accuracy was terrible - unusable, even! It turned out that when the player strikes an enemy, it’s often just as likely that what actually kills them is the enemy hitting their head against the wall, poking themselves with their own sword, falling off a platform or suffering any of a myriad of other horrible fates. The solution then, is not to try to figure out if the player is technically responsible, but whether or not they're liable to *think* they're techincally responsible!
I created a system called DeathBlameHandler that kept a history of recent damage events; instead of directly telling DamageContext it scored a kill, when an enemy dies, the system goes through the history to check if any of the recent events were associated with the player, and if so, uses that as the death-causing event and reports it to that events associated DamageContext!
This worked great, as you can see in the video! When I kill someone using a new weapon, a new box is ticked on the wall, but when I re-use a weapon, it does not. There are times when it feels a bit too generous, but I would rather the player feel they were treated unfairly in the positive sense than the negative.
UNREAL
As part of an online course in Unreal Engine 5 (C++), we made this third-person shooter game. The assets and the scene itself was made by someone at Epic, but as part of the course I set up the animations, created a basic combat system, win/lose state, AI and more. After completing the course, I added some additional features to the project, which you can see below.
Patrol System
I did this by creating a PatrolPath blueprint that uses a USplineComponent to define the path. I then created a Patrol node to use in the AI behavior tree, which is assigned a PatrolPath Actor; if the NPC is too far off the path, the AI will pathfind to the closest point on the Spline; if the NPC is on the path, the AI will pathfind to a point slightly further ahead on the Spline.
Investigation System
Having the NPCs pathfind randomly didn't look natural at all, so I created an Actor called InvestigationPoint that I could hand-place throughout the scene. Each InvestigationPoint can contain references to other InvestigationPoints, so when an NPC loses sight of the player for too long, it takes the last known player position, pathfinds and moves to the closest InvestigationPoint, waits, then proceeds to a random unvisited InvestigationPoint referenced by the last one. If no references exist, it picks the closest unvisited one. This worked a lot better!
UNTITLED PROJECT
This is my private project that I worked on in my spare-time for a few years. The original goal was to make a space-station simulation game, and I wanted the player to be able to create an indoor environment with as few restrictions as possible (while still keeping it as a normal, uniform grid for my own sanity’s sake).
In the end, I didn’t get to the other parts of the game and had to make a lot of compromises, but I think the result - while not completely finished - still turned out pretty nice. I’ve written some stuff about the more interesting features below.
Fluid Simulation
What started out as part of another project later just ended up becoming a fun exercise in compute shaders and multi-threading! I found an old implementation of smooth-particle hydrodynamics in Java which I rewrote to C#, then converted to HLSL after learning how to use compute shaders.
Below you can see some of my progress; from a basic implementation with a pseudo-temperature system, to a much larger scale simulation, to a final version with support for solids.
Lootbox Worktest
This was for a worktest I did for a position as a Tech Artist. The assignment was to create a scene where a lootbox appears, the player opens it, is presented with the contents and then you can choose to reload the scene. Preferably with some unique setting, so, I chose space!















