PUN Classic (v1), PUN 2 and Bolt are in maintenance mode. PUN 2 will support Unity 2019 to 2022, but no new features will be added. Of course all your PUN & Bolt projects will continue to work and run with the known performance in the future. For any upcoming or new projects: please switch to Photon Fusion or Quantum.


The Simple API contains a handful of sub libraries that deal with common networking challenges. Most of these have basic implementations that may work well enough for many projects. However these are all designed with the intention of acting as guides for how to property interact with the API and make your own.


Contact System

ContactTrigger Component

Sync Animator Component

This component is a universal starting point for networked collision/trigger/hitscan events. It produces an IOnContactEvent.OnContactEvent() callback whenever contact occurs between two ContactTriggers. For every IContactSystem that interacts with an IContactTrigger, a OnContactEvent() is raised.

SyncContact Component

Sync Contact Component

When this component exists on the same GameObject as a ContactTrigger (above), the ContactTrigger will deffer and serialize all OnContactEvent callbacks, rather than just triggering them locally. This component instead gets the ContactEvent for processing. This allows remote ContactSystems with controller authority to process these events.

A usage example would be a hitscan weapon, where the ContactTrigger is triggered on the shooter, but the health system being affected belongs to another player. The SyncObject on the shooter will collect the generated ContactEvents, and serialize/send those to all other clients, where they are raised again.

IOnContactEvent.OnContactEvent(ContactEvent event)

This callback is generated whenever two ContactTriggers register a contact. A ContactEvent is generated for each ContactSystem (VitalSystem/Inventory System) that contacts a compatible ContactReactor.


This is the root interface for systems that defines components that can produce Trigger and Pickup interactions actions with other NetObjects.


Defines a component that interacts with an IContactSystem. This is the flow of the interaction between pickup items and the Vitals and Inventory systems.

Projectiles and Hitscans

Projectiles and Hitscans can produce ContactEvents similar to normal collisions.

SyncCannon Component

Sync Cannon Component

This component produces a projectile, which can act as a proxy for the ContactTrigger on the same GameObject. Collision and Trigger events the projectile is involved in will fire OnContactEvent callbacks on the object with the SyncCannon component.

Contact Projectile

Contact Projectile Component

Projectile prefabs should have a ContactProjectile component, or a component that implements IProjectile.

SyncContactScan Component

Sync Contact Scan Component

This component produces generic hitscans which test for hits against ContactTrigger components with colliders. Hits produce a OnContactEvent that can be handled by a ContactReactor component on the same object.

Contact Groups

A Layer/Group mask system that avoids the shortcomings of Unity's tag and layers. Unity Tags are not proper bitmasks and are string based and Unity Layers is tied to physics, making it not ideal for networking.

The system itself is actually very simple. The ContactGroupSettings singleton stores an index of group names, which translate into a bitmask. ContactGroupAssign components can be added to GameObjects with colliders. You can then call GetComponent<ContactGroupAssign>().Mask on collision/trigger/raycast results to determine if the hit collider belongs to a group of interest.

ContactGroupAssign Component

Contact Group Assign Component

This component is used at runtime to associate ContactGroups of an object with indexed named groups. If Apply To Children is enabled, it will replicate the component to all child transforms that have a ContactTrigger component, unless they already have their own ContactGroupAssign.

Contact Group Settings

Contact Group Settings

This settings singleton allows you to name/add/remove groups from the mask system.

Inventory Contact System

BasicInventory Component

IInventory<T>, IContactSystem

Basic Inventory Component

This base class and interface for the Inventory System allows for the creation of Inventory components which automatically work with the rest of the Simple code base.

T is the struct that is used to define the capacity of the Inventory. The BasicInventory component uses a Vector3 as T and is provided to show how to extend the base to create your own inventory system using your own inventory struct and logic.

InventoryContactReactor Component

IInventoryable<T>, IContactReactor

Inventory Contact Reactor Component

The base class and interface for the Inventory System that allows an object to be considered an item that can interact with IInventory.

To successfully add an IInventoryable item to an Inventory the following must be true:

  • The SyncPickup must receive and OnContactEvent() (typically comes from the ContactTrigger).
  • The Pickup object must have an IInventoryable component (such as InventoryContactReactors)
  • and the colliding object must have an IInventory (such as BasicInventory) component.
  • The T types must match.
  • The Pickup object's SyncState must define a valid Mount that matches an IInventory's DefaultMount.
  • ContactGroupMasks must match.

Vitals Contact System

SyncVitals Component

IVitalsSystem : IContactSystem

Sync Vitals Component

A generic component for handling syncing of things like health, energy, shields, power, etc. This component makes use of the ContactGroups System.


The name/id of this Vital. Internally this is backed by an enum of the known types. Custom types turn the hand coded name into a hash.

Start Value

The value that this vital will return to when reset or initialized.

Full Value

The normal max value. If this value is changed at runtime it needs to stay below Max Value or it will break serialization. Value changes the current value can be flagged with Overload, which can allow current value to be greater than Full Value (but still less than Max Value).

Max Value

The highest possible value. This value is used to determine the bits needed for serialization. As such this value should not be changed at runtime.


The percentage of damage this vital will take. The remainder is applied to the next vital up the chain.

Regen Delay/Rate

How many seconds after damage occurs before this vital resumes regeneration. Rate is how much value is added per second.

Decay Delay/Rate

How many seconds after overload (being given a value greater than Full Value) before this vital will start to decay in value back down to full value. Rate is how much value will drop per second.

Auto Despawn

When the root vital reaches 0, this will fire a OnDespawn event with the SyncState component.

Reset On Spawn

When SyncState fires a OnChangeState callback flagged as a respawn, all vital values will be returned to the start value.

VitalsContactReactor Component


Contact Trigger Component

Vitals Contact Reactor Component

The VitalsContactReactor responds to OnContactEvents, and trigger changes to the ContactSystem if compatible with the ContactReactor.

Mount System

Mount Manager Component

Mount Manager Component

Mount Component

Mount Component

Mount Settings

Mount Settings

AutoMountHitscan Component

Auto Mount Hitscan

This component produces a hitscan every tick, and will attach its parent NetObject/SyncState to the mounts of any other NetObject the hitscan finds. The primary use for this is for automatically re-parenting objects to platforms/vehicles or any other moving object that motion should be relative to.

By mounting objects to moving parents, transform syncs can use local rather than global space. This will ensure that if the objects have different owners, they will still remain firmly connected and not suffer from "floating behind" due to latency differences.

Projectiles and Hitscans

SyncCannon Component

SyncContactScan Component



Mask Logic Drawer

This drawer is used by components to create mask tests with slightly more complex combinations than a basic mask compare.

The logic dropdown selects if the test applied is a EQUALS, ADD, or OR type test. The mask produces a bool result from: Evaluate(int mask).

To Document Top