Game Architecture - alexitsios/Calamity GitHub Wiki

This page is a work in progress.

Introduction

What is this?

  • An ongoing reference and guide for developers when creating content using our systems in Calamity.
  • A technical document providing comprehensive information on our systems.

Basic technology for everyone.

Everyone should know.

Design Principles

  • Our top goal is build a great game!
  • We want our code and assets to be easy to maintain and flexible to changes.
  • We're building a framework that can support all 3 episodes of Calamity's storyline.
  • Our focus is on developing technology that is easy for designers to work with and promotes teamwork across different areas of the game's development.
  • Our technology's modularity allows for creative exploration in design and provides numerous opportunities to innovate.

Examples Of How We Develop Modular Systems

Project Management

  • We manage our project and tasks using Github's Project and Github Issues Kanban system.
  • We rely on Google Docs and other third-party tools for areas of design.
  • Our engineers collaborate to break down large goals from the GDD into smaller ones.
  • Smaller goals are documented in Github Issues and assigned on a volunteer basis through a Kanban format. Engineers choose tasks that interest them or suit their skills.
  • Code and assets are submitted through our version control model. #HowToUseVersionControl

Tasks with Github Issues

What is this?

  • Github Issues is our system for managing tasks for the project.
  • We operate in a volunteer Kanban format. Meaning tasks are discussed as a group, then people assign themselves to tasks where they're best suited or would like to collaborate.

Get Started with Tasks

  • Create a GitHub account: If you don't already have one, create a GitHub account. This will allow you to join the team's repository and view and manage issues.
  • Join the team's repository: Accept the invitation sent to your email or check with a Producer. Once you have access, you can browse the issues in the repository and start working on tasks.
  • Our Kanban workflow: We break down large goals as a team into smaller goals. Smaller goals are added to Github Issues as tasks. We assign ourselves to tasks on a volunteer basis. As you make progress backup your files regularly to the server branches, and update the task board by moving your task through the different stages of the board as you progress.
  • Browse existing issues: Browse the existing issues in the repository to get an idea of what needs to be done. Pay attention to the labels and the status of the issues to understand what stage they are in.
  • Assign yourself a task: Once you find a task that you want to work on, assign yourself to the task by commenting on the issue or using the assign feature in GitHub. This will let the team know that you are working on the task.
  • If there are others assigned to the task, check in with them to see what needs to be completed and how you can contribute.
  • Work on the task: Once you have assigned yourself a task, start working on it. You can use GitHub and Discord to collaborate with the team, ask questions, and share your progress.
  • Move the task through the board: As you make progress on the task, move it through the Kanban board by changing the status of the issue. The team will be able to see your progress and know when the task is ready for review.
  • Submit a pull request: Once you have completed the task, submit a pull request to the team's repository. This will allow the team to review your changes and merge them into the main branch.
  • For details on our approach to version control check #HowToUseGithubDesktop.
  • Rinse and repeat: Continue browsing the issues, assigning yourself tasks, checking in with the team and backing up your progress regularly, and working on tasks until the project is complete. Remember to communicate with the team if you have any questions or concerns. Kanban is all about collaboration, so don't hesitate to discuss with the team throughout your progress.
  • Additionally everyone mentions their progress to the team verbally once a week in chat. And each department team varies on their specific approaches to tasks and regular communication. Some teams have regular voice calls and the days and timespans may vary.

Folders and Asset Structure

  • Conform new assets to our existing folder structures whenever possible.
  • Scripts should be kept with their relevant assets, not in a single “Scripts” folder that will grow large and unmanageable.
    • This also helps keep like-systems contained and organized.
  • No loose files. Everything should be organized into their proper project folders.
  • Don't store all ScriptableObjects together in one folder.
    • ScriptableObject is a serializable class type, not a category of assets.
  • Reference the #MenuOrganization section for technical details.

Version Control with Github Desktop

Introduction

What is this?

  • A way to stay organized and prevent overlapping work and conflicting files.
    • The system we use is a version control model called a "Gitflow branching model".

Download Github Desktop: https://desktop.github.com

  • Github Desktop is the tool we use to sync our files regularly.
  • Details of how to use Github Desktop will be added soon.

Submitting Files to the Project

  • Most developers on the project will use Github Desktop to backup their progress regularly to a local feature branch.
  • When enough progress is ready to submit to the project, create a pull request from the feature branch to the develop branch.
  • Pull requests are reviewed and merged to the project regularly, so re-sync local files from the develop branch frequently.

Technicals

Gitflow branching model

  • Our files are split into branches on the server to prevent overlap.
  • There's two main branches: main and develop.
    • tldr; most developers only work on the develop branch.
    • The main branch is the production-ready builds with version numbers.
    • The develop branch is the main branch for ongoing development.
    • There's a third testing branch in the middle called the release branch, between develop and main.
    • There's also a merging branch called the feature integration branch between features and develop.

