I spent 3 weeks of evenings and weekends building a tower defense game using the BFS / realm rush project as a starting point. It was a tough experience but well worth it.
I played with blender in the past, but I have given up trying to be both and artist and a coder So I mostly used lots of Synty Studios assets, and my favorite weapons asset Sci-Fi Arsenal by Archanor VFX.
Blending the path finding and the tower factory code was very difficult for me. I ended up rewriting it several times, and added two way travel to the paths required for picking the right road prefabs. In the end I ended up with an abstract CubeFactory for roads, footpaths, and towers.
I am still trying to fully understand SOLID principals and other coding best practices. So I fell back to single responsibility and keeping things as contained as possible.
Donât make anything public unless you have to. Benâs âSerializeFieldâ technique is great for this. I donât see many other instructors teaching this.
When things do talk to each other consider the dependencies carefully. For the complex chatty parts I used a centralized GameEvent class. For the simple and useful I used other singletons.
e.g. Lots of objects are interested in enemyâs being hit so the Enemy calls BroadcastEnemyHit method, and lots of classes subscribing to the âonEnemyHitâ event:
GameEvent code for the event:
public delegate void OnEnemyHit(int hitAmount);
public event OnEnemyHit onEnemyHit;
public void BroadcastEnemyHit(int hitAmount)
{
onEnemyHit?.Invoke(hitAmount);
}
Amazing game, just one issue, donât know if itâs my browserâs fault, but the game crashes at wave 13th (It crashed twice in the exact same point). A downloadable version would be great to avoid WebGL issues.
On coding:
Why lots of objects are interested in enemyâs being hit? I donât get it, I didnât see anything changing drastically other than a user score, not saying is a bad thing, but calling an event every hit might not be efficient, there are easier, simpler ways to do this, like using Scriptable Objects for each wave, Scriptable Objects can hold data that can be modify by other objects pretty easily, making the game far more efficient code wise, but I donât remember if youâll learn about those in the 3D course.
Avoid using singletons, they are considered bad practice for a lot of people, I once even got yelled during a jam for using one, it was kinda funny to be honest, people sometimes get pretty intense about bad practices in coding.
âBenâs âSerializeFieldâ technique is great for this. I donât see many other instructors teaching this.â
Yeah, I donât know why even Unityâs tutorials use Public all the time instead of SerializeField.
Thanks for taking the time to give great feedback Yee.
Wave 13 introduces Taxis, it might be something to do with the asset. Do you know what browser and version you were using? I tested the game on several devices, but to be honest it was only on Chrome due to its market share. And publishing a game binary sounds like a whole other level of support and distributionâŚ
Do you have any links to the scriptable object technique you were talking about? It would be interesting to check out. I did use them to list prefabs for each wave but nothing beyond that.
It would be great to get the kind of game jam mentor experience you got, and making an effort to stick to coding standards can solve a lot of issues. Code that the entire team can work on without friction can be extremely valuable.
You are right that singletons are kind of hackish - especially as I learn more techniques. But, I still canât help being a fan of the GameEvent singleton + delegate pattern. It acts as a hub that increases code maintainability by orders of magnitude, and I can find any non-obvious dependencies with a simple right click.
The UI singletons on the other hand were pure laziness. UIMessage has 49 references, UISound has 31 references. That is a lot of dependencies to set up for Debug.Log() like functionality.
One pattern I want to explore is a dependency injection like I found in ASP.NET Core tutorials. The startup class marries interfaces and objects together. Each webpage can then use these interfaces as it wishes, e.g. it doesnât matter if it is an in-memory database or a sql database, as long as it has the same methods. A very cool concept for swapping out parts + having a central hub for visibility. In Unity I imagine a spawner could do something similar - giving each object an IAttackable or an IScoreboard to use. Which in turn would reduce singleton dependencies.
As for performance, I know the game isnât the best. Before release when I was using the profiler, I found finding objects by name was taking 20 to 30% of the workload, and switching to finding by tag reduced it to under 1%. Two other big performance hogs I can now revisit are lighting and proper queuing. I have learnt more about light performance, and I have written a solution from the fps project for queuing three projectile objects at once: muzzle flash, bullet, and hit.
Sorry, I have no videos of that, itâs not really a technique but more of a suggestion that any beginner can implement but it already looks like you are an experienced coder, you are by no means a beginner if you are taking about interfaces, and yes, that can certainly avoid dependencies and make everything cleaner.
Iâm using Safari v13.1.1
Itâs easier to handle a Mac and Windows version than a WebGL, this is mainly because webGL is kinda crappy, Iâve seen all sort of games with bugs that donât appear in downloadable versions, you can see it for yourself just with the compile time, it takes almost 10x less times to compile for Windows or Mac. WebGL is super, super, super messy, Unity really needs to fix that.