Entry 71 - New Project

And so, with this post, I am officially beginning the devlog for my new project.

 

Having become thoroughly familiar with the Unity engine during the development of Force of Nature 2, I decided to stick with it for this project as well. At this early stage, implementing fancy graphics, animations, visual effects, or sound design wasn't a priority. To test whether the wall-to-wall movement mechanics actually worked, simple 2D abstractions were more than enough: a circle representing the character and polygons acting as obstacles.

 

Map Editor

To create the maps, I utilized my own custom vector editor, originally developed for FoN2. This tool allows me to draw and edit various shapes, assign tags and metadata to them, and even load raster images to serve as masks. I previously used it to create templates for procedural location generation in Force of Nature 2.

 

Later, while working on a MOBA prototype, I expanded the toolkit to handle the diagonal symmetry often found in that genre. The editor saves data in a custom file format, which is then imported into Unity via specific scripts, converting it into a structure that is easy to work with. I designed the code handling this format to be completely decoupled from the main game logic, so porting it to the new project was effortless.

 

Physics Implementation

As I mentioned in the previous post, the core concept of this project relies heavily on physics – an area of Unity I hadn't actually touched yet. The reason is simple: Force of Nature 2 didn't use it.

 

In that game, all projectiles followed simple parabolic arcs controlled by scripts. Even character collisions – whether with each other or the environment – were handled by custom logic. These systems were ported from the first game, which was built on a custom engine where I wrote everything from scratch. That legacy physics engine was quite rudimentary; it lacked surface friction and couldn't handle interactions between complex shapes, making it unsuitable for this new project.

 

Unity's 2D physics engine turned out to be quite intuitive. The basic setup is quick: assign polygon colliders to the level geometry, circle colliders to the characters, tweak some physics materials, and disable gravity. Since we are working in a top-down 2D plane where height isn't a factor, gravity is unnecessary. Movement works via mouse clicks: clicking applies a single impulse to the character (a ball), launching it toward the cursor. However, getting the character to actually stick to the environment proved to be a significant challenge.

 

In a typical platformer, gravity and friction keep a character grounded. But without gravity, I needed a different mechanism to anchor the character to a platform's edge; otherwise, even the slightest force would send them drifting away. Unity offers a way to link objects called "Joints" (Fixed, Spring, Wheel, etc.). Unfortunately, none of the built-in options allow one object to slide along the surface of another. This was exactly the behavior I required: once the character grabs a wall, they need to be able to move along it.

 

To achieve this, I had to bypass Unity's standard physics and implement a custom solution. When the character touches a wall, they attach to it using a Fixed Joint, but from that point on, I manually control their position via script. I calculate a contour around the wall, offset by a distance equal to the character's radius. The character can then slide freely along this calculated path in response to control inputs.

 

When a jump command is issued, the Joint breaks, and the character is handed back to Unity's physics engine. To ensure the transition between physics-based movement and script-based attachment is seamless, I also calculate the character's movement vector just before impact. I project this vector onto the platform's surface and apply a small, decaying impulse in that direction. This simulates friction, creating the sensation of gradually skidding to a halt against the surface.

  

The "Public IP" Problem

The next hurdle I faced was implementing player-to-player networking. On the surface, multiplayer looks simple: one player sends data to another, and the characters on both screens move in sync. In reality, however, computers on the internet can’t just "reach out and touch" one another. Almost all home devices sit behind so-called private addresses – they are invisible to the outside internet. To be reachable from the outside, a computer needs a Public IP address and an open entry point into the network.

 

Simply put: your computer is hiding behind a router, and other players can't send you anything directly unless you open the "door" yourself.

 

In major titles, specialized network services handle these issues. For example, when I released my previous games on Steam, I relied on Steam's ability to automatically relay data between players through their own servers. Players could connect to each other seamlessly, with Steam handling all the complexity behind the scenes.

 

However, this approach had a downside. During the holidays, when millions of users flooded Steam, their relay servers would get overloaded, and multiplayer performance suffered. Connections would appear and disappear randomly, purely due to the heavy load.

 

For this new game, I don't have access to that Steam "magic" yet, and the test server needs to function on its own. So, for this development phase, I had to set everything up manually:

  • Configure DDNS: This service assigns a constant hostname to my home server, ensuring it can be found even if my ISP changes my IP address.
  • Set up Port Forwarding: This involves configuring the router to open that specific "door," allowing external connections to reach my test server.

Only after doing this was I able to host a server at home that other people could actually connect to. For the actual transmission of data packets, I utilized Unity's built-in networking mechanisms.

 

Resource Gathering

Movement alone – no matter how unique – doesn't make a game. I needed to implement at least a minimal goal for players to compete over. To serve this purpose, I hastily threw together a basic resource collection mechanic:

 

A "spawner" floats lazily across the map, periodically ejecting clusters of resources. These resources come in two colors, corresponding to the opposing teams: the green team must collect green resources, and the red team collects red ones. Collecting a resource nets the team a point. While you can't collect enemy resources, you can knock them away to make the opponent's life more difficult. In addition to resources, the spawner also spits out small bombs; colliding with one sends the player flying and disables their controls for a few seconds.

 

Players primarily move by jumping, which applies an instant velocity vector in the chosen direction. While clinging to a wall allows for slow sliding, jumping remains the fastest way to traverse the map. While airborne, players can also apply a slight force to fine-tune their trajectory – essentially, limited air control.

 

This simple rule set was the first to be implemented. Here is the result – the very first gameplay test of the new project:

 

Unfortunately, the recording frame rate turned out quite low, though the game itself ran smoothly during the session.

 

After playing for a few minutes, we realized that the movement mechanics are actually quite easy to get used to and don't cause any motion sickness or discomfort. However, player interaction felt almost non-existent. To fix this, we decided to deepen the gameplay and introduce combat elements.

Write a comment

Comments: 0