Animal Crossing AI is a technical demo featuring an Animal Crossing village where villagers have a real routine and different needs made for an university subject called Artificial Intelligence.

Context

Animal Crossing is a life simulation game, in which the player moves to a peaceful town with the only goal of rest, pick fruits, catch bugs and... pay taxes.

There are 2 NPC types in these games: special NPC and neighbors.  Special NPC are unique characters with a specific role in the game that every player know, such as Tom Nook, the shop keeper, or Isabelle, the secretary. Neighbors are other inhabitants without any particular role, and every player has some of them living in their town. There are more than 300 neighbors.

Animal Crossing classifies neighbors by species. Each new one retextures the corresponding model and is given a personality. There are lots of neighbors: dogs, cats, tigers, kangaroos, penguins, rabbits… and each species counts with 10 characters approximately. The point in question is their personality. It defines what set of dialogs the character uses to communicate. 2 different neighbors with the same personality will speak exactly the same way. Animal Crossing personalities are exclusive to genders and we can find 8 of them:

Female

Male

Design

In the prototype, neighbors have a set of parameters that will represent their needs, and we count with differect actions that will satisfy each of them. Each NPC will decide which one is the most important at each moment and how to satisfy it.

Need

Drowsiness

Hunger

Dirtiness

Thirst

Boredom

Toilet

Cold

Hot

Rain

Filling speed

Slow

Medium

Vert slow

Fast

Very fast

Fast

External

External

External

Satisfaction action

Sleep

Eat

Bathe

Drink

Play

Go to the toilet

Go inside a building

Go to the beach

Go inside a building

They also have more parameters to define their personality by affecting the decisions they will take.

Each neighbor has different values in these variables so we can see how they affect in their final behavior.

Development

I chose Unreal Engine for the development, mainly because it provides many AI features by default, and seconly, because Epic Games gives away lots of premium asset packs for free I can use in this project. The Unreal Engine features I used are Behaviour Tree, waypoints and AI Controller.

VisAI is a Marketplace package that provides classes and preset AI behaviours. I don't know its full potential, but I used its template for the Blackboard, Behaviour Tree Tasks, waypoints and AI Controller.

Feature A. The town is filled with a navigation mesh and waypoints which satisfy the neighbors' needs.

The object NavMeshBoundsVolume automatically calculates the navigation mesh of the map inside the cube. It is set to leave under water outside the navigable volume. I set waypoints in the map that satisfy one of the neighbor's needs. Each waypoint stores this information:

This house has waypoints to sleep, drink, bathe, go to the toilet and have fun watching TV.

Feature B. The needs of the neighbors rise with time at different rates and will try to satisfy them when the surpass the variable threshold.

Each neighbor inherits from the blueprint (a class) BP_Villager. It has all the variables mentioned before and the references to the UI elements and the time and weather.

Every frame, each neighbor updates their variables, incrementing them at a different rate for each need, and depending on whether they are sleeping. Then, they'll check if they have to earn money - they earn their salary every day. Finally, the UI is updated. Each need has a progress bar that goes from 0 to 1. The UpdateProgressBar function also sets the color of the bar in red id the threshold of the need is surpassed, so we know the neighbor is going to prioritize satisfying it.

Feature C. Neighbors decide which need is the most important and search for the closest waypoint that satisfies it, go to it and satisfy themselves when they arrive at a different rate.

To decide what to do, I use a Behavior Tree. To assign a Behavior Tree to a "Pawn" (a character) we must create an AIController and assing it to the blueprint.

My AIController is named AI_Villager, inherits from VisAIController and is the one that runs the Behavior Tree.

The Behaviour Tree uses tasks and decorators to decide which action to run every time an event triggers.

I arranged decorators by what I think is more important to satisfy first, so neighbors will stop their actions to satisfy the more important needs when they surpass the threshold: first go to the toilet, then eat, drink, slepp, bathe, and finally play. Every decorator checks whether the value of the need surpasses its threshold. To attack a task, the neighbors have to search for the most convenient checkpoint, go to ir and satisfy their need.

The task BTT_FindBestMapPoint iterates all waypoints of the scene and if a waypoint is suitable, compares it to the previous best free and overall candidates to update them. When it finishes, it chooses between the closest waypoint and the closest free waypoint depending on the distance difference and the neighbor's greediness. 

To know whether they're interested in a waypoint, it must be of the corresponding type, it must be free, they must be able to afford it and it must be cheaper than the previous candidate. The cost is the distance from the waypoint modified by tastes and extroversion.