Creating a feature branch

  • To submit content to the Unity project you'll need to make a feature branch that's local to your computer.
    • You can use this to backup your progress regularly.
  • When there's enough to submit to the project, use Github Desktop to create a pull request from your feature branch to the develop branch.

Synchronize Progress: Backup and Updates

  • Pushing content to your feature branch is a good way to backup your progress regularly. This ensures that your work is saved in a remote repository and can be accessed from anywhere.
  • It's important to use descriptive commit messages with a summary log of changes you've implemented so that other developers can understand the changes you've made and why you've made them.
  • Switch to the develop branch and fetch origin after backing up your progress to the feature branch. This will update your local branch with the most recent develop branch changes, ensuring your feature branch is up-to-date with the latest changes in the main codebase.
  • To continue progress on your local feature, switch the branch back to the feature branch you'd like to work on. Now you can continue making progress with the most updated code from the develop branch.

Creating a pull request

  • Details of how to create a pull request will be added soon.
  • Use descriptive commit messages with a summary log of changes you've implemented.
  • In Github Desktop, use the checkboxes next to files to select the files related to the changes you've made.
    • Unselect files that are not related to changes of the feature you're submitting.
    • If there are changed files you didn't intend you can Discard changes after pushing changes to the feature branch for backup, then create a pull request from feature to develop branch.

The Release Branch

  • Details of the release branch will be added soon.

