Project 1935 Devlog #2
(Originally written on 25th May @ indiedb)
Okay, so many moons later, here is devlog #2. The reason it took me so long is simply because I didn’t do that much work, only working here and there in bits due to exams and having to travel so I waited a little longer until I amassed enough work done to produce a devlog. From here on out though, I will be doing a devlog every Thursday whether I have enough work or not, as I really have no excuse because exams are finished.
Another note, devlog #3 onwards will be much more structured as I aim to do the devlog as I actually work, whereas with this devlog I looked at my changes at the very end and compiled them all together, meaning I may have forgot the intricacies of some things.
Anyway, onto the good stuff!
The Unit
I wanted to approach this game from an object oriented point of view from the very beginning and even though my C# skills aren’t the best, I have had experience with it before despite never actually finishing a game (until a recent game jam) and so I set out to create base classes similar to how you would see within C# when used outside of unity. One usage of this being the units. All units will have similar functionality, really the only thing changing between units would be their stats, due to this it is obvious that a unit class should exist, and then every unit inherit from that class.
Following this idea, I created a unit.cs class that will have all the functionality that cannot be changed by inheriting classes, the only thing that can be changed are stats such as movement speed, strength etc. First of all, the movement, this is quite simple right now as I only need a rudimentary movement system that will help when testing networking, this works by passing in a destination and then using Vector3.MoveTowards until it reaches that destination, slowed down using Time.deltaTime.
I made this work by activating a temporary UI that allows a pin to be placed on the map somewhere, the unit will then move towards that pin.
Now that the movement code was out of the way, I needed to add in now, instead of later, the ability to restrict access to units. As this will be a multiplayer game where strategy and diplomacy are involved, I don’t want every single unit on the map to be visible to every single player in the game. Therefore I created, on the base unit class, an access matrix, this uses simple booleans, but in the future those booleans can be checked and restrictions put into place.
The access is set based on the nation being played as, and the parent nation the unit belongs to. Both of these attributes are controlled via a Nation enum, and everything in the game that belongs to someone, will have a parent nation, if the nation of the client and the nation of the unit match, all access is given. This is flexible, say, in a situation where an ally would like to see your units, access can be changed to show that said nation can see the units, but cannot interact with them etc.
With the base unit pretty much in place, I needed to test it via inheritance. So was born the version 1 infantry unit.
*Mind the art, not quite a modern day picasso.
Everything worked, including the movement.
Although it was worth considering something very important. The base unit class utilised the Monobehaviour functions Start() and Update(). Now suppose I wanted to inherit from the base unit class, but on my inherited class, I wanted something to occur in Update() or Start(), this would break my class because it would overwrite the base units Monobehaviour functionality, which obviously does things fundamental to the unit itself.
The solution was to not use Monobehaviour functions on the base class, rather only on the inherited class and then call the base classes functions inside of the inherited classes Monobehaviour functions. If that sounds like a riddle, don’t worry, it is as simple as having a unitStart() and a unitUpdate() on the base class, and calling them in Start() and Update() on the inherited class. This solves the issue and allows for flexibility, although I assume there is a much better way of doing this!
The Camera
Up until this point, I had forgotten that the camera needed to be implemented, it would be a pretty stale experience without it. The idea was pretty simple, you drag the camera around with your right mouse button, and you zoom in and out by using the scroll wheel, working much like a mobile phone with movement going the opposite way.
I got the aforementioned idea working pretty easily, the only problem being that the camera jumped around when you started scrolling, in hindsight it was a really easy fix, but it had me pulling my hair out for a good hour at least. In the initial version, of which I have no gif :(, I moved the camera position away from the current mouse position, this resulted in the jerkiness as I never saved the mouse position. In the fixed version, I got the mouse position when the right mouse button was clicked and then saved it.
Now knowing where the mouse position started, I have the origin of the drag point, this meant I could simply move the camera to the current mouse position minus the first mouse position as long as the right mouse button was held down.
Zooming fortunately didn’t result in a self-inflicted headache, as all that occurred was I changed the size of the camera every time the mouse wheel was scrolling up or down.
The second to last change for the camera controls were to restrict going too far up, down, left or right and making sure that the size of the camera never went below a threshold (as the camera would flip) or never above a threshold as the map would be too small to see. This was quite simple.
The end result being:
The very final change for the camera controls were to, at the start of the game, pan the camera to the nation currently being played as. So, I needed to first find out which nation was being played, I already had this data in the form of a Nation enum mentioned earlier, second I needed to find out which Transform in the world map related to that enum. So on the GameManager I grabbed all of the children belonging to the WorldMap game object in the hierarchy, this contained all of the current nations.
I then needed to store the Transforms of those children inside of an array so that their index can be checked against the enum, and then that position be passed into the camera controls as the position the camera should be panned at on game start.
The checking looks something like this, as the Transforms were returned in the order they are in the unity inspector.
The UI
Let me say this before you read any further, my mind is not a creative one, I cannot design anything to save my life. With that out in the open, here is the ‘concept’ UI I came up with, which will most definitely change:
I planned on having a UI that is always on screen and that shows key information about your nation such as the resources it is gaining, the money it has etc. I did not plan on this being the only UI though, and therefore the code I wrote (which is still messy), should accommodate different UIs and the values that need to be updated on them.
I tried my best to create a modular script, one that can be changed and will not break much of anything, hopefully.
This is done using an UpdateValue() function, when called, it takes a value that needs updating, this should be the actual data representation of a UI element, it takes a value by which to update the previous value and then a string which specifies which UI to update. This is important as most UIs will have similar UI elements, the overall persistent UI has happiness, and then the resources, but then so does the province UI. These values should be able to be updated without rewriting code.
Province Management
This part is the final part, and ties in with the previous UI section.
Here I created a project management screen that should show when you click on a province you own. Before anything, I mocked up what I believed it should be designed like, this is also subject to change.
Using some raycasting and province points I figured out when a province had been clicked, and then when it had, opened the province management UI and raised the province that had been clicked slightly.
The goal is to have it so that only one project management screen actually exists, and the data on that screen is updated depending upon which province has been clicked, up until the replacing the data part, all of that functionality is present in the form of a C# object.
Now before using a C# object, I was using Lists. There was a list that contained all of the province’s transforms, and the functionality shown above did work. I had the problem though, of, province data and the province transform aren’t related so how would I know to show the data associated with York when York was clicked? My initial idea was to have each data element (happiness, economy, food etc) be a part of a list and the index of each value in that list was the same as the index of each province transform in the province list, therefore if Province[3] was opened and we wanted it’s data we could simply go Happiness[3], Economy[3] etc. This would work, but it would require a lot of lists, assuming I stored the values by which each province’s values were updated every so often, it would soon become unwieldy.
The solution was to use a C# object. It would store all of the data associated with a province, as well as its transform and then where the provinces transform list was before, I can just store a list of all Province objects. This was much cleaner, maintainable and it meant that when adding or removing provinces from a nation’s list, it will take all of its data with it.
Thanks for reading my second devlog, hopefully the content here was better than in my last devlog as I have actually done some work this time! If you have any questions about how I did something, or want me to go into more detail, just ask away as I know I have undoubtedly explained something in a less than ideal way. Also, if you think I am doing something in a roundabout way, please give me suggestions as I am an inexperienced programmer and would really appreciate any sense of direction :D.
0 comments