Building of Little Bear | Design Process
The Concept:
The core concept was based around general local or couch co-op games, where two players have minimal interaction options but need to collaborate to complete the level.
The game is a 3D top-down local co-op game that you can play with 2 people on the same local network. You are tasked to clean up the playground space by picking up objects and dropping them in the correct locations.
Note: The main focus of this project was to learn to work with Unity’s Netcode Library and Multiplayer Tools, as a result, the level design was kept to a minimum.
Story:
You are a part of Little Bear’s Cleaning crew, a crew that goes around cleaning up messes. You are tasked with cleaning up the playground.
Characters:
Bear 1/Bear 2 - Play as a Bear to clean up the messes.
Story Progression:
Pick up the color-coded balls and drop them at the color-coded platforms to clean up. Avoid and navigate around obstacles, and collaborate with Player 2 to clean up faster!
The Motivation:
The main focus of this project was to learn to work with Unity’s Netcode Library and Multiplayer Tools, as a result, the level design was kept to a minimum.
Design Process:
Project Length: 2 weeks
Tools: This project was made with Unity with a 3D Universal Render Pipeline (URP) template as the base.
Packages Used:
- ProBuilder
- CineMachine
- TextMeshPro
- InputSystem
- NetCode
- MultiplayerTools
Other tools used:
- Concept: For sketching early-stage level design
- Adobe Express: For the creation of logo assets on the Itch.io page
Task Tracking & Source Control:
- JIRA
- Github
The JIRA Scrum project consisted of 1-week sprints and several epics under which stories were assigned.
Epics:
- Game Engine Setup
- Player Actions
- Level Design
- Game Design & Architecture
- Networking
- Documentation
- QA
Base Level Design:
The original base-level design was to create three rooms in a house - Hall, Kitchen, and Laundry, but certain ideas were split further down to meet the time constraints.
For the Barebones prototype, I decided to start with a single room - the hall. The environment is a room with 4 walls. 3 are visible and one wall in direct view of the camera is hidden.
Base concept/view:
Blockout with ProBuilder:
Basic shapes in approximate sizes were created to get a general understanding of the space - and check if it was too big or too small for two players to navigate.
Learning about Networking
When I started brainstorming the concept of the game, I want it to eventually expand to incorporate a multiplayer networking design. To gain the knowledge required to build multiplayer, I did a lot of reading and summarized a lot of notes.
Below are some of the core concepts and eventually the design decisions I took.
Note: These notes are based on my understanding, so please correct me if there was an error!
Understanding Server and Client Architecture
There are different ways to handle communication among players. Some of the common ones are:
1. Client Server
1.1 Server Authoratative
One of the common designs used in online multiplayer games.
- All the gameplay logic resides on a game server.
- The client communicates and sends their inputs to the game server.
- The game server then updates the game state and returns the updated values to the client.
- The client then uses these values to update itself.
From the above, we can see that there is a possibility of a delay from when the user performs an action to when the update is made on the user screen. To handle this, one option is Client Server Prediction
1.2 Client Server Prediction
In client-server prediction, as the name suggests, the client predicts something. This something is the client player action between the time when the inputs are sent to their server and awaiting a response back. The client predicts a possible position for the player based on its previous actions, e.g a ball bouncing in a direction at a speed of 5 m/s. The client locally predicts it will continue in the same direction at the same speed until it receives the updated position from the server and then updates the local value to the server value. While this is great, it also introduces the next problem, which is what happens if the local client prediction was different than the one server eventually sent back.
1.2.1 Rubber Banding
Rubber banding is when the local predicted position on the client end is ahead of the server result, when the data is sent back to the client, it causes the player to "rubber-band" back to where it started from or a few steps back from where the player currently is.
1.3 Client Server Prediction with Circular Buffer Queue
To avoid this, we can use a data structure. The last few snapshots of player input are added to the buffer. When the updated result from the server is returned, we compare the sequence number with those in the buffer and discard any snapshots that are older than the server sequence number.
2. Peer to Peer
This is one of the earliest protocols used in multiplayer games. Here there is no Client / Server structure, instead, each client sends its game state to all others and awaits information from all other clients in the network before proceeding further. The drawback is that the latency is not great because of the waiting to hear back from each of the players.
There are a few variations and strategies you can add in for Lag Compensation, Entity Interpolation, etc.
Formulating Design Questions
Formulating these questions helped me identify the important aspects when considering networking.
" I want two players on a screen that can be controlled separately"
- How are you planning to establish this connection?
- How are you planning to authenticate the users?
- How are you planning to keep track of the number of users in the game?
"I want Player 1 to pick up an object and have Player 2 see this action"
- How many objects do you estimate to have on the game screen?
- Is each of these objects important? - If there are issues sending information about an object, do you want to discard or retry sending the information?
- Can you identify objects that are important to the game state?
"....in near real-time"
- What is the delay latency that you're okay with within the game?
"Object A is very important, its changes need to be similar as possible across two players of the game"
- Can you identify core gameplay data?
- What things does a player NEED to know about this object if they join mid-game? - It could be things like the number of objects of this type that have already been picked, the percentage interaction with this object, etc.
Design Decisions and Tools for Little Bear:
Netcode was used as a library, among the players, the player that joins as Host is treated as both Server and Client. All other players that join later are considered clients.
Core gameplay loop
The core gameplay loop is as follows:
- Player 1 joins as a “Host” on Local Network. Multiple Scriptable Network objects are spawned in the space
- Player 2 joins as a “Client” on the same local network.
- The player can pick up an object with the E key for Interaction
- Players use RayCasts to identify collisions
- Players can drop an object with the Q key.
- Players can “clean up” an object by dropping it on the color-coded surface to clean up.
Core Game Data:
- A number of players joined
- Number of objects to be picked and their positions
- Percentage of tasks to be completed (Future feature)
- Time Remaining for Level (Future Feature)
Multiplayer and Refactoring
- Objects:
- Each object is a Scriptable Object type, assigned with a sphere collider, network object, and network rigid body. All Pickable objects were assigned a Layer “Pickable” which is later used with RayCasts. As the number of total objects that need to be synced was less than 20, this approach was okay, but as the number of objects increase, this approach could be improved further.
- Picking up Player Object:
- Single Player: This usually involves creating a “PickUpPoint” gameObject in front of the player and then adding the object as a child of the parent. However, with Netcode for GameObject, clients cannot do this directly.
- ServerRPC with ownership as False was used to allow this.
- Single Player: This usually involves creating a “PickUpPoint” gameObject in front of the player and then adding the object as a child of the parent. However, with Netcode for GameObject, clients cannot do this directly.
- Sync-ing object Positions:
- Each object that was required to propagate information across the network was assigned a Network Object type and added to the Network Manager. A client Network Transform was used as it was a local co-op only.
- Dropping Objects:
- ServerRPC: Uses Raycasts to identify the network Id of an object with which the collision took place, gets the network Object and transforms position, and reparents it.
- Dropping Objects at the correct location:
- Despawns a network object when dropped near a particular object (color-coded drop area)
QA and Testing
- Prevent Multiple object pickup: To avoid the same player from picking up multiple objects at the same time, conditions were checked to see if an item was being held before a player can pick up a new one.
- Avoid (some) Client-side network latency: Despite being a local co-op there was a significant network latency that could be noted when playing with 2 players. To reduce this during object pickup on the client side:
- The client requests the object to be picked up by the Server
- Immediately picks up the object on the client side
- Receives the updated object position from Server
- Implements the updated object positions on the client side
While this approach can be modified with the addition of a circular buffer to maintain along with Tick rate and positions, this would be explored in future features and projects.
Testing of the game involved playing with 2 players and creating a “Bug Report” Jira ticket containing the following:
- Description of Bug
- Steps to Reproduce
- Expected Result
- Bug reproducibility rate
- Assign a Severity, Logs, and GIFs/Videos of the Bug
Redesign:
The initial concept was redesigned to a playground-like scene to fit better with the objects that were being picked up and dropped.
Art & Music:
As the focus of this project was to learn and create a simple networking sample, I used the KayKit Character Animations and Mini-Game Variety Pack by KayKit and Music by Olexy from Pixabay.
Conclusion:
The Good:
- Learned about networking concepts and networking with Netcode
- Learned how to create and prioritize features based on impact on the game and Minimum Viable “Interactions”, QA tasks
- Learned to work with Player Animations, the new Unity Input System, CineMachine, Multiplayer Tools, Netcode (Network Rigid Body, Network Objects, Network Variable, Network Manager, Server, and Client RPC) URP, ProBuilder, DOxygen, Game Design Document
- A completed prototype within a 2-week timeframe
The Could be Better:
- Better Game Play Loops
- More work on Client Side Prediction
Thank you for reading! Feel free to leave your thoughts/feedback on the process!
Leave a comment
Log in with itch.io to leave a comment.