When they arrive to the waypoint, a task reduces the value of the corresponding need. When it reaches 0 or a new need emerges, the waypoint turns free again and it cost is discounted from the neighbor's money.

Feature D. Each neighbor has a different routine to fulfill when no needs are to be satisfied.

To create a routine - a set of actions the neighbor's will do when they are fully satisfied - I decided to give them tastes. When they have free time, they'll choose one of their tastes at random, search for the closest waypoint of that taste and go to it, bypassing whether it is free or it cost because they aren't going to use it. When they arrive, they'll wait some time before choosing another waypoint. Every neighbor has at least 2 tastes so they can walk around.

Feature E. Neighbors keep in mind the player to ask them money to buy food and drink or have fun, if they decide so based on their personality parameters.

The interaction with the player has 2 benefits for the neighbors: the player can give them the money they need to buy food and drink, and they can have fun talking to the player. The distance to call the player and the amount of fun earned depends of the extroversion parameter, being 0 avoiding the player and having no fun, and 1 searching them in the full range and totally empty all the boredom bar.

The Behavior Tree has been updated. On the one hand, when the neighbor is hungry or thirsty they check if the player is inside their range. If they are, the neighbor will call them out and receive the money they need to use the closest waypoint, so it becomes free. This money can be 0, but even so, their boredom is reduced, so it's always beneficious.

On the other hand, when the neighbor is bored, they also check if the player is close. If they are, they will go talk to them until their boredom is done for. I use the simple parallel node to continue going to the player while the neighbor reduces their boredom.

Feature F. Weather interrupts the neighbors' actions if it rains or the temperature is too high or too low.

Weather influences in the neighbor's behavior, completely interrupting them. Their parameters control when the whether affect them. They can care about the rain or not, and will be cold or hot at different temperatures. In case the wheather interrupts them, an icon in the UI will appear. If it rains and the neighbor cares about the rain or they are cold, they will shelter inside buildings. If they are hot, they'll go to the beach. With the waypoint structure, I can't know if 2 interior waypoints are in the same building, so it is possible that neighbors change buildings to satisfy a need that is not available in the current building. If they want to use a waypoint outside, they'll wait until it stops raining or the temperature is higher. To implement this in the Behavior Tree new nodes have been added as the most important ones.

These decorators are more complex: they are composite decorators. They run logic operators with other simple decorators. 

Results

The results are satisfying, the behavior is as expected. The neighbors correctly satisfy their needs and run their routine. Balance may need some tweaking, but it is valid to test all features.

I found some deadlocks. When it rains and the neighbor wants an exterior waypoint, the target is changed every frame because the rain sets an interior waypoint, and then, as the rain is dealt with, the neighbor finds the next waypoint to satisfy their most important need, which is outside, and so on. The result is OK, they simply wait inside the building until it stops raining, it's just not appropriate. Another deadlock is that the neighbor is hot and it starts raining, when something similar happens. I didn't expect the last one. The task BTT_FindBestMapPoint can fail, and it was because all neighbors where thirsty. The waypoints are market as occupied the moment they decide to go there, so it is possible that all drinking waypoints are occupied simultaneously. The result is that the neighbor stands still until a drinking point is available again.

These deadlocks are not bugs, but they trigger events every frame and fill the console with messages. So I chose to print less info.

Unreal Engine's navigation doesn't keep in mind other agents and their avoidance is not good. It seems it can be fixed with a Crowd Manager, but I couldn't make it work.

Performance is not good, it doesn't even reach 25 FPS, but I suspect it's because of the graphics - mostly the water. We can see exactly the time the Behavior Tree, which is a bit more than 6 ms. I don't know if it's good or bad because it's very good for this project, but maybe in a real game there is no time for such long calculations. Anyway, I'm sure the Behavior Tree could be optimized a lot.

Conclusion

The feeling this neighbors give is more robotic, but I think its due to the time going so fast. In Animal Crossing, the time flows at real time. I think that taking this into account, a new layer is given to them. They have tastes to walk in their free time and eventually they have to leave their job or leisure to go to the toilet or eat. In the original games, shop keepers can't be seen when their shop is closed.

My opinion about the viability of this system in a real game is that I think a fixed schedule would win against it due to uncertainty and performance. However, I believe it's possible to implement it as the results are good and Unreal's Behavior Trees are cheap. The improvement I would do is a short-term prediction to avoid, for example, go to sleep if you predict that you will be hungry at midnight and you'll have to stop sleeping.

Finally, choosing Unreal Engine has resulted in a really beautiful looking project thanks to its rendering engine and premium assets. Here are some screenshots.