Hi mr awesome City builder, this looks insane! I’m making a low poly style modern city builder (won’t compete with yours and is targeted at mobile) I’m still in the asset making stage in blender, and haven’t even looked at the coding part yet, and I’ve forgotten most of it.
I’ve been planning the mechanics of the game, and how people will interact, but I have an issue that you might be willing to help me find a solution to. See, your people I presume follow paths to get back to their house, but how do you make them follow paths back home? How do you even begin to make them so that? I just don’t understand. Like in Gta when it plots the quickest path to get to the set location. How? Please help me, and I’m grateful for anything. Keep up the good work, this looks really good! You are really talented (he says, massively sucking up…)
First off I don’t worry too much about competition, this is how better games are made!! Pathfinding is probably one of the most important parts of this kind of game. When I first picked up Unity I had no idea how to implement this. I kept reading on the A* pathfinding algorithm on Wikipedia and it didn’t make any sense.
I decided a ready made solution, the A* Pathfinding Project made by the very talented Aron Granberg: A* Pathfinding Project
This is one of the few assets I didn’t make myself I’m using. You can use the free version but even at 100$ the pro version is worth every penny. It’s a bit hard to setup at first but once you get it going it’s amazing.
The documentation is fairly easy to understand but you should put your movement code in Update and not FixedUpdate.
It gets a bit more complicated when you want to make modifications to the existing graph for example prioritize using roads and prevent walking through buildings. But he also has a tutorial for this.
At the end of the day going somewhere is as easy as doing:
Thank you for the great feedback and good luck on your project! Feel free to send me a private message if you have any issues with aron’s pathfinding I’ve gotten quite good with it!
Dynamic Events
Today I will give you a little glimpse of my event system in the game. The events are stored in a txt file that is parsed by the quest engine at startup. Every 30 seconds or so it will test every single event on every single citizen in the game. Right now the load is offloaded in a coroutine but eventually this will be done on a separate thread.
Let’s take this event for example(I used the CSharp tag to keep the formatting but this is just a regular txt file):
Event{
id = 3
description = My Liege, I noticed you had no one aiding you with the peasants and farmers. Surely it must be a lot of work. Perhaps I could be of assistance, I wish to be named your Reeve.
player_only = yes
MTTH = {
month = 1
modifier = {
has_trait = ambitious
factor = 0.5
}
}
Conditions{
diplomacy = 12
reeve_unlocked = true
reeve_assigned = false
}
Response{
name = $FROM$ is my new Reeve.
Actions{
FROM = {
opinion = opinion_on_council
assign_council = reeve
}
}
}
Response{
name = I'd rather elect a Reeve myself, but I'll consider it.
Actions{
FROM = {
random_list{
0.1 = {
opinion = opinion_denied_from_council
}
}
}
}
}
};
Alright these are fairly easy to understand, the ID is used for quickly looking for events in a dictionary. Description is the text that will appear to the player. player_only = yes indicates that the person receiving this event will always be the player (the manor lord)
An event usually a person calling the event, and a person receiving the event. This tag allows me to save time by already knowing who will receive it.
MTTH stands for meantime to happen, when the conditions of the events have been met this is how long we’ll wait until the event triggers. I’d like to have a little more random options now because now if anyone is over 12 diplomacy you’re 100% certain to receive this event within one month so I need to figure a way to fuzz the odds some more.
Conditions are again very straightforward, they will make sure the person calling the event (FROM) meets the conditions.
The flag reeve_assigned and reeve_unlocked are global flags.
The Response tags outline what each possible responses will do. In this case the actions are only done on the person calling the event which is why they’re enclosed within a FROM = { } block. You can create random lists or fire actions regardless of chance. You can have certain conditions modify the chance of something happening using the modifier = { } object.
This is what it looks like in game, the quest system found that Isac had over 12 diplomacy, the reeve position was available and unfulfilled. The text will be evaluated to match the name of the caller and all the tool tips are built dynamically by the system when the event gets fired.
In order to add content I only have to add a few lines of text in my file and the quest system will take care of the rest. This will enable me to quickly add content and allow players to create their own events.
Upgrade to Unity5
So it turns out that upgrading to Unity5 has been less of a problem I thought it would be. I had to fiddle a lot with my snow shader to get it to work again, and especially the terrain one. I was using the ats snow suite which is an amazing pack sadly it seems it’s no longer being supported by the dev.
Aside from that most of my shaders were still working fine, no scripts error. I do not use physics except to intercept raycasts from the mouse so no issues there. I noticed a slightly slower performance in the editor, but better in the actual build so I don’t know what’s up, perhaps it’s all those sweet pro features slowing down the editor.
Speaking of which, after 18 hours of intense googling, forum lurking, trial and errors, I manged to get reflections working on a custom flow map shader, see for yourself:
Not much has change functionality wise except now each social class has it’s own unique AI meaning that the lord will not plow the fields, peasants will not hunt (unless allowed) etc. It’s easier now to break down possible actions for each social class. A year ago I had no idea what derived classes were, I can honestly say working on this project is definitely turning me into a better programmer. I recently redid the trade window to include the resource icons (still need to make most of them)
Of course it will be possible to disable the effect.
I’m still having an issue with hunger people eat way too much or factories are not producing enough. I’ll need to balance the production vs needs and values and this is going to be real tough.
Thanks for referring me to this thread! Very interesting to see your event system breakdown. I have two big questions.
How does the system handle the MTTH currently? Does it just check all the possible events, and then say “trigger this in a month?” Does that mean that all events are theoretically guaranteed to fire in your current implementation?
I’m very interested to know how you’re handling the tooltips. Handling it at the script level sounds a little more complicated, but quite ingenious.
In the current implementation yes, if the conditions are met the event will fire within it’s mean time to happen for sure (unless the citizen that’s triggering it dies before it gets launched). I think I have a good base for a system like this but there is not enough randomness, it’s very common to begin a new game and have at least one peasant who’s going to have 12 diplomacy or more. So every time I play I get a pop up for someone asking me to be the reeve. I’m still on the lookout for some way to add another degree of randomness to it while retaining a certain control.
Right now the system has been thrown together quickly for prototyping purposes, it’s far from perfect. I have a coroutine that checks for eligible events in a loop. Once a quest is deemed ready I put it in a wrapper class that has the Event, the caller and the receiver as well as a timer . For example in my game a season (3 months) is 600 seconds, so a month is 200 seconds, a week is about 50 seconds and a day about 7 seconds.
The MeanTimeToHappen is placed within its own class and has the ability to check modifiers against the calling villager to modify the time it would take for the event to launch like so:
[System.Serializable]
public class MeanTimeToHappen{
public float DelayBeforeStart;
public Modifier[] Mods;
public MeanTimeToHappen(float _avgDelay, Modifier[] _mod){
this.DelayBeforeStart = _avgDelay;
this.Mods = _mod;
}
public MeanTimeToHappen(float _avgDelay){
this.DelayBeforeStart = _avgDelay;
this.Mods = null;
}
public float GetEventTime(){
float factor = 1f;
if(Mods != null){
for(int i = 0 ; i < Mods.Length ; i++){
factor *= Mods[i].GetFactor();
}
}
return factor * DelayBeforeStart;
}
public float GetEventTime(CitizenAI cs){
float factor = 1f;
if(Mods != null){
for(int i = 0 ; i < Mods.Length ; i++){
factor *= Mods[i].GetFactor(cs);
}
}
return factor * DelayBeforeStart;
}
}
Then my update loop simply decrements the timer for the given event, when it reaches zero launch the event:
Yesterday I tested a build of the game with 145 citizens active and this system induced little to no lag at all even though it does tons of string comparisons. Of course having 150 skinned mesh on the screen is another matter.
To evaluate the tool tips at run time again I’m taking a very basic approach (I’m not really a decent programmer). I’m simply comparing flags in my Actions, this is done only once per event when it fires and gets displayed to the player again trying to minimize the amount of allocation created by all these concats. The EventResponse class has a method for this:
public string GetActionToolTip(QuestLauncher ql){
string toolTip = "";
for(int i = 0 ; i < AllActions.Count ; i++){
toolTip += StringDisplay.Evaluate(StringDisplay.GetActionString(AllActions[i]), ql);
}
if(RandomActions.Count > 0){
toolTip += "One of the following will occur:\n";
for(int i = 0 ; i < RandomActions.Count ; i++){
for(int k = 0 ; k < RandomActions[i].PossibleActions.Count ; k++){
toolTip += StringDisplay.Evaluate(StringDisplay.GetActionString(RandomActions[i].PossibleActions[k]), ql);
}
}
}
return toolTip;
}
QuestLauncher is the wrapper class I was refering to earlier, it contains the root and from variables so I can assign them to tooltips Evaluate is very simple it will look for any enclosed text and replace it with the appropriate villager name. Here’s what GetActionString does (omitted a lot of code)
public static string GetActionString(PairContainer EventAction){
string key = EventAction.Key;
string value = EventAction.Value;
float chance = EventAction.chance;
//...
else if(key == "opinion"){
string chanceString = "<color=#ADDA74>" + (chance * 100).ToString("#0") + "</color>";
OpinionContainer c;
if(OpinionDB.OpinionDictionary.TryGetValue(value, out c)){
string color = "green";
if(c.modifier < 0){
color = "red";
}
string result = EventAction.target + "'s satisfaction changes by <color=" +color + ">" + c.modifier + "</color>";
if(c.seasons > 0){
result += " for <color=#ADDA74>" + c.seasons + "</color> seasons.";
}
if(chance == 1f){
return EventAction.target + result + "\n";
}
else{
return chanceString + "%: " + result + "\n";
}
}
}
return "";
}
I’m very sorry if this was a lot of code, maybe you wanted a simple answer. Please feel free to ask any questions I love to answer them as it also allows me to see my code from a different angle and perhaps notice weird stuff.
This is awesome. Appreciate your humility that maybe this is something that can be thrown together quickly with some imperfections, but it really helps clarify the whole system, and it gives me some ideas for how to approach a similar system.
Thank you very much for the feedback! There isn’t much to show these days as I’m mainly working on back end stuff (mainly saving and loading and all the issues it brings out) and it’s also the end of semester in school so exams and stuff.
I follow you for four months now and even if i haven’t enought skill to make the same things that you, I love to understand how it works. I have two questions today :
I know you use A* pathfinding, but can you explain which graph do you use (grid, point or mesh)? And can you explain how do you prioritize the roads?
I read in your blog that you use a StateMachine to assign the Task to the citizens. Can you explain how it works, how you assign Task to citizen (which task? how the computer know you must come back home or to job?). And can you explain a bit how your AIState is writen?
Thank you so much for the feedback!! It’ll be a while before it’s ready for people to play but once I have a bit more content I’ll ask around for closed alpha testers!
I’ve decided to go with a grid graph because I needed a graph that could be updated quickly at run time. The way I prioritize the roads is by setting an initial penalty on the terrain of 10 000. Then when I build a road I simply set the nodes within its collider back to zero penalty. The A* project comes with a class called GraphUpdateObject which you can derive from and make your own update rules.
It’s not a real statemachine, as normally each state would have possible transitions to other states. In my case it’s really a queue of tasks to do. Take a look at my update and dequeue method:
When a state is done, it is dequeued from the tasks list and the next one will begin. If there are no more tasks to do then find something else.
Some tasks are blocking and some will just happen once. For example let’s say someone wants to eat something but doesn’t have a home, they have to find the nearest storage barn, walk there, grab some food and eat it. I’ve made States for all these actions. These are classes that implement AIState which uses the SetUp(), StateUpdate() and Exit() methods.
The agent will then go through it’s queue, first play the walk animation, then move to the storage barn. Once there, play a bend down animation, grab food and eat from the storeage barn. Since this is done over one frame only, wait 2 seconds, then get up.
At that point the action queue will be empty and the agent will call its assess needs method. The AssessNeeds() method works down a priority list (Should I eat?, am I cold?, Should I look for a house? Can I work?, Is there a field I can work at?, Should I be constructing something? and so on.) The moment it gets a yes it will load up the proper action queue, and start doing the tasks!
It’s a very naive approach, but it works absolutely great and performs very well contrary to what I thought. It’s not a real state machine though (I think).
I hope I answered all your questions, have a great day!
The church is one of the few buildings that, as the Lord of the land, does not belong directly to you. The church will open up the Friar/Priest position on your council and appoint that person as the manager of the church (limit of one for now). Monks will come to the church and eventually make copies of holy texts which can give a bonus to piety.
This by far the highest poly model I ever made. It has 1400 verts according to blender. Unforunately since it’s unrwapped on an atlas, every vertex is split so it ends up being 2600 verts in Unity. I’m hoping this trade-off is worth it compared to having each building on its own texture image.
The upside is I only have one texture (4096 x 4096) for all my buildings. The downsides are that I can’t really make any custom details on those textures and I have to take into account that I’m pretty much doubling my vertex count.
I dont think keeping all buildings on one single atlas has a lot of benefits. Dynamic batching wont work as the models are different and would have too many verts anyway (i think for DB you can only have like 300 verts or so).
The only direct benefit you have will be saved texture memory, as you wont need a lot of it since you are reusing textures all over the place. This comes with the direct downside, as you mentioned, that you cant go full detail on individual buildings. Not sure how much that last one matter from a RTS camera view though.
To fully make use of your atlas approach, you should really ‘batch’ the buildings manually, by using Mesh.Combine. How implementable this is depends on your game though.
You dont really have to worry a lot about the vert count, as computers can handle a lot of them these days. Your focus should be more on the drawcalls, which most of the time is the bottleneck on modern hardware.
Thank you for the information. I’m using my own take of the Mesh.Combine method for a lot of things like the grass, crop fields and dynamic meshes like walls, fences or bridges. For example the grass is 25 patches around the camera, each patch contains 2500 grass meshes and are combined to a single mesh. Take frustum culling into account and I have lush, animated grass for about 15 draw calls.
I thought about combining my buildings together but there are a couple of things I need to take into account. For example this would most likely break any LODs (I don’t have them yet but if I want to implement those I guess combining is out of the question). Most of my buildings are below 1000 verts, to be honest I could very easily reuse my code for the grass which automatically culls meshes that are a certain distance away.
I thought the biggest performance hit came from “context switching” on the GPU which meant material swapping. I thought even though the meshes aren’t combined they use the same material so there’s no new texture to upload to the GPU is that not the case?
So at this point there is absolutely no performance benefit from using a single material instead of 30ish?
I mean it’s not too bad I could easily re do my UVs on my model and just bake the textures from the atlas, I’m pretty sure that within a few days it would be done and then I could go on adding details.
I guess the point of view really depends on the player. I’m the kind of guy that loves zooming in and looking at all the detail in a game like this. I rarely play zoomed out all the way.
This is still something that would be done much later during development. The atlas at least allows me to quickly texture buildings, the church took less than an hour to texture since I already have a diffuse and a normal map.
For a while I really had an issue with my food production and consumption, I would run out of food within a season or two so I thought why not make a UI element that shows me how much food I have, how much I’m expected to use to feed my people and so on.
Before, everyone had it’s own hunger timer, when they were hungry they’d either eat straight from their house inventory or walk to the nearest barn to get food. This did add some degree of randomness as to when people would eat but it made handling food stocks a nightmare. So now everyone gets the same timer, every 200 seconds (month) people must fulfill their hunger needs. Here’s what it looks like for now:
So you constantly see the amount of food available in your barns, when you mouse over you can see a breakdown per food type, the amount required for your next meal, and the time before people must eat (the green progress bar).
If you have a steward on your council you can know exactly the amount of food in the entire village, not just in your storeage barns. With this new system I’ll be able to add the concept of Ration so you can have half, double rations. This will of course have an effect on satisfaction and probably on health.
You can also notice a new panel in the UI at the bottom right. This is the minor events, right now it will only alert you when you promote someone on your council, when someone gets pregnant and when a kid is born. But I can see a lot of use for this kind of information in the future.
For some odd reason my hunters are firing their arrows pointing straight down, I’ll need to look into that.
I’ve removed all OnTriggerEnter/Stay/Exit from my villagers. I was using it to know when they were over a road to adjust the speed. Now I keep a Dictionary<Vector3, float> which contains the speed bonus. In their path state I only have to get that value from the dictionary and add it to the base speed. I got a pretty good performance boost from those.
I added specific cull distances for all my animated meshes as well and I’m also combining meshes more aggressively now with reflections and shadows I’m at a comfortable 85FPS in editor.
Just for giggles I thought I’d show you what it looked like almost 2 years ago:
Wow, very good progress. Who would imagine that. I’m a huge Tilted Mill’s games (Caesar, CotN, Zeus, etc…), but I’m also a huge fan from Dwarf Fortress and “similars” (if there is any game that is similar to DF; heheh). I downloaded the Unity in an atempt to “build my first game”, and so on. And my “dream’s” game actually is quite similar to the game you’re building hahaha…
Do you have any other space to discuss it, or just this topic?
I woud like to ask you some desing questions: how will economy be like? Something similar to Children of the Nile?
Seccond: I notice that your timelapse is very fast! (200 seconds a month, it’s that correct?). It will be possible to follow somebody’s life? Like see a person growth? But How will be the “roleplay” thing of the game?
Third: How do you structure the society? By families (similar, again, to CotN)? Each family has a house, has A job (same job for all the family members, no gender distinctions) has their equipment (food / currency / cloth / others stuffs)? Or by classes (hey, Marx!, hehe)? Or by individuals?
That’s all by now. I’ll add to fav. this topic and visit it every day (yeah, I’m that excited by your game, hahaha)
Sorry for the “non-tecnical” questions, and sorry for the bad english, not even my seccond language
Hey there, I’m very very sorry for the delay in response. I had to put down my cat last week and it’s been really hard on me and my girlfriend, I haven’t touch my computer since the 19th. I’ll get back there soon but I’m not ready yet.
I don’t have anywhere else yet when the game is more fleshed out I’ll have a website made, here is just fine.
I’ll be honest I’ve never played Children of the Nile, I just looked up some videos of it and it reminds me a bit of Caesar III which I loved when I was younger. So far the economy is not fleshed out at all, everything is a set price and will not vary at all. Of course I plan to change that and maybe limit production in cities instead of allowing the player to build everything. I can see advantages to both sides of that coin.
Yes it will be possible to follow people from birth to death, see how they do in life (provided they stay in your town for that time). If you play at normal speed a year takes 40 minutes, at max speed 4 minutes. So going through someone’s entire life will take a looooooong time. The role play resembles Crusader Kings II, basically you’ll get some events pop up to which you can react. Depending on the kind of people in your city and the way you manage it you’ll get different events, and different actions you can take. People will also have special events between themselves, to which you might have to react or not.
Society is something that’s very much still in the prototype phase and has went through a couple of major changes already. Housing is done on a family and class level, as soon as someone finds a suitable house for their class, the entire family moves in. Work is done on an individual and class level, most businesses have a main job. For example the blacksmith will be the person producing tools. This person must have a high enough craftsmanship skill in order to work there. The second job is the runner. This person moves the goods back and forth between the storage barn and the work place. This person needs a high constitution skill in order to be able to carry more goods. The third job is the Overseer, this person handles the resource management and sales of the business, this person needs a high stewardship skill in order to maximize profits. You could have 3 people from 3 different families working there. Of course a proud nobleman might have a problem with being assigned as the runner boy.
That’s only the blacksmith, each workplace has a combination of different professions. For example the forester only plants trees, so there are no runners and no overseers.
There is absolutely no gender distinction in the game, any man or woman can do any job.
Marriage is pretty much a class only thing but it’s also a tool to help people climb the power ladder. There are no equipment per say but people will consume a set amount of clothes every year, again depending on their classes. Nobles require better garments than farmers.
I hope I answered all your questions, let me know if you have any other.