A tank for the job of a bike (AKA what not to do when coding)

This post is about a spawn algorithm for the light berries in the game. But, in this post, I will be focusing on the things I did wrong, things that should NOT be done. I will mention why I did it, why I shouldn’t have, and what I could have done.

What happened with this algorithm is similar to this: to do the job of a bike, I tried to build a tank. And to build a tank, I started by building a piece of the tank, which then gets destroyed to remake the proper piece, instead of, well, building a tank from the start. Or even better, build a bike, which was all that was necessary. Oh, and, the result of the whole process wasn’t a good tank, it was one with a gigantic hole in it! So, yea, generally not a good idea to do this.

So here’s what I did. I made an algorithm that stores all the spawn points of the berries in Vector3 (Vector3 because it is required for the instantiate function) with z co-ordinates set to 0 (because it’s a 2D game). Then, I add these to a list. Each time a berry spawns, that point is removed from the list (did I mention how awesome the lists in Unity are?). Each time a berry gets picked, the co-ordinates gets re-added to the list. This time, the list is public static, so it can be accessed and edited from other functions. Static can be used here because there is only need for one list of berry positions. The berry respawn timer and maximum number that can spawn at a time can be changed through Unity with a public editor. While this seems like a simple way to do it, there are several problems with it. Mainly, all the values are hard-coded. So others (even programmers, since they are unfamiliar with my code) will have trouble editing it. But more importantly, any edits to the map, from a tree being moved 0.1 units to a new enemy being added, will most probably make the code unusable. The berry would spawn in the wrong position! Which actually did happen. Twice. I had to find and hard-code 15 to 20 berries, about three times! Now that’s inefficient.

So what I did to ‘fix’ this, is make a new prefab berry sprite (with all the scripts from the berry removed) and a different tag on it. These berries would be scanned for at the start for their positions. The positions get added to the list and the berries would be destroyed. The new prefab was because I didn’t want the actual berries in the scene at start (they had scripts on them) and then randomly destroy and re-add them. So what did I do wrong. For starters, if you are going to have a script manager with a script that searches for different objects in the game, do not put Destroy(this.gameObject); there, it will destroy the script manager itself. I repeat, do NOT destroy the script manager, it could be really bad for the game (and cause potential calls from annoyed team members who can’t figure out why the game  suddenly has an instant win condition)!

What should I have done here? Well for one thing, NOT DELETE THE SCRIPT MANAGER. Use the correct object from the iterator in the list, such as Destroy(berryPoint.gameObject); instead of Destroy(this.gameObject);. For another, I should have realized that the berry prefabs could in fact be added from the start with very little re-factoring. They didn’t even need to be deleted, they would just remain there until they are picked or broken, at which time they will be added correctly to the list. The scripts on the berries probably would not have interfered with anything either!

The pictures below show what the game looked like before and after the errors were fixed. The golden circle is the what you fly into to finish the game, and it should only spawn after all the children (the count should be displayed in the UI) have been found. But all these and more were controlled by the script manager which got deleted (I feel like I keep coming back to this one) by the broken code.

broken
What it actually looked like
working
What it should have looked like

So, to conclude, even though a series of temporary fixes can get things done, it might eventually lead to an inefficient code. While sometimes these are necessary, it is usually better to try to make the best code for the situation from the start (if possible), and at each modification. Don’t make a tank where a bike is enough and most assuredly, don’t make a tank which blows up in your face.

2 thoughts on “A tank for the job of a bike (AKA what not to do when coding)

  1. Greetings!

    All in all great work in explaining the entirety of the little adventure you had in making the light berries and how you (eventually)worked it out with the spawning positions and algorithm.

    I find the contents very easy to understand with how you explained exactly what went wrong in your process and how you tried to fix it. The use of examples like the tank & bike was a good one as well. You’re good at keeping it interesting throughout the post with a mix of humor and you wrap it up just nicely in your conclusion in the end of the post.

    I also have to say I can really relate. I wish I too had thought about this before I started programming on this project. Not making temporary fixes as well as simpler solutions are really the way to go if you want a functional product in the end of the day.

    Like

Leave a comment