Pagina's

Saturday 31 August 2019

A little big thing

So, good afternoon.  No development today,  or at least not until the evening.  I do have things to talk about though, as I have been busy working on the movement mechanics in Holocene and there are some problems.

When a unit is selected and the player right clicks somewhere,  the unit should go there and that works for parts on the terrain where nothing already is. When there is a unit, it works too and the game knows where to stop to prevent two units to fight for the position to stand on.

The problem is when the unit wants to move to a stationary object like a resource or a building. The navmesh understands that the unit cannot just go there, so we'll have to find a place where it can go. Unity has these methods to find out the edge of a collider and places on the navmesh, but they do not yet give me what I need.  When I send a unit to an object,  it just stands next to the object on one place, no matter which is closest.


I'm not sure how the game decides that specific spot, but it's not what I want.  That is because it does not decide which place is closest to the unit. I was hoping the methode for finding the edge of a collider would fix that, but they don't.  I'm confident I will find a way, but I have not yet.

This is one of those "little big points". You might expect it to be a small minor thing to find the point where to go, but after a couple of days,  you realise, maybe not so much...

Wednesday 28 August 2019

Worker is too lazy

Good morning CET. An update on what I've been doing yesterday. I told you there was going to be 3D modelling for the gathering mechanics.  We have the rock and the worker that is supposed to mine the rock. We also have the mining mechanics,  but once the worker has enough stuff, there's nowhere to go to to deliver it.  So insert s simple 3D hut that I made in Blender. 



As always,  this hut is placeholder,  but I'd like to have it look like a hut and not some cube or something. I think I succeeded in that. I put the model in Unity, gave it a collider and building script and put it in the scene. Next I gave it health to prevent it from being destroyed right at the start of play mode (something I struggled with when I introduced a warrior). Good to go.

Well, no. That was because there was something wrong with the rock. Somehow I had that specific one yield gold instead of stone. And the hut only accepted stone, so the worker's not going anywhere. Well, fixed that. Still not going. This means there must be something wrong with the AI state picking thing and it is. The worker finishes mining, switches to walking as it's supposed to. Then it goes idle.

Being lazy myself,  I get that. Sometimes you just go idle, but not this time. We're talking algorithms and they are supposed to do what I tell them to do. It hurts to say, but I guess I could have made a bug then. Let's fix that. Next!

Monday 26 August 2019

Transitions are important

Working with and getting used to Unitys Animator, I find that the beef of these state machines is in the transitions between the states. Different states have the agent do different things, but the main thing is to get the agent to go to a specific state when you want it to.

I'm working on the gather mechanics for workers.  I put a little rock from Blender in my scene, added a resource script and focussed on the interaction between worker and rock (and explaining to a friend that not all interaction is sexual).


In short, you right click on the rock and the worker will move towards it. When it's there, it'll make a difference if the agent really is a worker and not, say, a catapult. Catapults can't gather resources in Holocene. Workers can. I managed that by adding a task enum to the unit script. That enum contains certain things that only certain units can do, like gather. The worker script will override the unit script for moving to a resource, adding the gather task. Now that is used to trigger gathering.  Guys without the task will go idle on arrival.  Others will go to the gather state.

Then gathering happens.  The worker will get resources over time and the rock will loose some. Then we need to decide what to do next.  When the rock is 'empty' or the worker can't hold any more resources,  we need to drop it to a building.

I've not finished this yet,  but I will save the resource object and location in a separate variable and find a suitable drop off point and object to go there, setting the task to return. The walking behaviour takes the worker to the drop off point and triggers the dropping.  Next the resource will be the target again and the worker returns to gathering. When the wotker does not have any resources and the rock is empty too, he's finished and will look for another rock to carve.

This should be the gathering AI. It took my some time to think up, especially since I need to get used to the triggers in animators. I am at a point though where I think I know what to do next.

This is one of those things I love about making games. There's little victories around every corner,  much more than in my day job. That's very motivating.

Sunday 25 August 2019

Fighting for position

Ok. Weekend is over again.  I have not been able to get too much work done in Holocene this weekend as I had other things to do (and yesterday night I wasted my time watching The Marathon Man).

What I did do is making a start with moving units. For that, I made another of these primitive shapes based Workers. A capsule for the body, spheres for head and red nose to know which way he's facing and an elongated cube for arms. And a worker script and some needed Unity components.

