Project Architecture
The Unity Project
The project follows a standard Unity project structure. All scenes are located in the Scenes folder, with Game being the main scene. Unlike typical games, the Fusion MMO sample does not have a separate menu scene - instead, it features a compact connection menu directly within the Game scene. All scripts in the Scripts folder are thoroughly commented to help you understand the codebase.
High Level Breakdown
The game starts from the UIGameMenu
script, which calls the Connect
method on the ConnectionManager
script. The ConnectionManager
handles both the initial connection and transfer logic when a player moves to a different game session through a Remote Portal (see Player Transfer for more details).
In Shared Mode, each player typically handles their own spawn logic, and Fusion MMO follows this pattern. The GameManager
script manages player spawning, while the EnemySpawner
script handles enemy spawning. Enemy AI is controlled by nearby players (see Enemies for more details).
The Player
and Enemy
scripts inherit from a base class called Agent
, which contains shared properties and functionality. The Agent
script also manages sensors - components that periodically gather information about the game world for their owner (the agent). Examples include the AreaSensor
, FindTargetSensor
, and LineOfSightSensor
.
This project uses two key addons for both enemies and players:
- Simple KCC for character movement
- Finite State Machine (FSM) for behavior management
The Health
component tracks agent health points. To provide responsive feedback during combat, the health component can predict health changes even before the player gains authority over the target object.
Players
The Player
script manages all essential player functionality including movement, finite state machine (FSM) updates, input handling, abilities, camera control, and character progression.
Players use a finite state machine to control their behavior. The FSM states determine how the player moves, which animations play, which abilities can be used, and which effects (sounds, particles) are triggered. The main player state is LocomotionState
.
The game features three player abilities, each implemented as a distinct FSM state that the player can transition into:
MeleeAbility
- A melee attack state that deals damage to nearby enemiesDashAbility
- A dash state that provides quick mobility and temporary invulnerabilitySpawnEffectAbility
- A spawn effect state that allows precise placement of area effects using a top-down targeting system
Players can earn experience points (XP) through a progression system by defeating enemies. When players accumulate enough XP to level up, they receive a full health restore and celebratory visual effects mark their achievement. A coin collection system is also included, though this serves as a demonstration feature only - there is no way to spend the coins in the sample.
The camera system provides smooth follow behavior with configurable zoom and rotation speeds.
Upon death, players respawn in the town area after a brief delay. The respawn system ensures players can quickly get back into the action without excessive downtime.
For testing purposes, players can be controlled by a basic AI system. For more details, see the Player AI section.
Enemies
Fusion MMO features three distinct enemy types:
- Dummy enemies (
DummyEnemy
script) are passive creatures that simply wander around and graze on grass. - Melee enemies (
MeleeEnemy
script) actively patrol their spawn points and engage players with close-range attacks when they detect them. - Ranged enemies (
RangedEnemy
script) patrol their territory and attack players from a distance using projectiles.
All enemies inherit from an Enemy
base class which provides common functionality.
The EnemySpawner
script manages enemy population in the game world. It dynamically adjusts spawn counts based on spawner settings and the number of players in an area. As more players enter an area, the spawner increases the enemy count to maintain engaging gameplay. Enemy spawners are controlled by the master client.
Enemy AI, animations, and visual effects are driven by states from the Fusion FSM addon. All enemy states can be found in the Scripts/States/Enemy States folder. To ensure correct execution order (Sensors Update -> State Changes -> FSM Update -> Movement), the FSM is updated manually from the FixedUpdateNetwork
method in the Enemy
script.
Enemies use multiple sensors to gather information about their environment:
FindTargetSensor
identifies the best target from visible playersAreaSensor
tracks which area the enemy currently occupiesLineOfSightSensor
(used by ranged enemies) verifies clear shooting paths to targets
For pathfinding, the game utilizes Unity's AI Navigation package. The NavMeshSurface
component is attached to the Environment game object in the Game scene.
Distributed Enemy Authority
Since there is no dedicated server in Shared Mode to run enemy AI, and a single client (master client) would be overwhelmed trying to calculate AI for all enemies, the game distributes AI calculations among the closest players. This approach allows the enemy count to scale efficiently as more players join.
The system works in a straightforward way: As a player moves through the environment, their AIControlSensor
script periodically scans for nearby enemies that aren't currently controlled by any player (those without assigned state authority). When such an enemy is detected, the player requests authority over it. The player will also release authority over any enemies that is too far away. This entire functionality is implemented in the AIControlSensor
script.
Interactables
The game includes a flexible interaction system that enables players to interact with various objects in the world, such as opening chests, picking up items, and using portals. The InteractionSensor
component continuously scans for nearby interactable objects within its detection radius.
For an object to be interactable, it must meet two requirements:
- Have a Collider component set to the
Interactable
layer - Contain a script that implements the
IInteractable
interface
The IInteractable
interface defines two key methods:
CanInteract()
- Determines if interaction is currently possibleInteract()
- Executes the interaction logic when triggered
Common interactable objects include:
- Chests that can be opened to receive coins and health boost
- Portals for traveling between different locations
- Pickups that provide instant benefits when collected:
- Health pickups restore a portion of player health
- Coin pickups add to the player's currency
The chest prefab (Assets/Prefabs/Interactables/Chest) provides a good example implementation, showing how to properly set up collision detection and handle networked interaction events.
Portals
Portals are special interactable objects that allow players to teleport between different locations in the game world. The game features two distinct types of portals:
LocalPortal
enables teleportation between two points within the same scene. When a player interacts with a local portal, it activates the Portal State
on the player's state machine, which creates a smooth transition by playing spinning animations and visual effects before teleporting the player to the destination point. Local portals work in pairs - each portal has a designated target portal that players will be teleported to.
RemotePortal
facilitates travel between different game scenes and sessions. When used, it initiates a Player Transfer process that preserves the player's progress and state while moving them to a new scene and game session. Each remote portal has a unique identifier and maintains information about its target scene and destination portal. To ensure consistent multiplayer experiences, remote portals track the most recent session name used for teleportation, so all players teleport to the same session.
Player Transfer
The game implements a seamless player transfer system that allows players to move between different scenes and game sessions while preserving their progress and state. This functionality is primarily used by Remote Portals to enable travel between different game areas.
When a player interacts with a Remote Portal, it initiates the transfer process by:
Creating a
TransferData
object containing:- Origin session name and scene
- Target session name, scene, and portal ID
- Player state data (level, XP, health, coins, ability cooldowns)
The
ConnectionManager
handles the actual transfer by:- Disconnecting from the current session
- Connecting to the target session
- Loading the new scene
- Showing/hiding loading UI during the process
In the new session, the
GameManager
:- Locates the destination portal using the portal ID
- Spawns the player at the portal location
- Restores the player's state from the transfer data
Additionally, the PhotonAppSettings' EmptyRoomTTL setting keeps sessions alive for a short period even when empty, ensuring players can successfully transfer back to their original session.
Areas
Areas are defined regions in the game world that help manage gameplay mechanics and difficulty scaling. Each area is defined by one or more bounds and can contain enemy spawners. The Area
class tracks important information like:
- Area name and ID
- Current player count in the area
- Whether sprinting is allowed
- Area level (scales with player count)
The AreaManager
maintains a list of all areas in the scene and tracks player distribution across them. It updates player counts per area every second, which affects enemy spawning and difficulty.
Players and enemies use an AreaSensor
component to detect which area they are currently in. The sensor checks the player's position against area bounds. Players receive notifications when entering new areas.
Difficulty Scaling
The game features dynamic difficulty scaling based on player count in each area:
Area Level:
- Base level increases with number of players in the area
- Affects overall enemy strength in that area
Enemy Count:
- Each spawner maintains a base number of enemies
- Additional enemies spawn based on player count
- Maximum enemies per spawner is capped
Enemy Scaling:
- Enemies dynamically adjust their level based on number of players in their area
- Level adjustments happen silently in the background when enemies are not in combat
- Higher levels increase enemy health and damage
- Ensures appropriate challenge as player count changes
This system automatically balances difficulty whether players are solo or in groups.
Scene Context
The SceneContext
provides centralized access to scene-specific references like GameManager and AreaManager. Instead of inheriting directly from NetworkBehaviour
, components can inherit from ContextBehaviour
to automatically gain access to these scene-wide references through a cached Context property. This eliminates the need for manual reference lookups and provides a clean way to access scene managers from any networked object.