top of page

Splatterfield

ROLE

Solo

GIT REPO

DESCRIPTION

Splatterfield is a 1v1 Multiplayer PVP game inspired from Splatoon! Focus on killing your enemy over and over with blasts of paint, paint as much of the world in your colour, and paint claimable areas to get points!

Both the paint system, and multiplayer integration are made modular so they can be used in future projects.

TIP: Hover over images to play videos

Project Length

6 of 9 Weeks

GENRE

1v1 PVP Multiplayer

PLATFORM

PC / MODULA ASSET

HOW PAINTING WORKS

Painting Overview

To create nice looking splats, like in Splatoon, you need to know where the paint is in 3 dimensions., otherwise if paint is splattered onto a wall object, and there is a floor object right beneath it hat is in splatting range, only the wall will get paint on it.

 

So to do this I created a shader graph in HDRP that takes a 3D texture mask the size of the level. When a splat occurs, the world position is converted into the 3D texture mask's pixel position (with randomness  so its not just a square blob) by script , with the player that shot it's assigned colour, eg (1, 0, 0, 0) for player 1 (RED), and (0, 1, 0, 1) for player 2 (GREEN) . Realisticly this can be any RGB to create thousands of teams. The Textured 3D mask is then updated and the shader graph does the rest.

 

Where the 3D texture mask is GREEN it will lerp to player 2's paint colour will now be visable (with noise to make it look splatty) on the shot object/s. Where it isn't GREEN it will lerp to be player 1's paint colour.

 

So now everywhere without player 2's paint colour will be player 1's colour, not the original texture. To fix this I then do a lerp another lerp. Where the Texture 3D mask has alpha (RED or GREEN) paint the paint texture, where it isn't keep it as the original texture.

Disadvantages of this Technique

Performance for a 80x80x80 area is OK. Spam painting in single player with a 3060 TI makes the frames drop from 120 to 100 in editor. A 160x160x160 area drops from 120 to 40, and a 320x320x320 area, fps drops from 120 to 20. Updating a texture with the texture format as RGBA32 is very expensive because each colour channel is stored as an 8-bit value. I'm currently working on reducing the GPU load by converting the texture format to R8, which would make painting 4x more performant. This with the introduction of a shooting cooldown will make the painting way more performant.

Another drawback is, this shader doesn't work with moving paintable object. Since the painted area is stored on a static 3D texture, moving a paintable object with paint on it, will not move the paint with it. To fix this issue, I've made a similar shader using a 2D texture mask, indipendent to each object using it. Splats won't be able to cover multiple objects with this shader, but with clever level design, this won't be an issue.

HOW MULTIPLAYER WORKS

Multiplayer Overview

To integrate multiplayer into my game, I decided to use mirror. I use the player gameobject to update the player's movement, animations and camera over the network. Mirror has components that automatically update these for the gameobject they are attached to, as long as 'Client Authority' is checked on all of these components.

I'm using an Inverse Kinematic Controller to get the player to aim their weapon at the mouse's world position. To achieve this I need to use Mirror 'Attributes' to call functions across the network. 

 

These attributes are:

  • [Server] / [Client] tags can be used for the server-only and client-only parts

  • [Command]s are used for Client->Server communication

  • [ClientRpc] / [TargetRpc] for Server->Client communication

  • [SyncVar]s and SyncLists are used to automatically synchronize state.

bottom of page