First thing I set out to do is to implement the walking behaviour that I made for goats. When the unit is selected and the player rightclicks on the ground somewhere,  the unit is going there. Quite easy.

When clicking on a friendly unit, the unit should go there and stop right next to it.  Well, that gave us this little gif that I shared on Twitter:


Now what happens there? Note that I have not yet implemented any fighting mechanics.  These workers are not fighting per se, but yet they actually are. The thing is, the moving one is trying to stand on the spot where the stationary one is already standing. Because two entities can't occupy the same position, there's squeezing going on.

This was actually quite easy to fix. The worker script knows what object it's going to and that object knows its size. All we need to do is tell the walking behaviour script what the size of both objects is. Add them up and we have the stopping distance. 

This is actually really all I pulled off this weekend.  Hopefully I have more time for my game this week.

Thursday 22 August 2019

Setting up the interaction

Ok, another update. Yesterday, I wrote about a little issue in the WalkAround state of goats.  Well, it somehow took the best part of the evening to fix that. Somehow the trigger for starting to move kept getting hit before the position was picked, having to goat literally go nowhere.  Well, done now.

The more interesting thing to talk about  is a little groundwork for giving orders. I already had a system to find objects when given a location.  I upgraded that with a class of references to everything you need to interact with an object. In the end, orders will all be "interact with this object over there" and the kind of object is central to know what "interact" really means.

When I  right click on an object,  selected objects will run a method on a base Worldobject class to decide which virtual void to run, with some basic general stuff and possibly overriding methods in a derived class.

Sorry if this is technical. It means that I define basic behaviours for interacting with objects of a certain kind that should apply to anyone. When a certain agent has its own behaviour for some interaction,  I'll program that and run that instead. This is how I understand object inheritance in C#.

Well, all I ended up with visually is that Holocene looks exactly like it did the day before yesterday,  so I won't bother you with screenshots or the like, but now it should be set up to do things I did not program yet. I like to have it flexible, because I know it is getting more complex quickly now.

Wednesday 21 August 2019

To our goat overlords

So I opened Pandoras jar. Yesterday was quite productive and I am pretty pleased with it. I started working on a new AI system, based on Unitys animator component and the theory I found at the likes of Tommy Thompson who has a compulsory YouTube  channel on AI in games. It took a little rewriting,  but it looks really workable. Someone on Twitter already greeted our new AI goat overlords when I shared this one.


This one is as complex as it looks really. A goat enters the game in a WalkAround state where after a time a trigger "arrived" is hit. When that happens, the goat will go to the NextTarget state. It then immediately returns to WalkAround. If, after some time, a trigger "died" is hit, the state will transition to Dead.

Now that I'm typing this, I see a flaw. It works, but only for randomly walking around. That is because I use the behaviour scripts for this state machine. NextTarget does not actually anything but having the WalkAround state restart. Picking the destination for walking is done in WalkAround,  making it useless for any agent that does not walk around randomly.

What I'm going to do tonight is move that destination deciding thing to NextTarget and rename both states to be used for other agents.  The Walk state will deal with a destination in the Unit object and walk there. When it arrives,  the next state will decide where to go next or what to do next. A worker might want to collect food after moving to the bushes, a goat will go somewhere else. Both could use the Walk state for walking. The difference is in the transition after that.

Anyway... I also did a little thing to trigger the "died" thing. For that, I added health to objects. When health gets to zero or below, it hits the "died" trigger.  Objects then change to other objects. For instance, when a tree dies of cutting, it turns into a horizontal thing that gives wood supplies. It gets different attributes by dying. Technically it's become a different object,  but ssssht, don't tell anyone.

Next steps will be to first fix the issue with the states, to add a healthbar and damaging mechanism to test the death thing and then to start Worker AI. With AI here I mean the intelligence to perform orders like "go there" and "harvest that". Giving the orders by enemy players is for much later. I call that Player AI and I did not give that much thought yet. Did I forget to mention anything? Probably, but the bus hits the "arrived" trigger, so I sign out for now.

Monday 19 August 2019

Big goats unite!

Ok, that went more easily than expected.  Yesterday, I had a couple of hours to work on the selection system for Holocene and I think I finished it, which is nice. 

