Resources and Resource Systems
/Progress on Game #2 marches slowly towards the goal of have a "releasable" product. Not a Steam ready product, but a product ready to tested by others. So much work to do...
In my first game I made the mistake of implementing "feature X" and then "feature Y" only to have to go back and hack the code for "feature Z" into the code base. I had no idea how to make my code easy to use or easy to extend. Simply adding a new building to a menu took hours... Oh the mistakes I made!
In my current project adding a new building to the UI takes approximately 45 seconds.
With game #2 I am trying to build the systems before adding any significant content. I don't expect flawless execution of this, but when I find myself writing code that will only work in one situation or copying code and only changing the value of a string I'm trying to step back and generalize or abstract the code. I'm making better use of getters and setters to keep behavior consistent and spaghetti code to a minimum, more of my variables are private and I'm making (some) use of the delightful world of static classes and static methods.
I have a bit of a man crush going with static methods at the moment.
One of those static classes is a "Helper Function" class that contains static (naturally) methods for things such as finding the nearest gameObject with a given component (good for snapping functionality), or finding the distance to a player or rounding a vector3. Not methods that every class needs, but methods that are needed frequently and all over the code base. I'm learning to do things better. Slowly.
Static lists are doing good things too especially when it comes to searching for components in a scene. Several of my more common classes add their instance to a static list when they are initialized (and remove themselves when they are disabled). This allows for the quick searching of a list of components rather than a more time intensive "Find Objects of Type" situation.
I don't think the extra memory usage a concern, at least not for now.
All of this is helping to create a more manageable code base.
So what is the result of all this work?
Energy Mechanics
The focus has been to get the basic resource mechanics working. As mentioned in an earlier post Energy is Everything, so getting the "generation" and delivery of energy working was a major goal. At the moment energy is broken down into two categories, mechanical and electrical. Steam engines, wind turbines (not yet implemented), maybe solar (these aren't functional yet either) and even hand cranks will generate energy. While generators and motors will convert between the two types of energy.
The current design vision is that energy sources can be attached directly to objects that need energy or that energy can be converted to electrical energy - at a cost - and transmitted via power lines or some other transmission mechanic.
The energy mechanics are largely functional and the parts that still need work should be easily created by extending the code that already exists. Getting this all working took several iterations and several bouts of refactoring with careful choices on script inheritance. There is, of course, plenty of tweaks and balancing that will need to be done, but the basic framework is in place and working well. Check!
Resource Gathering
I want to keep the resource gathering simple. I also want to make it easy to extend or add new resources. Can you sense a theme? So once again the focus was on building the base mechanics - which certainly needs some tidying and refactoring, but by in large the mechanics are functional and I'm happy with the product at the moment. Inventory Pro has gone a long way in helping structure much of the resource code - both in good ways and bad - the built-in item types and categories provide a natural structure for the resource content.
Currently, I'm focusing on wood/lumber gathering and basic mining. These should provide several resource loops as well as the basic building materials for all (most) structures. Or in other words, hopefully enough content for alpha build.
Logging
With the logging I started working to get the visuals right before tackling the coding or player side mechanics. Maybe this is backward, but if chopping down a tree didn't feel good it wouldn't matter how great the code was...
So, in Blender I took a basic tree model and added a loop cut to the trunk to allow it to split into two parts. I spent a few hours adding colliders, rigidbodies and tweaking physics settings until I arrived at something that felt decent. A particle based dust cloud finished off the chopping down of a tree and I was ready to implement the chopping mechanic.
I love physics. Both as a subject and as a game feature/tool. My trees use physics to fall. So why not use physics to chop the tree down? I added a trigger to my axe and a script to my tree. Hit the tree the right number of times and ... Timber!
I loved it. Until I had to line my character up with the tree. Ugh.
Trying to get a third person character lined up with a tree and get with in the range of the axe's trigger is doable, but that's not generally how you want to describe a commonly used game mechanic. "Oh yeah, it's 'doable.'" Cutting down a tree is not supposed to be the hard part. Did I mention the obvious fact the that axe is in front of the avatar so the player can't see it without rotating the camera.... Not awesome. So back to the drawing board.
I paused my work with logging and moved on to mining.
I often find when I'm stuck on a problem, big or small, moving on to another task often results in a more creative or at least better solution.
Mining Mechanic
I started with this Minecraft like vision where players would build an above ground mine and then be "transported" to a mine full of cubes. I wrote some code to generate the mines and place them below the game world. I added walls to limit player movement as well as block out the directional lights from the outside world.
Why not just have a new scene you might ask? I want/need the simulation in the outside world to continue and I also want NPCs to be able to visit a mine.
It was all looking good, I was feeling good about my mining solution. That is until I placed my player into the mine. Damn walling clipping! I immediately saw the huge flaw in my plan. It didn't take 3 seconds to know this approach wasn't going to work. Totally dead on arrival. The camera was clipping through everything. It looked horrible, especially when the camera was outside of the walls looking at the world above and the vast nothingness below.
Again, a new approach was needed. Something that will feel good and look good.
At times I wonder if I implement ideas from others because I'm lazy or maybe because they realized the issues and designed around it... Hmm. Good artists copy, great artists steal?
Click and Wait
With the tree chopping feeling lousy and the mining mechanic needing to be redone I decided to implement the classic "click and wait" (CAW) mechanic with mining just to see how it felt. And by CAW I mean that a player would walk up to an object, click the mouse and wait for an animation/action to finish. When the animation is finished the resource (or whatever) is ready to be collected. Add a progress bar to this and you've got nice, easy, and hopefully well understood feedback to the player.
It may be not be very creative. It may be fairly cliche. It may be a lot of things. But most importantly it feels good. The player walks up and clicks. The computer does a quick distance check and the progress bar starts doing it's thing. It's so much easier. Not only that but the previous method didn't really communicate to the player what was happening. Sure the old physics based approach had sound effects and particles when the pick axe hit the chunk of ore, but nothing much happened when you missed... Not good design. The progress bar, as cliche as it may be, teaches the player what to expect and gives near immediate feedback as to whether something is working or not. That's worth an awful lot in my mind.
The CAW mechanic felt so good I immediately added it to the chopping down of trees. While I miss the elegance of the physics based solution, as soon as I had the CAW working it was way more fun. I made a line of trees to just cut them down over and over... for testing purposes! I spent a little time appreciating the sounds, particles, motion and general goodness of how it felt. Hopefully the future players won't even notice - it'll just feel right and never get much attention.
Best of all with a little clever refactoring, the CAW mechanic can be applied quickly and easily to other game mechanics.
Freezing Player Input
When I was first coding up the farming scripts I made the decision to freeze input to the player and rotate the avatar towards the point of action. This did a couple things. First it helps the animations look better. It's pretty silly if your character is facing left and dirt is flying on the right... Second it solved the issue of the player interrupting an action part way through. While I like the idea of the player having control, breaking out of an action requires a good deal more code and bookkeeping then simply knowing the action will be complete.
As the only player tester, I thought it felt pretty natural and normal. I was more engaged with where I was clicking than the direction that my character is facing. Hmm. It would be interesting to get feedback on this. Maybe I'll implement hitting the "escape" key to break out of a CAW loop. So far it doesn't seem like a game where cutting down the wrong tree or planting a carrot in the wrong spot would impact game play much...We'll see.
Progress Bar
My progress bar at the moment is nothing fancy. Just a UGUI slider with the handle turned off. Maybe I'll make a dial or a circle or some thing with a little more style, but for now it works.
As of now I only foresee one (player) action happening at a time I added static methods (of course) to the script on the progress bar. This allows any script to call the progress bar and update it's value. No need to grab an instance via script or drop in a component in the inspector, simply call ProgressBar.UpdateValue(value) and the progress bar will toggle itself on and display the appropriate value. Have I mentioned how much I love static methods?
What's Next?
So what's coming next? I've been avoiding working on the AI side of things. Partially because I'm not 100% set on all the details of the game and also because, well, I know it's going to be hard. After watching "Less is More : Designing Awesome AI" I was encouraged to truly start simple. No need to plan out the entire AI, but rather start with basic functions and features, adding and tweaking until it behaves in a way that adds to the game.
I'm starting with farm animal AI. Why you might ask? I'm starting there as a way to learn and get familiar with Behavior Designer (my chosen AI solution for #2). Surely a behavior tree is over kill for a chicken, but I want or rather I need to start simple.