DEV Community

Cover image for Dev diary 1: A first attempt into gamedev and C#
MaxP
MaxP

Posted on • Updated on

Dev diary 1: A first attempt into gamedev and C#

Dear diary, here I will log my progress and thoughts on how I deal with this small project. No guarantees that i'll finish it or get to a playable state. But it will be fun to read it in a few years. And maybe someone will find it worth reading.

Intro

What's the game about?

No idea, let's build something generic for starters and then bother with the game design. Main focus is on the technical aspect, how do I design the data structures, what are the abstractions, how do I keep it simple, etc. In short - lets get some hands on experience.

Initial requirements

  • Single player - let's keep it grounded, I am working solo on this and building the next MMO is not an option. Though it would be nice to write code in a way that would not make that impossible.

  • 3D graphics - the visuals are not something I am aiming for. Most models will be primitive meshes. For now we will use our imagination :)

  • Unity and C# - I will be building the project in Unity but I want keep the option of switching the game engine by relying less on the engine features. This is why I will be separating the code into two parts: Game logic and Engine logic. The engine will be used as a front-end, rendering the objects based on the game logic state.

  • Structure over design - First I want to architect the base of the game to be easy to maintain and extend with features. Some of the code will be over-engineered, some of it will be simple. The goal is to get more experience and log the though process behind each solution.

  • Fantasy RPG with magic things - That's it for now. Let's keep this in mind and write code expecting future features like movement, teleports, melee and range combat, area-of-attack effects, targeted spell casting with obstacles. The initial vision almost never matches with the final result, so let's keep it open for future inspiration.

Who? Why?

I am a backend engineer professionally. Had my share of years working with Android, doing libraries and firmware. Kotlin is something I enjoy working with and Rust has taught me multiple things on performance. I have no prior experience in C# or Unity.
But the desire to make games and create fictional interactive worlds - that's what has led me into the tech space years ago.

Getting into it

Where do I start?

Skipping the project setup and minor configurations, as of now I think the best first step is to architect how do I represent the game map.

As I do not want to make the game restricted to Unity, entirely based on its collisions and physics - I will try to replace that with my own restricted implementation.
Another reason is the possibility that the map will be randomly generated, maybe it will hardcoded, maybe both. So lets build the map representation from scratch. But first we need to think of the use case.

Depiction of how the map might work

The game will have collisions with static objects such as walls, decorations, doors. A multi layered map also would be desired, expanding the options of level design to bridges, wall walks, etc. Without the jump or fall mechanics.

So I see several options on how to represent that:

  • Grid based - a 2D matrix of models which describe each node, for example if it is passable or not, speed of movement, special effects. The performance of this solution should be quite good and easy to scale by segmenting. The drawbacks are:

    • this introduces a minimum size of (1x1) on the map. Depending on the scale the user might feel the rectangular routes in the movements.
    • no option to rotate the collision bounds.
    • additional complexity of rounded values on cell borders.
  • Polygon based - this is similar to implementing collisions via Unity components in 2D. The idea is to move polygons and check for their intersections, limiting the movement based on that. Also there is no need to perform complex mesh collisions, a character for example could be represented as a circle on a plane. This is a very agile solution, allowing for various cool game mechanics. Drawbacks:

    • it could get computationally expensive, especially if done wrong.
    • making seamless transitions between layers adds complexity.
  • Mixing polygon and grid based solutions - inspired by Youtube - Sebastian Lague, a great video about ray tracing. I could apply a similar principle to group lines into sectors, while moving through a sector only a part of lines would be checked for intersections, thus optimising the algorithm.

  • For sure other options do exist, I just do not know of them.

Attempt 1. Grid

At first i've implemented the grid based solution with some modifications.

Grid map with a multilayered structure

The map is a vertical stack of layers, where each layer is a 2D matrix. Any node can be null meaning there is no passage at all. Also nodes point to neighbouring nodes or to null, representing if there is a connection or not. It also can point to a different layer, which I will call a cross-layer-link for now.

Grid map test scene

This is a test map with two sections connected by a "bridge". The entity that describes the map state is part of the "game logic", while a separate custom component is responsible for reading that state and drawing the map layout. Debug.Draw is used to visualise the layout.

Syncing player position with environment

Adding some meshes mirroring the layout and performing a Raycast below the character (to calculate the elevation), creates the effect of walking on top of the map. This is part of the "engine logic", the player component pulls the position of its counterpart in the "game logic" and changes the transform per frame.

Next is implementing the grid traversal algorithm to find which cells are in the path of movement. This way the character will be restricted to only the allowed cells.

Path traversal

Image above shows the result of traversal from point (0,0) to the current player position. This will be used to check the path from old position to the new player position and find any obstacles.

Though I did my own implementation, a good reference is this Youtube - Super Fast Ray Casting by javidx9

There was/is an issue of finding the cell index from the current position when reaching a border. For example imagine that cell (0,0) is a valid passage while cell (1,0) is not. If I set the current float position to (1.0, 0.0) - this can be an ambiguous position.
As a workaround an epsilon value is used to clamp the float position.

Attempt 2. Mixed

Mixed map structure 1

In the next post I am planning to attempt this solution and compare it to the grid approach.

Additional notes

Camera movement and controls

I've decided to handle most inputs via one manager object. This object has a fixed update method to check if any keys have been pressed. Based on that a simple gesture detection was implemented, which then allowed for smooth camera control along the z axis.
A custom camera component reads from a global state the angle of the camera and adjusts the rotation properly around the player character.
User input for movement is also rotated by that angle, allowing for movement in the direction of the camera.

PS

Feel free to leave suggestions, you have my thanks!

Edit: Part 2

Top comments (0)