Gitflow pipeline involves the following steps:

  • The develop branch is made from the master branch.
  • From the develop branch, create a feature branch titled as the 'feature name' for each new feature or bug fixes you'd like to add.
  • Once a feature is complete, create a pull request to merge the feature branch back into the develop branch.
  • Automated testing: (Use of automated testing hasn't been finalized for Calamity) Automated tests are run on the programming changes to ensure that they meet the defined quality standards.
  • Code review: Before a pull request is approved, after automated testing, it will be reviewed by other team members to ensure that it meets Calamity's standards and follows best practices.
  • When the develop branch has enough features to warrant a release or build, create a release branch from the develop branch.
  • Test the release branch, and merge any necessary bug fixes back into the release branch.
  • When the release branch is ready, merge it back into both the master and develop branches.
  • Tag the master branch with the new release version.

This workflow helps keep the master branch stable and production-ready at all times, while still allowing for ongoing development in the develop branch. It also allows for easy collaboration on new features and bug fixes, as each feature or fix is developed in its own branch before being merged back into the main branches.

QA Pipeline

  • Bug reporting is handled through Github Issues on a separate Github Project to maintain organization for QA.
  • General flow of QA is:
    • Individual bugs are reported to Github Issues Kanban backlog separated by department; Art, Design, and Programming.
    • Team from appropriate department takes on tasks to fix bugs and moves task status to In Progress.
    • Completed bug fixes are moved to Pending Verification.
    • Quality Assurance Testers take tasks from the Pending section and confirm that the bugs are fixed.
    • Continuing problems are returned to the fixer, moved back to in-progress.
    • Bugs that are Verified Fixed are move to the Done lane.
  • QA also has a section on the main Calamity Project for tasks relating to testing specific areas of the game or content for new bugs.

QA Testing Process

  • Most of the QA testing will be on the release branch.

Debug Tools

  • Details of Debug Tools to be added soon.

Audio System

Unity Documentation

🎓 The Basics: https://learn.unity.com/tutorial/working-with-audio-components-2019-3

Official Documentation

Working with Audio Files in Calamity

Adding New Audio Files

  • Our AudioFiles are stored in ScriptableObject containers that expand the audio files properties and it gives us greater control over the sound.
  • Export your audio files as .ogg extension.
  • Rename the file to be something easily understandable from the title.
    • Follow a standard naming convention like PascalCase, i.e. Write the title as one group of text but capitalize each word.
    • Add a common suffix at the end of the title that describes at a glance how the audio is used, e.g. Sfx for sound effects or Music for music.
    • A full example of a well named file would be renaming from 619320__asuperiorpotato__facility-hum-ambience-loopable.ogg to FacilityHumSfx.ogg.
  • After renaming the file, add it to the project by dragging it into its appropriate folder in our asset structure, or create folders under the Audio section as you need.
    • First load audio files into the _TestEnvironment folder under Assets in the project window if you're loading a large number of files or are unsure of how to immediately integrate them.
    • Remove or delete anything in the Test Environment folder at no risk to the project.
    • This enables you to do final adjustments to the audio files before committing them to the projects assets.
    • Select the audio file in the project window to adjust its base settings.

AudioFileContainers

  • To integrate the audio file into the game, create a new AudioFileContainer from the CreateAssetMenu.
    • Right click in the project folder window, select Create > Audio > AudioFileContainer.
    • Drag your audio file onto the Source (Audio Clip) section.
    • Set the Clamp Volume to somewhere around 1 to test the sound at a regular volume.
      • A large range for the Clamp values will have the sound play at a range of volumes in the game. 0 is mute.
      • Use the Preview button to test. Note: Use it sparingly, it's been finicky. To be safe press Play in Unity before previewing. Unity needs to compile.
  • The file is now successfully setup to work with our system.

How Audio is Used:

  • When should the audio be played and how?
    • Instead of being a fixed to a single use, we tie the AudioFileContainer to an AudioEvent.
    • An AudioEvent is a feedback response to something that happens in the game.
    • We pair the audio file to an event to say that sound will play when this happens through event listeners.

AudioEvents

  • There's a placeholder _TestAudioEvent to start with and use for testing AudioFilesContainers.
  • Create new AudioEvents in the AudioEvents folder or the test folder from the CreateAssetMenu.
    • Right click in the project window Create > Audio > SimpleAudioEvent
    • Drag the AudioFileContainer into one of the AudioFiles slots in the Unity Inspector.
    • Set the volume and pitch ranges or other settings as needed.
  • Now the Audio Event is ready to be used by the Level Designers or Audio Level Designers.

Mixers

  • To open the Mixer panel in Unity go to Window > Audio > Audio mixer.
  • We have a few Mixers as placeholders, they can be changed as needed.
  • Audio Designers should modify or add to the Mixers, add effects, adjust any audio settings as needed.
    • Consider a File and Mixer naming convention that's consistent between all involved parties. e.g. PascalCase and adding a title suffix like Sfx, etc.

Command System

  • Player Commands are C# scripts that carry out a specific function then trigger callback events as needed.
  • Each Command is stored as a ScriptableObject that triggers callback GameEvents that are easily modifiable in Unity.
  • Commands can invoke a series of callback events at once.

Creating New Commands

  • An empty Command that has no functionality other than to trigger callback events and catalog the command is available from the CreateAssetMenu.
    • Add it to the Commands folder in the Assets folder. Add new paths as needed.
    • Right Click, select Create > Player Commands > EmptyCommand to create a new empty command.
    • Set it up with callbacks.

GameEvent Callbacks

  • Commands can trigger a group of callback events when invoked.
  • Our callback events are stored as ScriptableObjects called GameEvents.

FeedbackCommands

  • FeedbackCommands are special callback commands designed to trigger additional commands after a PlayerCommand is invoked, e.g. play a sound, flash the screen, camera shake, etc.

FeedbackCollections

  • FeedbackCollections are groups of FeedbackCommands that can happen at once. e.g. Multiple sounds, multiple screen effects or UI changes, etc.
  • // Audio is the only feedback type currently implemented.

GameEvents

  • GameEvents are simple triggers that invoke a wide range of functionality in the game.
  • Organize new GameEvents into relevant folders in the Game Events folder.
  • Create new GameEvents from the CreateAssetMenu
    • Right Click in the Game Events folder from the project window, select Create > Events > GameEvent

Lighting

  • Details of lighting system to come.

Test Environment

  • The Activate Launch Scene button in the Unity Editor will toggle the Play button between the current open scene and the main game.
  • Changes to the TestEnvironment scene, or the "_TestEnvironment" folder under the Assets folder, won't be uploaded in a pull request so changes are at no risk to the project.
  • Use the _TestEnvironment folder to load external files into a safe area in the project before integrating them to the rest of the folder structure.
  • Use the TestEnvironment Scene to test models, features, or anything experimental.

UI Tools

  • Details of UI tools to come.

Technical Details

Packages

Imported Packages

  • Ink
  • Poly perfect
  • TextMeshPro
  • Toolbar extender

Code and Menu Organization

AssetMenuSortOrders

  • Our asset menu organization class is called AssetMenuSortOrders
    • They're preset file paths that keep new objects in order.
  • The order is alphabetized. You can find the correct order in your IDE by searching for all the references to the paths you're using.
    • // If anyone has ideas for a simple alphabetize algorithm for the menus, that sorts when the editor refreshes, please share!
  • In the script, set the file path with [CreateAssetMenu]
    • Direct new command scripts to the following directory, add sub-directories as needed,
[CreateAssetMenu(menuName = AssetMenuSortOrders.CommandsPath + "Empty Command", fileName = "EmptyCommand", order = AssetMenuSortOrders.CommandsOrder + 2)]
  • Check AssetMenuSortOrders.cs for the list of existing menu paths.

MenuItemSortOrders

  • MenuItemSortOrders are similar to AssetMenuSortOrders but it has less organization functionality.
  • It's used for organizing new menus in Unity, e.g.
[MenuItem(MenuItemSortOrders.SceneSettings + Emoji.EmojiConstants.Recycle + "Refresh Scene List Menu", priority = 50)]

Custom Namespaces

  • One way to keep our code organized and modular is by using functional-based namespaces. This helps us to better manage dependencies and keep things streamlined.
  • Namespaces can also help avoid naming conflicts with imported packages.
  • Our namespace prefix is Calamity followed by FunctionalGroupTitle, e.g.
using Calamity.AssetOrganization;

namespace Calamity.EventSystem
{
    // class
}
  • Wrap classes in namespaces starting with the prefix followed by the related system.
  • Add new namespaces as needed.
  • Remove any unused namespaces.
  • Note any added namespaces in your pull request description.

Our custom namespaces (so far):

// Add and use namespaces as you need.
using Calamity.AssetOrganization;
using Calamity.Audio;
using Calamity.CommandSystem;
using Calamity.DebugTools;
using Calamity.EventSystem;
using Calamity.Math;
using Calamity.Primitives;
using Calamity.SceneManagement;

// external namespaces
using Seeker.StringMarkupEncapsulation;
using Seeker.Emojis;
using RoboRyanTron.Unite2017.Events;
using Ink;    // And it's sub-namespaces

Math Formulas as ScriptableObjects

  • Storing simple math formulas as ScriptableObjects enables us to arrange GameEvents based on these formulas.

Post-Processing

  • Details of our post-processing effects to come.

Primitives as ScriptableObjects

  • Storing primitive data types such as int, float, vector3, and more as ScriptableObjects enables us abstract data from our classes into standalone components in Unity.

Scene Management

  • Scenes are abstracted by functional-use, e.g. Audio or MainMenuUI.
  • Scenes are added to the Scenes list menu item after refreshing from Scenes > Settings > Refresh Scene List Menu
  • Scenes are organized into folders under Scene > Game Scenes > [game scene category] > New Scene

Shaders

  • Details of our shaders to come.
  • Custom shaders details and use of ShaderGraph.

Universal Render Pipeline (URP)

  • Details of how we integrate URP to come.

Visual Effects

  • Details of our visual effects to come.
  • Details of our use of VFXGraph.

Technical Gameplay Details

Monsters Factory Module

  • All monsters subscribe to this singleton and are created by it. Links directly to the monster prefab via FindAsset(). Instantiates new monsters to the scene by loading scriptable objects.
  • Scriptable Object Template script
  • Single Monster Prefab with mesh, animator and behavior script
  • Folder for Scriptable monsters filled with all monsters in the game
  • New monster features are added to the template with a default value so old objects still function.
  • Monster meshes will follow a naming convention and be kept in a monster mesh folder. The scriptable objects will target this same named mesh. This link will be generated by an editor script. A second editor script will check for mismatched naming conventions, SOs without meshes and vice versa.
  • A default animator will be fine for most monsters.
  • A default behavior script will be fine for most monsters | This script will include the monster’s stats, populated by the SO.

Inventory Controller

  • All weapons subscribe to this singleton.
  • Scriptable Object Template script
  • Single Weapon Prefab with mesh, animator and shooting script
  • Folder for Scriptable weapons filled with all weapons in the game
  • New weapon features are added to the template with a default value so old objects still function.
  • Weapon meshes will follow a naming convention and be kept in a weapon mesh folder. The scriptable objects will target this same named mesh. This link will be generated by an editor script. A second editor script will check for mismatched naming conventions, Sos without meshes and vice versa.
  • Depending on the weapons, we may need an animator per weapon. This can follow the same naming conventions and folder placement as weapon meshes.
  • A default shooting script will be fine for most if not all weapons. | This script will include the weapon’s stats, populated by the SO.

Camera Controller

  • Automatically switching to cameras by room proxy.
  • Prefab for each camera area. A large hitbox with inspector sliders to adjust size, camera location and pitch/angle.
  • An editor script to run a check that all camera area's are touching. All walkable area must have exactly one camera hitbox.

Bestiary

  • Bestiary definitions can live in the monster and weapon SOs.
  • Possibly use Ink or a similar function to manage large volumes of text data.

Level structure

  • Level design is abstract
  • Each level will need to be custom build
  • Instead of a level creating script, we will need something to handle transitioning from one area to another.
  • When moving from room to room, 1 scene is preferable but repositioning the game's origin will be required to avoid float point issues.
  • Consideration for a polygon editor package within unity depending on design preferences