I made a script to handle selecting and deselecting objects for the player and made some changes to the script handling input from the mouse. As I said yesterday,  the script keeps track of what object is under the mouse cursor. When the user clicks, the following things can happen:
  • You click on an object. It gets selected.
  • You hold shift and click on an object. It gets added to a list of selected objects. The selection script always knows what kind of objects are selected and uses that information to decide whether the clicked object will be the only object to be selected or the other selection remains. Only units you own can be multi-selected. If the current selection contains other kinds of objects (e.g. buildings or enemy units), or the object to be selected is another kind of unit, the selection is cleared and that one object is selected. 
  • You click somewhere on the ground and drag a box on the screen. All owned units in the box are selected. 
That's it, actually.  Because I don't have any GUI yet, I used the inspector to test it and it seems to work fine. In the little gif below, the big goats are owned by the player. The small ones are enemies. I try all the ways to select them.  It works.



Next up will be making basic moving units. Select 'm and right click on the ground to have them move there. The goats are not supposed to be controlled. They move around on their own. 

Sunday 18 August 2019

Selecting Objects Again

Good morning, people. I'm back from a weekend with quite some game development time and half a season of Casa de Papel. It was raining, but now I need to go to the office again,  so it stopped raining.  Time to tell what I've been up to this weekend.

First, there were two issues related to the world not being flat. I kind of solved them, but I'll revisit them when I feel like it. The camera is flying over the terrain and it avoids high hills like the plague, which is nice. It does not do that very smoothly. I need to find out why.

Same goes with the rotation of my models when moving uphill or downhill. It seems the navmesh agent does not care about the y-axis, so I had to do the rotation myself. After tinkering (and cursing) the rotation is now correct, but it flashes to that rotation in an instance. But hey, quaternions are evil. I'll get them good one day.

Now to the meat. As I told you, with the hilly terrain, I decided to refactor majorly, so I  am not porting all of my old stuff to the new Unity project. First thing to remake is the mouse control. The control script always knows what object the mouse is pointing to. That will make it easier to interact.

First thing is selecting objects. Like in the old project,  that happens by left clicking. Holding shift will add an object to the list, but only if we're having your own units. You can only group select units you own. All other kinds of objects are only selectable on their own.

This works partly and I expect to finish it soon, but it was late yesterday, so being tired, I probably put some bugs in there. I'll revisit this tonight if I have time. After that, I'll see if I can get box selection to work. That'd be an entirely new feature. Hopefully I can start with that today or tomorrow.

Thursday 15 August 2019

The ground is not flat

Just a small update, because time is an illusion. What have I been up to yesterday? Well, bits and pieces.  First of all, I have been working on the camera system.  Next, I'm reimplementing the features I already had.

You might have noticed I am working on a different Unity project since starting the procedural level generation. This is because I found out that much of what I made was dependent on the ground being flat. That, and when you're learning,  sometimes you want major refactoring and it's often better to do that early.

The camera then. Because the ground is not flat, I cannot just clamp its position to a certain height on the y-axis. I need to find out how high the ground below is and then clamp in to a certain height above the ground.

Typing this, I now know what to do tonight. I need to send out a raycast and see how far away it collides. Then I have this point. Add some minimum value to the y-value of the camera position and we are done. I just need to make sure the camera doesn't go beyond the level, looking to the void that we all fear.

Next, this guy.


You know the goat. It's our first agent walki g around on the navmesh. It works, although I need to tweak some parameters. That's nice, because I am implementing a new AI state machine. With the floor not being flat, rotation will be changed, but I didn't have time for that yet.

Now, the bus is almost at the station,  so you know what that means...




Tuesday 13 August 2019

Trying a different way

So the magic phrase is "procedural level generation". I opened a whole can of worms when I told myself that Holocene needed a ground that would be different from a flat plane. It got me into a whole range of tutorials for making something that looked exactly like I needed, but really wasn't.

I learned to work with Perlin noise maps  and how to use those to get a 2D configuration that looks random enough for my purpose. That's nice and it's also nice to use plane objects of home made meshes to get the level rolling,  but probably not in Holocene,  because I could not get the navmesh working. And by now you should know that this is a no-go.

The problem is that, no matter how hard I try, navmeshes end up below the surface of the level and not on top. That means that the characters would not be able to walk over the surface of the world in the way that I planned. I couldn't get it to work.

Yesterday I found another tutorial on putting what I learned to practise on an actual terrain mesh and that works if I use the special navmesh scripts that I found on the Unity github. The scripts allowed for baking the stuff at runtime which seems to work. All I need to do now is bake the mesh after generation.

