Better AI, creative mode, a new look, and more.
31 August 2018 by Jarryd Campi
Passengers in SkyCruise have always been a little aimless, generally just wandering around and using the objects around them. I had some spare time this month, so I looked into adding some new behaviors, like dancing, looking out windows, talking, etc. The AI system has grown organically with the game in some unintuitive ways, and new features like passenger lines, emotes and running away from hazards pushed it to its breaking point. It was a huge spaghetti-like mess of hard to parse code that only I knew how to control, so I decided to rebuild it.
You won’t see any major changes other than the new behaviour, but everything has been rebuilt to be more modular and easy to expand. I spent some time on Before when I first joined Facepunch, and I really like a lot of systems they built for their AI, so this is a vastly simplified take on their system. Things are about to get nerdy, so if you don’t care feel free to skip ahead.
Essentially the AI is broken up into three parts: Target Generators, Actions and Action Chains.
Target Generators are responsible for finding a goal for an AI to do. This could be a position to wander to, a prop to use, a fire to put out, etc. These run immediately.
Actions do most of the actual unit logic, and are responsible for moving units, picking up objects, using props, looking at things, emoting. These can take time to run - a “Move To” action won’t complete until the unit has arrived at their destination.
Action Chains are the final piece and tie everything together. Every chain has generators and a sequence of actions. When evaluating which behaviour should be run, the unit will process the generators and if they find a target will then step through each action in the chain until it’s done. A simple chain might be sitting down: find a chair, walk to it, sit down, wait, then stand up.
Chains can have multiple Target Generators in And/Or configurations and each generator writes its target into a named target slot. Each action can then read from a specific slot. An example of that is in the more advanced “Move Luggage” chain run by staff. In this case it writes the luggage to be picked up as well as the destination of the luggage.
The benefits of this system are pretty huge. When implementing new behaviours I no longer have to write lots of boilerplate go here/go there code. I’ve also standardised several systems in this process (the staff job system used to be completely separate from the regular AI system). This has also helped with debugging, instead of having to step through spaghetti code in Visual Studio, I can just look at the passenger in Unity and see exactly what it’s doing and where it’s at in that process.
Another new feature this month is Creative Mode - a new, low pressure way to play the game. Essentially an endless money cheat, Creative Mode should let you build whatever ship you like without the need to worry about your income or sustainability.
Game Options are a new menu you can access when setting up a new game that modifies how your game works. You can make things a little easier by making passengers easier to please, or maybe increase the difficulty by increasing how often your props break down. There’s only a few options right now, but if you have more ideas feel free to share them in our Discord channel!
One lingering job I had to do thanks to the wall changes we made earlier this month was the floor painting system. The floor paints still used the old wall grid size, and this was obviously not good enough now that you can build walls anywhere you want. My first attempt to fix this simply involved shrinking and duplicating the old surfaces you painted on, essentially turning one paintable surface into 25. Unfortunately this tanked performance and was a pain to paint on, it also would have had a lot of overhead when saving/loading the game.
The solution I ended up settling on was generating a dynamic mesh at runtime for the floor, based on a list of points. Each paint type gets a unique mesh which cuts down on the number of objects and renderers in the scene. This means that painting is essentially removing a point from the old paint, adding a point to the new paint and telling both surfaces to rebuild.
From there it’s a pretty simple mesh generation. Unity has some pretty simple to use API’s to achieve this. I essentially just build a list of Vector points and triangles and then pass them to the Mesh component.
The final challenge was updating our shaders to work in world space. This was much easier than calculating repeating UVs for the mesh. Our custom shaders in SkyCruise were mostly built in Amplify Shader Editor which has a handy Triplanar node that gets the job done.
This system made it much easier to implement a long requested feature: drag painting! Just click and drag to paint large rectangular sections of your ship in one move!
If you’ve been keeping an eye on other Facepunch prototypes you’re probably aware of Tub, a co-op platformer sandbox Garry has been making. There’s been some talk internally about using the art and character style of that world in more Facepunch games, especially since it’s already based on the Wiseguys character. So the plan going forward is to bring this art into SkyCruise!
Clothing variety for the Tub character is still being fleshed out, so for this month you’ll still see the old low poly passenger models. I did manage to bring in a few new props with the new art style, mostly to get a pipeline for bringing this art in up to speed. Going forward it should be relatively easy for me to keep our art in sync with the other projects, and there’s a long list of new props and character clothing for SkyCruise that’s being worked on.
That’s about it for this month! All of this stuff is this month’s update which is out now. Already a tester? Be sure to restart your Steam client to ensure you’re on the latest version. I’ll be sending out some more keys, so if you’ve signed up be sure to check your inbox. Haven’t signed up yet? You can register as a tester here, I send out keys once a month. Have fun!