NPC Movement Example
One of my worst habits is refactoring when I should be moving forward. I’ve got a kind of OCD about organization, especially in the case of Unity where being disorganized is easy, and can come back to bite you in the ass pretty quickly.
I spent some time re-thinking and re-working my NPC movement setup. I tried Playmaker, but ran into a snag that I couldn’t grok, and the jumping back and forth between Playmaker and scripting turned out to be no as worthwhile as I’d hoped. Had I committed to Playmaker and attempted to re-model the whole NPC experience in that method, it might have worked, but that would have sent me back to the very beginning of NPC movement.
Instead, I broke out the individual class movement into different scripts. Merchants, police, and miners all have their own movement scripts, which effectively divides them as GameObjects now. The benefit is that each script can be worked on without worrying that I’m going to break the other two. The detriment is that I have a lot of duplicate code in some places.
To cut down on that, I diagrammed my control scheme as it stands right now:
This gave me a clearer picture of how things should be organized by limiting me to a “communications chain of command”. Previously, everyone could talk to Data Control (soon to be renamed Game Control) in order to get data from Master Database. Now, only components on Sector Control can speak with Data Control, and only Data Control can speak to Master Database. I was able to move some generic functions into the NPCController component of the Sector Control game object in order to streamline some of the scripts, and the SectorController component of the Sector Control game object now takes over the responsibilities of some of the functions that Data Control was handling (technically, SectorController only aliases calls to Data Control, but it standardizes the *Controller references I need to make on individual elements in a scene).
I also had some issues with triggers misbehaving. The solution was to turn all trigger objects into a two part object: the main model, and a spawn point. Miners gave me the biggest headache, and are what prompted the change. In the new system, the asteroids gain any number of dynamically created spawn points that the miners can spawn at and return to, while stations got the same spawning functionality that jumpgates had for when NPCs “undock” from the station. This allowed me to move from the powerful but complex OnTriggerEnter/Stay/Exit control scheme to a “distance to target” control scheme that has the NPC taking action once it’s within a certain distance of it’s current destination. This also allows the NPC to not get waylaid by other potential action objects if it cuts to close. For example, the miners who had to cross the asteroid’s trigger to get to the station were immediately re-docking at the asteroid when they started to move to the station because activating them inside the trigger fired the OnTriggerEnter event, preventing the miner from ever being able to leave the asteroid.
Here’s a video which explains all of this, with examples of the new spawn points and distance to target system. I didn’t think of colorizing the individual NPC prefabs, so I pause and highlight individual items as I talk about them. Hopefully it’s not too confusing.