It’s a beautiful day in my sweet little Unity project when the NPCs are not broken. Sadly, it has been a while since that happened. In my tram horror game, the NPCs are considered to be the hardest part of this game to develop. Atleast, considered to me. And I really suck at art.
Their roles
There are two types of NPCs in my game: TramNPCs and WorldNPCs. As you may have guessed, the TramNPCs are the most important ones that go in and out of the tram at tram stops. And WorldNPCs roam the world of Halte.
As the core of the game, atleast the TramNPCs, they support the worldbuilding, atmosphere and the core narrative. You, as the player, ride to tram stops, you let the TramNPCs in and you ride away, Seems easy enough.
You can talk to these NPCs and they can talk more about themselves, the environment or what they ate for breakfast. All very interesting things and necessary to the plot. To be honest, this is all basic horror game stuff. It’s not like I’m the first person to ever make an NPC talk. However, I feel like the actual AI and narrative design of it, is atleast a little bit interesting.

How they were made
As of this moment, the NPCs took the longest to develop. It was honestly a pain, especially during the early stages. If you haven’t seen the video I made about it, you should definitely check it out to see all the bugs I endured. Or don’t? I don’t know. Use your free will. Just know that I’m happy it’s mostly over.. for now.
“This is gonna be really easy. I’ve made NPCs before with NavMesh. It’s gonna be a breeze.” That’s the first thing I thought when I started to work on the NPCs. In theory, it is easy. Most game engines actually have plugins that will do most of what you want an NPC to do. However, when you combine that with a moving platform.. there is nothing left. Fast movement, rotation, movement within the tram while the tram is moving. Everything was a challenge. I ended up trying a dozen different techniques, even resorting to free versions of paid plugins to check whether it would be worth it to buy a plugin. But nothing really worked out.
It was not until I took a step back and viewed the monstrosity I created from afar, that I saw the light. I was too focused on AI. I want very simple pathfinding, which does what it’s supposed to do. Nothing more. I wanted NPCs to go around eachother and around the player too. But that may have been just too much. So I did it differently.
When the NPCs are entering the tram, nothing is moving. That’s nice, so that means I can use normal NavMesh. And whenever the NPCs enter the tram, they completely switch systems. They change from complex NavMesh AI to a primitive waypoint system. They simply go from point to point until they’re at their destination. And when they’re eventually there, they simply sit down and ‘Mission Accomplished’. And with some easing, it doesn’t look half bad.
I then combined this with a blocking system, which completely stops movement when the NPCs are being obstructed. This actually worked for a while. When i got in front of an NPC, they simply stopped and that enabled their dialogue option. But when I wanted the NPC to stop, based on more than 1 reason, it obviously stopped working. After making it so the NPCs also stop when the tram is not ‘ready’ (when the doors are closed or when the tram is not aligned with the tram stop correctly), the NPC could be reactivated after I blocked them. It makes total sense. The NPC is blocked because I am talking to them, but then the doors of the tram open or the tram stops and they forget about any other block because I used a simple true/false.
So I created a movement lock system. The NPC simply pauses/resumes movement (or the ability to speak) when 1 or more locks are active. These locks can easily be added to. Right now, I have locks for being blocked by another NPC or the player, locks for being talked to and locks for when the tram doesn’t completely line up with the tram stop platform or when the doors are closed. It actually ended up working great. When there are 1 or more active locks, the NPCs will stop, but they will also be able to be talked to by the player.
All the NPCs have unique dialogue. I’m still figuring out to what extent, but the basics are pretty straight forward. The TramNPCs have a specific set of dialogue. One for entry, 1 when sitting down, 1 when the ticket scanning is done and 1 when exiting. This makes the NPCs feel more real, with minimal effort (besides some masterful writing of course). These features will be added later to the game and it will also be explained some more in future posts.
Final thoughts
That’s it. I’ll stop rambling about the NPCs for now. At this moment, they somewhat work.. until I create some new feature for the tram or player and everything stops working again. It truly is an endless task. I wouldn’t be surprised if I end up working on the core AI script one day before release.
Hopefully you got something useful out of it. I still don’t really know how to balance simple explanations vs in-depth dev talk in this blog. Who is my audience here? Low attention YouTube watchers or fellow devs? I’ll just keep on experimenting until that core audience is happy, whoever that may be. Are you happy? .. in life?
Anyways, see ya!
-Luxo