Player

Overview

Player (Player script, Player prefab) represents a connected peer in the game and has no visuals. Player provides access to common metadata - UserID, Nickname, selected character, and other data that should survive the respawn of the Agent (visual representation spawned in the game world).

Agent (Agent script, AgentBase prefab, and its variants) represents an in-game character that is controlled by the player. It is spawned by GameplayMode and has Health, Weapons, and other components. The character is spawned and despawned as needed.

The following diagram shows the component hierarchy as an execution waterfall:

Agent Components

Back To Top

Input Processing

The following diagram illustrates processing input and execution of actions:

Input Processing

Notes:

  1. Frame: Unity render frame number, Tick: Fusion fixed update tick number
  2. At the start of each frame, input from the device is collected in BeforeUpdate() and written to the Render Input data structure (executed on input authority only)
  3. The same input is also accumulated into Cached Input (for example, look rotation delta)
  4. If the accumulated delta time is big enough to simulate the next fixed tick (frame 103)
    • Cached Input is polled/consumed through NetworkEvents.OnInput() callback
    • Because the most recent Render Input is already accumulated and will be processed in the following FixedUpdateNetwork(), it needs to be cleared, so it is not applied twice (from FixedUpdateNetwork() and Render())
    • Player input is read from Fusion in BeforeTick() and stored in Fixed Input (executed on input and state authority)
    • FixedUpdateNetwork() called in other scripts use Fixed Input to generate gameplay actions
    • Render() called in other scripts use Render Input to generate gameplay actions (render predicted movement, shooting is done only from FUN)
  5. If the accumulated delta time is NOT big enough to simulate the next fixed tick (frames 101, 102)
    • Render() called in other scripts use Render Input and Cached Input to generate gameplay actions (render predicted movement, look rotation)

This diagram is a simplified version and doesn’t cover all edge cases. For more details check the documented code.

Back To Top

Look Rotation Smoothing

Fusion BR comes with a custom solution for a smooth look rotation under any conditions.

The following log illustrates the aliasing problem with raw input when using common hardware (mouse polled with 125Hz rate) and high render/output refresh rate (200+ FPS). The rendered output will always feel jittery, no matter how good the CPU/GPU is.

Look Rotation Smoothing

To fix this problem, input values are recorded with a timestamp, then the value for the current frame is calculated as the average of a defined time span (Fusion BR uses a 25ms window by default). This results in a butter-smooth perception experience (especially noticeable with a high refresh rate monitor) but introduces a very small input lag. Using hardware with a higher sampling rate allows you to decrease the smoothing window to a minimum.

The following graph shows raw mouse delta (bottom line) and character look rotation (upper line) in time:

Look Rotation Smoothing

The following graph shows smoothed mouse delta (bottom line) and character look rotation (upper line) in time:

Look Rotation Smoothing

This also helps to reduce sampling errors (desk surface) and micro-jitter caused by uneven hand/mouse movement (desk friction, muscles).

Back To Top

Character Animations

The project has a custom animation controller implementation based on the Playables API. It provides support for tick-accurate animation evaluation and dynamic performance scaling.

The following diagram shows the architecture which is similar to the Mecanim:

Animation Controller

Animation layers and states setup in the agent's object hierarchy:

Animation Layers

Animation Layers:

  • Locomotion: Base full body layer for movement
  • FullBody: Override layer for full body actions, blended with Locomotion
  • LowerBody: Override layer for lower body character turning
  • UpperBody: Override layer for upper body actions, usually blended with Locomotion
  • Shoot: Override layer for hands actions (shooting), usually blended with Locomotion
  • Look: Additive upper body layer for looking up and down

Depending on the animation controller complexity, evaluating 200 players can easily become a bottleneck on the server. For better performance, the server allows for interlaced PlayableGraph evaluation every n-th frame based on the connected players count. All important properties like layer or state weight are still calculated every frame. The following table shows the rules for an interlaced evaluation.

Players Connected PlayableGraph Evaluation
> 150 Every 4th frame
> 100 Every 3rd frame
> 50 Every 2nd frame
Otherwise Every frame
This project uses animations baked with the generic rig. Using a humanoid rig would add additional performance overhead due to retargeting

Back To Top

Character Controller

This sample uses Fusion KCC (an advanced kinematic character controller addon) for movement. It is a generic low-level character controller with a strong focus on performance, gameplay interactions, and customization.

Fusion KCC features:

  • Control over position and look rotation (pitch + yaw)
  • Shape defined by Capsule collider
  • Predicted Render movement for local player
  • Combined dynamic (physics-like) and kinematic (unrealistic) velocity based movement
  • External forces - from explosions, moving platforms, …
  • Move acceleration and friction
  • Advanced KCC Processors pipeline for customization (speed and direction override, blocking)
  • Out of the box network synchronization for default properties (radius, height, mass, ...), optional synchronization of other - properties
  • Custom Collider filtering and ignore list
  • CCD (Continuous Collision Detection)
  • Collision callbacks
  • Support for ground snapping and step height
  • Support for local mode (no network traffic)
  • Network & performance optimized
  • Platform independent, mobile friendly
  • Basic support for frame by frame debug - editor drawings and logging

When a player's health is below a certain threshold, and the player is currently out of combat, auto heal kicks in and starts replenishing the player's health.

Back To Top

Jetpack

The jetpack provides the ability to fly and quickly navigate in the level while draining fuel. Fuel can be replenished by picking up fuel cans found in item boxes.

The state of the jetpack is handled by the Jetpack script which handles fuel consumption, propellers, sounds, and on/off state. The actual movement in the air is handled by JetpackKCCProcessor. This script overrides KCC velocities and suppresses default behavior.

Jetpack

Back To Top

Spectator Mode

When players are eliminated or join the game too late, they enter the spectator mode. In spectator mode, players can observe the game from other player's perspectives. In code, this is actually handled quite simply. The camera and UI act based on the ObservedAgent assigned in the SceneContext. The ObservedAgent can be either the local player agent or spectated player agent.

To Document Top