I have a working navmesh now and I can now add the features to it. I am still not completely satisfied with the way the terrain looks. I think I need to tweak the noise script to allow for more flat regions, but for now it works. Next is to turn this into a game.

Sunday 11 August 2019

Building the world

Alright, I've been quiet on the blog recently. That's because I mean to have a big change on the game. The change is about level building. Holocene is a Real Time Strategy game and those games should be replayable, but that only works is the playing field is more interesting than just a flat plane and if it's different every time you play the game.

For that reason, I studied procedural level generation for a couple of days. It works by putting a plane in the scene and having vertices inside of it go up and down according to some noise thingy that I do not yet totally understand. The idea is to get the plane to resemble a sort of low poly terrain.

Next, there'll need to be some changes in the different scripts to allow for the third dimension that we have now. In fact, Holocene may look like a 3D game already, but it's the famous thing with the ant that quantum physicists always say when they explain the multidimensional world they think of. An ant is walking on the pavement like its 2D. There is no up or down for it. Well, the objects in Holocene should turn from ant to human.

I'm starting to get the gist of the level creation and I think I might be able to use the same script with some modifications once I build a campaign mode, but right now, I am not yet satisfied with the way the terrain looks. It's too bumpy and not mountainous enough. It's too all-the-same to my taste and I'll need to change that, because we need valleys and mountains, not just one 6 meter high hill following another.

I need to get the noise changed. While there's the Perlin Noise, I need to tweak that. I need lower the frequency so that we don't get hills everywhere we could get. We're trying to run a civilisation there, right? Next, we need higher amplitudes, because we need mountains and valleys. Lastly, I need to add more noise within the noise so that it does not look the same everywhere we look. We need hilly parts, flat parts, sea and mountains. And everything in between.

Looking at the code I have now, that must be feasible.

Monday 5 August 2019

Dead, depleted and vanished

Alright, what did I do yesterday? Well, two things from my little list that I made recently. At least, a variant of one.

First, I wanted to make sure that when gathering or returning resources was interrupted,  you could order a worker to drop the stuff at a building.  When you right click a building that you own, the script will check if the selected unit has resources and whether the building is the kind of building that will accept the resource type that the unit is carrying.  If it is, the unit will get the task of returning to that building and dropping the resources. If that is done, he'll go idle.

The second thing is that once a resource is depleted, it is no longer useful and only causes annoyance for the player to find out which of the 17 felled trees have wood left. Now, the object will have its alpha decrease to zero over the course of a couple of seconds.  When the alpha is zero, the object is transparent and is destroyed.

I am going to change this later though. Right now, this only works for resources.  I'm going to move the functionality to the worldobject script and have it apply to dead units and broken buildings too. Furthermore, I think I will make a dead-and-depleted model for those objects, like a skeleton, a ruin of  tree stump. That object could then be removed more slowly. Most importantly, I now know how to make it work.

Sunday 4 August 2019

Actual goats and improved gathering

Alright,  Monday morning.  I'm on my way to the office again.  What did I do this weekend? Well, mostly modelling the goat in Blender.  It's not rigged yet, so there might be some revisions later, but it looks like a goat and that's more than I expected at the outset.


This goat model is now also linked to the goat prefab and the dead goat prefab in Unity. A goat is a unit and a dead goat is a resource.  Goats are replaced by dead goats once they die. These are the things one needs to explain a conputer. Visually,  right now, a dead goat is a goat flipped to the side. Might revisit this later.


The next thing I made progress in, is the thing where resources cannot be brought to just any building. The little white domed building to the right is a Mill and mills are good for bringing food. Even though it's the closest building to the tree,  when the tree is cut, the resources are brought to the Zigurat. Food can be built to the mill. That kind of thing.


The other thing was fixing a bug. When the dead goat is emptied, the workers went looking for living ones to kill instead of the dead one nearby. I fixed that. Then I found that the guy started gathering the goat food a couple of meters away. Had to fix that too. 

For now, I'm pleased with how it goes. Some of the core features work now. I have these points that I mentioned the other day and there's the combat system coming up. Next, I'll see how the stuff works on a terrain instead of a flat plane. Next, there'll be the enemy AI to think about, then starting to replace placeholder things with better things to have it look and feel better, as well as review the GUI. 

This sounds like it'll take 2 more days. Well it does not.