My AI is utility-driven in a similar pattern to The Sims, where all unique behavior is coded into interactable objects, and the only thing an NPC does is decide which object they wish to use, path to it, and activate it. This is deceptively powerful, as I can extend nearly any desired behavior by creating a novel object and shaping constraints leading to its selection.

The challenge I'm having with this approach is giving the illusion that NPCs are moving around when the player isn't nearby. The game runs a 24/7 clock and seeks to have each NPC go through the motions of maintaining a regular schedule: going to work, going to bed, and randomly doing weird things in their free time to preserve the illusion of unpredictability. This is implemented with a dict(float time, Appointment appointment), which acts as a global behavior queue and is called every time the in-game clock changes to teleport each AI who has an appointment to use an object to that object's position. This works well enough for prototyping other systems, but it isn't very convincing: you never see NPCs moving through the world, and when you're familiar with a few specific characters it becomes very obvious that they're teleporting around when you can't see them.

Is there a better way to simulate movement around a world with a large number of NPCs, or am I better off keeping my current queue-oriented behavior system and writing an entirely different system to fake movement? My optimal endpoint would be a system that can order NPCs to be at any location, at any time, and trust them to move there in a convincing way, but I worry I'm putting too much detail into a simulation that could fake the same behavior more convincingly with a simpler solution.


1 Answer 1


Make a list of things a character would do at certain hours and be sure to have multiple activities at every time. Say at 08:00 they eat breakfast or shower and at 09:00 they commute to work or work from home. Now you keep also note how long a NPC would take to finish the task. You keep track of the last time the player was able to see the NPC. If the player returns within the time it would take to do the task you would make the NPC do the current task, but if the player returns after a couple of ingame hours you would teleport them to their new task or if it's a traveling task you would calculate the percentage of distance they covered and teleport them to that location.

The multiple task possibilities at a certain time will reduce the pattern the player will be able to see. To reduce the randomness multiple lists would be created that feature different tasks which are logical follow ups of the previous task.

Example: At the start of the day choose either list 1, 2 or 3.

List 1

07:00 - Wake up

07:02 - Go to Toilet / Drink a glass of water

07:05 - Drink a glass of water / Go to toilet

List 2

07:30 - Wake up

07:40 - Make breakfast / Watch a cat video

I trust in your ability to make list 3 yourself.

  • \$\begingroup\$ Hmm, wouldn't this be really computationally expensive? One of my goals in focusing on NPC position over behavior was to make the simulation as low-overhead as possible: my thinking was to basically reduce inactive NPC's thought process to "At time A, be at location B," then if the player actually loaded the chunk location B was in, every NPC in the area could quickly poll the nearby useable objects, teleport to one, and pretend that they'd been busy this whole time. \$\endgroup\$ Commented Mar 13, 2015 at 16:46
  • \$\begingroup\$ It would require some memory, but should not be computationally expensive. It would only update when inside player view/range as it does not actually move when the player is out of range but simulate movement once it is in range. You would be limited by memory, not by CPU. I can easily see this simulating a couple hundred of NPCS. And since you only simulate them when inside range it would not be more than 50 or so depending on the density of your city areas. \$\endgroup\$
    – Eejin
    Commented Mar 13, 2015 at 17:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .