Architecture
Player
Player (Player
script, Player
prefab) represents a connected peer in the game and has no visuals. Use Player to sync statistics, nickname, selected hero, their desire to join gameplay etc.
Player Agent (PlayerAgent
script, PlayerAgent
prefab) represents an ingame character that is controlled by the player, is spawned by Gameplay
, has Health
, Weapons
and other usual stuff. Can be spawned and despawned as needed.
![photon dummy](/docs/img/fusion/v2/samples/projectiles/fusion-projectiles-photon-dummy.png)
Weapons
Overview
Fusion Projectiles contain a small weapon handling system. It is a basic implementation which only handles weapon switching. For more elaborate usages like weapon drop, pickup, reload, recoil patterns, dynamic dispersion and other check Fusion BR sample.
To manage all kinds of weapons however, a convenient weapon action-component system is included.
Weapon Actions
A weapon action is a set of weapon components that represent a single weapon action. One weapon action is for example a standard fire and other action is an alternative fire. Weapons can have various weapon actions.
![weapon action](/docs/img/fusion/v2/samples/projectiles/fusion-projectiles-weapon-action.png)
Weapon Components
The Weapon component represents part of the weapon that has its own logic and can be reused in different scenarios. Weapons can be assembled from multiple components to form the desired functionality. Fusion Projectiles comes with several weapon components:
WeaponMagazine
- Provides ammoWeaponTrigger
- Says when the weapon should fire (checks player input, controls weapon cadence)WeaponBarrel
- Fires the projectileWeaponFireEffect
- Shows muzzle, plays fire sound, applies knockback, starts camera shakeWeaponBeam
- Fires continuous beamWeaponSpray
- Fires spray projectiles
💡Note: When building various weapons the idea is to just swap one or more components while reusing the others. One example is Laser Gun where the WeaponBarrel
component is swapped for WeaponBeam
- magazine still provides ammo, trigger still tells when to fire, just the fire effect is different. Another example would be a minigun where it takes time for the rotating barrel to gain speed before fire starts - in this instance, a DelayedTrigger
component could be created to replace the standard trigger.
Shake Effect
ShakeEffect
utility is used for driving camera shake (SceneContext/SceneCamera/Shaker
object in SceneContext
prefab) in response to weapon fire. The effect is triggered from the WeaponFireEffects
component, where position and rotation shake ranges can be set. The ShakeEffect
utility supports stacking of different camera shakes and continuous shaking (continuous fire).
![camera shake](/docs/img/fusion/v2/samples/projectiles/fusion-projectiles-camera-shake.png)
Health and damage system
For hit synchronization an approach similar to projectile data is used. Hits are stored in a small networked circular buffer of Hit
structures.
C#
public struct Hit : INetworkStruct
{
public EHitAction Action;
public float Damage;
public Vector3Compressed RelativePosition;
public Vector3Compressed Direction;
public PlayerRef Instigator;
public NetworkBool IsFatal;
}
From the Hit
struct the appropriate hit reactions can be constructed - e.g. playing hit animation, showing hit direction in UI, showing hit confirmation and numbers to damage instigator, spawn of blood effect, etc.
💡Note: Notice how RelativePosition
of the hit is stored in Hit
data instead of an absolute position. Since position of the proxies is interpolated between last two received ticks from the server, relative position is better to place hit effects such as blood splash correctly onto the body.
Gameplay Elements
Explosion
Simple spawned Network Object
that deals damage within a certain radius.
![](/docs/img/fusion/v2/samples/projectiles/fusion-projectiles-explosion-inspector.png)
![explosion](/docs/img/fusion/v2/samples/projectiles/fusion-projectiles-explosion.png)
Damage Area
Damage is applied to all targets inside this area over time. Use it to test incoming damage.
![damage area](/docs/img/fusion/v2/samples/projectiles/fusion-projectiles-damage-area.png)
Turret
SimpleTurret
is used to spawn standalone projectiles in some intervals. There is no search for target logic nor rotation toward a target. Used for testing weapons outside of an PlayerAgent
prefab.
![turret](/docs/img/fusion/v2/samples/projectiles/fusion-projectiles-turret.png)
Game Core
GameManager
Handles joining and leaving of connected players and spawns Player
prefab. For more elaborate handling of connected players with saving of player data for reconnection refer to the Fusion BR sample.
Gameplay
Gameplay
is responsible for spawning/despawning PlayerAgent
prefabs. This base implementation acts as an endless deathmatch. Can be inherited from and extended to add different gameplay functionality such as proper deathmatch, capture the flag, elimination etc.
Pooling
In projects that involve projectiles, a large amount of object spawning is expected (projectiles, muzzle effect, impacts, hit effects,...). Since instantiation of a new object is an expensive operation everything in Fusion Projectiles is pooled.
There are two types of pool:
NetworkObjectPool
is used to pool theNetworkObject
s. For network object pool to work it needs to implement theINetworkObjectProvider
interface and be present onNetworkRunner
game object. For more information check out Network Object Provider section in the Fusion Manual.ObjectCache
is a genericGameObject
pool that can be used for non-networked objects such as projectiles and impact effects. It has a handy feature to return objects with a specified delay.
Scene Context
SceneContext
provides safe access to common game objects or other information that are needed across the codebase without the use of statics. Scene context is assigned to all IContextBehaviour
components found in the scene after scene load is done (GameManager.OnSceneLoadDone
) and is also assigned to network behaviours (ContextBehaviour
) in NetworkObjectPool
. Inherit from ContextBehaviour
instead of NetworkBehaviour
if access to the SceneContext
is needed.