#8 Color Palettes & Physics Problems
Welcome to the eighth devlog!
This time, I want to explain a certain workflow I’ve adopted that greatly improves in-game performance AND my work speed/efficiency. Additionally, I want to add some quick remarks about player movement and why I switched from a Kinematic Body to a RigidBody with so-called “custom integrator” (it’s way simpler than it sounds, no worries).
As I was working on the first assets of the game, I remembered some art streams I watched a while back. (I think it was the art stream for Parkitect.)
That game has a similar style to mine: low poly, simple models with flat colors, etc.
One thing the artist did seemed very interesting to me: he used a single, low-res texture with a color palette for almost ALL assets. I thought: hey, that sounds nice, let’s try it! And so I did.
I created a 128x128 png file with a color palette. Right now, the palette is only partly filled, but as the game progresses, I will add any new colors I need. (Yes, I work from top to bottom, not left to right per color. Why? I don't know, it just happened, and I feel comfortable with it.)
Every asset (except for the “hero assets”, the ones that will be large and special) uses this exact same image as their texture.
I then UV unwrap the model (which basically means turning the 3D shape into a 2D image) onto this texture, scale it down, and place the right faces on the right colors. For example, the brick walls use two different shades of the same red color. To achieve this, I simply selected all the faces that belonged to one color, and dragged them to the right position on the color palette.
It works. Really well actually. There are just so many benefits to this workflow:
- I only need a single (low-res) texture for 99% of the assets
- This increases game performance: it reduces memory usage, draw calls, and what not
- This improves the look of the game: because everything uses a carefully picked color palette, the look will be very consistent.
- This makes my work faster: I don’t need new textures, UV unwrapping and placing faces on the right colors really isn’t a very difficult task. And, if I ever need to change a color, I can just update the texture and everything automatically updates!
You must be wondering: surely there are some drawbacks! And you’d be right:
- If I ever need to texture something (instead of making parts of the object solid colors), I can’t use this technique. I’ve done some tests with textures and low poly meshes for my game, but I wasn’t satisfied with the results, so I’ll probably rarely encounter this problem for this game.
- Because all UVs share the same palette, they are very tiny and overlap often. If I were to bake the Ambient Occlusion map (which I explained before – it determines the shadows on/within the object), this would result in a blurry mess. But the workaround is relatively simple: you can have multiple UV unwrappings, so I simply unwrap it twice (in different ways), and use the 2nd UV for any maps I want to bake.
I’m really happy with this workflow. Making assets is a lot smoother now, and the game also runs much smoother.
There’s a problem in all physics games: we want the player to adhere to the laws of physics … but we also want the player to move quickly, do incredible jumps, be very responsive, etc.
As a developer, you’re always searching for the balance between realistic physics (collisions, bounciness, gravity, etc.) and physics that are fun/easy to play.
Usually, it’s recommended to make the player a so-called “Kinematic Body”. It collides with the world around it … but nothing more. You need to program gravity yourself (if you want it), you need to say what should happen when it collides with a specific object, etc.
This works fine, in most cases. It worked fine for me during the first weeks of development. But then I encountered … the seesaw strangeness! (Followed by the crane catastrophe!)
One of the first interactive objects I created was the “seesaw”. You could jump on one of the ends, or walk over it, to activate or deactivate a certain switch. For example, if the left side was down, an elevator was going DOWN, but with the right side down, it went UP.
When I tested this … nothing really happened. Sometimes the player could stand on the seesaw like it was made of stone, other times it did work but only very slowly. Why was this happening? Well, I programmed the “Kinematic Body” to detect if there was floor underneath it. If so, it should stop going down (because of gravity). As a result, the player exerted zero force on the seesaw as it stood on top of it.
Now, this could be easily fixed. I checked specifically if the player was standing on the seesaw, and if so, gravity remained turned on. But this still resulted in a choppy movement, where it looked as if the player was jumping to get the seesaw to move downward.
This could also be fixed, by snapping the player to the seesaw, until you move/jump away.
Hopefully you see the problem here: a bunch of fixes were needed to make the player work with a single, simple object. I don’t want that. It becomes a mess, performance becomes a problem.
The final nail in the coffin of the “Kinematic Body” was when I tried to jump on the platform, which was held up by a rope attached to the giant construction crane in the center of the level.
(I don't have image/video for this, as I was TOO FRUSTRATED to think clearly. So here's an image of the crane and its platform:)
No matter what I tried, the player SMASHED into the platform like it had infinite weight, glitching the physics all over the place. I tried the same tactic as with the seesaw: it didn’t work, because the platform was too wobbly. I tried many tactics, but I just couldn’t get the player to jump on the platform without the platform suddenly dropping ten kilometers.
Rigid to the Rescue
So I switched to a normal body, aka RigidBody. This body follows all the rules of the physics world, which means it automatically jumped on the platform without any problems.
However, it can be hard to control such a RigidBody. For example, if your player is walking, but you bump into an object ever so slightly, the player might just bounce back, rotate, fly into the air, whatever is realistic for that type of collision. We don’t want that.
So I wrote a custom integrator, which simply means “a piece of code that overrides some of the physics rules, which is executed at the proper time during the physics calculations”. It …
- … locks the player so it can only rotate around the Y-axis
- … overrides the player’s velocity to follow the input from the player (but keeps the original Y-velocity, so gravity and everything works correctly by default)
- … rotates the player to face the direction in which he walks
- … reduces friction to a very small number, so the player doesn’t get stuck when it accidentally brushes against a wall or something.
- … increases gravity scale by a certain number (it’s currently 4, might change), so that the player movement is a bit faster and snappier => more arcade style, which fits the game.
That’s it! The player moved identical to before, but I don’t need any fixes or custom code to make it work with the seesaw or the hanging platform.
The only thing I needed to do, was write custom code for moving platforms. Otherwise, the moving platform just slid out from underneath the player. (Because the friction is so low, the player doesn’t follow objects that touch it.)
But this isn’t a huge deal: the player detects which object is underneath it, and if it’s a moving platform, it asks for the current speed of the platform. This speed is added to the player’s VELOCITY, so it follows the platform, but can still move around freely.
Get Package Party
Leave a comment
Log in with itch.io to leave a comment.