Defend Your Friend

Defend your friend is a co-operative puzzle game where the players have to protect each other using their individual abilities. One player has a shield to block projectiles and reflect beams, while the other has a beam they can use to push away objects and activate mechanisms. Both players need to actively watch each other’s backs to make it through the multiple puzzles and traps, encountered inside the ancient temple they found themselves trapped in

  • Role: AI/Gameplay Programmer
  • Team Size: 12
  • Platforms: PC, PS4
  • Engine: Unreal Engine 4
  • 2015-present
  • Steam

In this project I was a gameplay programmer most of the time. I started with prototyping a lot of gameplay elements such as the camera, player movement, enemies and the lasers. After the base game was working I refined the lasers and AI. I have a more in depth implementation of the lasers here.

Since this is a co-op game, making sure people can play it together is quite important, especially on PC people will not often have 2 controllers to play with. To make sure that these people can still play the game with their friends, we decided to implement online multiplayer. After the initial setup was done using the Unreal subsystems by another team member I made sure everything was working on Steam. The player should be able to, for example, invite other players and be able to communicate with each other using voice or in-game symbol communication.

One of the mayor problems we had was map traveling, Steam doesn’t support the standard non-seamless map traveling method of Unreal engine. In non-seamless traveling the players are disconnected from the server and reconnect when the new map has been loaded. In seamless traveling the players stay connected but are transferred to a transition map until the next level has been loaded. So I had to change how the connection of the players was handled so it would work in seamless traveling. We had different player controllers for the main menu and the game itself which had to be changed because in seamless traveling the main menu controllers were transferred to the game and game player controllers weren’t spawned. So I had the choice to merge the two controller types or spawn game controllers in the game level, transfer over all the data from the main menu controller and then destroy the main menu controller. I did the last one because we decided that we want to have a separate main menu controller.


We needed a pipeline which allowed us to build and test on steam with one mouse click. I made a script which allowed us to update the source to the latest version, build it, upload it to steam and publish it to the test branch. This script was run on a timer and mailed me when a build failed. Developers could also trigger the script themselves. The implementation of steamworks and using the steamworks tools I have a good knowledge about how to work with it.



Implementation of the Laser

The laser was a tricky object to make. Originally my team members asked me to make a base class for each object that can “interact” with a laser with a function the laser can call. For example when a laser hits a button with that base class, the door would open. The biggest problem with this is that in Unreal there are a few kinds of object to inherit from which all have different goals. We had to implement a base class for each of those base objects and check for them all. I proposed a better solution which used c++ multiclassing to create an interface which declares an object laser interactable.


I also created a LaserSpawner, which starts the laser and called it UDyfLaserobject which is also shown in the code example. At the start of each frame the LaserObject spawns a laser by calling AddLaser which spawns the laser, puts it in the drawinglist and checks if it hits a LaserInteractable and calls HitByLaser if it does. When it calls HitByLaser it gives a reference to itself to the object that has been hit. This is useful when it hit’s a mirror for example, now it doesn’t have to spawn a new LaserObject it can just call AddLaser to the original LaserObject.


The image below shows the implementation of ILaserInteractable(image above) in ADyfMirrorBase where the laser gets reflected by the mirror.