SlideShare a Scribd company logo
A Dynamic Component Architecture
      for High Performance Gameplay


Terrance Cohen
Lead Systems Engineer
Insomniac Games
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System

• Implementation by Example



• Questions (note slide #)
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose
  o Statement of Problem
  o Proposed Solution


• The Dynamic Component System

• Implementation by Example
Purpose : Statement of Problem

• Monolithic / deep Game Object hierarchy
  o Memory: binds data @ compile time
      Allocated throughout lifetime
Purpose : Statement of Problem

• Monolithic / deep Game Object hierarchy:
  o Memory: binds data @ compile time
  o Performance: poor cache coherence
      Arrays of non-homogeneous objects
      Virtual dispatch
      Fragmented instance data
Purpose : Statement of Problem

• Monolithic / deep Game Object hierarchy:
  o Memory: binds data @ compile time
  o Performance: poor cache coherence
  o Architecture: capability <=> inheritance
      Fixed at compile time
      Fully determined by class
      Change capabilities -> change hierarchy
Purpose : Statement of Problem

• Monolithic / deep Game Object hierarchy:
  o Memory: binds data @ compile time
  o Performance: poor cache coherence
  o Architecture: capability <=> inheritance


• "What we're used to"

• But select the best tool for the job.
Purpose : Statement of Problem

• Monolithic / deep Game Object hierarchy:
  o Memory: binds data @ compile time
  o Performance: poor cache coherence
  o Architecture: capability <=> inheritance


• "What we're used to"

• But select the best tool for the job.

• There's a better way!
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose
  o Statement of Problem
  o Proposed Solution


• The Dynamic Component System

• Implementation by Example
Purpose : Proposed Solution

• Construction of Game Object through composition of
  components at runtime
Purpose : Proposed Solution

• Construction of Game Object through composition of
  components at runtime

• Simple!

• Thank you for coming!
Purpose : Proposed Solution

• Construction of Game Object through composition of
  components at runtime

• Simple!

• Thank you for coming!

  o   Oh, you want details !?!
Purpose : Proposed Solution

• Construction of Game Object through composition of
  components at runtime

• Small chunks

• Represent a data transformation
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System
  o Features


• Implementation by Example
The Dynamic Component System

• Evolution
   o Resistance 1 - Proof of Concept (1 type)
   o Resistance 2 - "Early Adopters" (32 types)
   o Ongoing (295 types as of May 1st 2010)
       Majority of new gameplay code
       Large portions of old gameplay refactored
The Dynamic Component System

• Evolution
   o Resistance 1 - Proof of Concept (1 type)
   o Resistance 2 - "Early Adopters" (32 types)
   o Ongoing (295 types as of May 1st 2010)
       Majority of new gameplay code
       Large portions of old gameplay refactored

• So it’s mature.
The Dynamic Component System

• Evolution
   o Resistance 1 - Proof of Concept (1 type)
   o Resistance 2 - "Early Adopters" (32 types)
   o Ongoing (295 types as of May 1st 2010)
       Majority of new gameplay code
       Large portions of old gameplay refactored

• So it’s mature. (No, not that way.)
The Dynamic Component System

• Side-by-side implementation
   o Not necessary to refactor existing code
   o Coexist with components


• General solution
The Dynamic Component System

• Does not address matters of
  o Reflection
  o Serialization
  o Data building
  o Instance versioning
  o ... those things are handled separately
      outside the scope of this discussion
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System
  o Features


• Implementation by Example
Dynamic Component System : Features

• Components

• High-performance

• Dynamic

• System
Dynamic Component System : Features

• Components
   o Originally Aspects
   o Base Component class
       8 bytes of administrative data
   o Allocated from pools
       One pool per concrete type
       "Roster" indexes instances
       "Partition" separates allocated/free instances
Dynamic Component System : Features

• Components
• High-performance
   o Small, constant-time operations
       Allocate/free
       Resolve handle
       Get type
       Type implements (derived from)
   o No instance copying
Dynamic Component System : Features

• Components
• High-performance
   o Updates per-type (per-pool)
       Cache friendly
   o Encourage async update
       e.g. on SPU
          Roster: contiguous list of alloc'd instances
          Roster up to partition is DMA list
Dynamic Component System : Features

• Components
• High-performance
   o Resolving handle
       Small, constant-time operation:
          Index into Pool
          Compare generation
          Return Component*
Dynamic Component System : Features

• Components
• High-performance
• Dynamic
   o Runtime composition of game objects
       Dynamically alter behavior without baggage
   o Component allocated == in use
   o Pool sizes == max concurrent allocations
Dynamic Component System : Features

• Components
• High-performance
• Dynamic
   o High-frequency alloc() & free()
       alloc():
          test for availability
          make handle from index & generation
          increment Roster Partition
          Component::Init()
Dynamic Component System : Features

• Components
• High-performance
• Dynamic
   o High-frequency alloc() & free()
       alloc():
       free():
           Component::Deinit()
           swap Roster index with Partition-adjacent
            index
           decrement Partition
           increment generation
Demo : DynamicComponent::Free()
  //free the component from host's component chain                                                 
  void         DynamicComponent::Free( Type type, HostHandle host_handle, Chain& chain,     
                                       ComponentHandle& component_handle );                 
Demo : DynamicComponent::Free()
  //free the component from host's component chain                                                 
  void         DynamicComponent::Free( Type type, HostHandle host_handle, Chain& chain,     
                                       ComponentHandle& component_handle );                 
Demo : DynamicComponent::Free()
  //free the component from host's component chain                                                 
  void         DynamicComponent::Free( Type type, HostHandle host_handle, Chain& chain,     
                                       ComponentHandle& component_handle );                 
Demo : DynamicComponent::Free()
  //free the component from host's component chain                                                 
  void         DynamicComponent::Free( Type type, HostHandle host_handle, Chain& chain,     
                                       ComponentHandle& component_handle );                 
Demo : DynamicComponent::Free()
  //free the component from host's component chain                                                 
  void         DynamicComponent::Free( Type type, HostHandle host_handle, Chain& chain,     
                                       ComponentHandle& component_handle );                 
Dynamic Component System : Features

•   Components
•   High-performance
•   Dynamic
•   System
     o Not all-or-nothing!
     o Examples:
         Conversation
         Script Events
         Shots: no game object
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System

• Implementation by Example
   o API
   o Script Events: Type Registration
   o Navigation: Allocation & Init
   o Shots: Asynchronous Update
namespace DynamicComponent                                                                         
{                                                                                                  
  //                                                                                               
  // Hosts' API                                                                                    
  //                                                                                               
  // Call these from GameObjects (or other objects) that host Dynamic Components                   
  //                                                                                               
___________________________________________________________________________________________________
                                                                                                 
  //allocate a component of type, add it to host's component chain,                                
  //  and optionally park a prius in the component                                                 
  //  returns null if no space is available for allocation                                         
  Component*        Allocate                  ( Type type, HostHandle host_handle,                 
                                                Chain* chain, void* prius = NULL ); 




     

            
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
___________________________________________________________________________________________________

 //resolve a ComponentHandle to a Component
 // returns NULL if component_handle is null or is a stale handle
 // (i.e. component instance has been reused)
 Component*        ResolveHandle            ( Type type, ComponentHandle component_handle );
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
  Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
___________________________________________________________________________________________________

 //get one component of type that belongs to host
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
  Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
  Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
___________________________________________________________________________________________________

 //get the first Component in host's chain that implements the type interface
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
  Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
  Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
  Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
___________________________________________________________________________________________________

 //get all Components of type in host's chain, up to a max of count instances.
 // count should be passed with the size of the component array.
 // on return, count will contain the number of matching components, up to the specified limit.
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
  Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
  Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
  Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
  Component**       GetComponents             ( Type type, HostHandle host_handle,
                                                Chain chain, u32& count );
___________________________________________________________________________________________________

 //get all Components in host's chain that implement type's interface.
 // count should be passed with the size of the component array.
 // on return, count will contain the number of matching components, up to the specified limit.
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
  Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
  Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
  Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
  Component**       GetComponents             ( Type type, HostHandle host_handle,
                                                Chain chain, u32& count );
  Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                                Chain chain, u32& count );
___________________________________________________________________________________________________

 //free the component from host's component chain
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
  Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
  Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
  Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
  Component**       GetComponents             ( Type type, HostHandle host_handle,
                                                Chain chain, u32& count );
  Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                                Chain chain, u32& count );
  void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                                ComponentHandle& component_handle );
___________________________________________________________________________________________________

 //free all of the components in host's component chain
 // (GameObjects automatically free their component chain when they are destroyed)
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );
namespace DynamicComponent
{
  //
  // Hosts' API
  //
  // Call these from GameObjects (or other objects) that host Dynamic Components
  //

 Component*        Allocate                   ( Type type, HostHandle host_handle,
                                                Chain* chain, void* prius = NULL );
  Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
  Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
  Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
  Component**       GetComponents             ( Type type, HostHandle host_handle,
                                                Chain chain, u32& count );
  Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                                Chain chain, u32& count );
  void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                                ComponentHandle& component_handle );
  void              FreeChain                 ( HostHandle host_handle, Chain& chain );
___________________________________________________________________________________________________

  //downcast a Component* to one of its subclasses.
  // please use this instead of the c-style '(Type*)object' so that casts are checked in debug
  //Example:
  // HeadComponent* my_head = COMPONENT_CAST(component_ptr, Head);
  //
#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );
namespace DynamicComponent
{
  // Hosts' API

 Component*        Allocate                  ( Type type, HostHandle host_handle,
                                               Chain* chain, void* prius = NULL );
 Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );
___________________________________________________________________________________________________

 //
 // Systems' API
 //
 // Call these from systems that use the DCS
 //

 //get a list of component types that implement the interface of the given component type
 // count should be passed with the size of the types array.
 // on return, count will contain the number of matching component types,
 // up to the specified limit.
 Type*             GetTypesThatImplement     ( Type type, u32& count );
namespace DynamicComponent
{
  // Hosts' API

 Component*        Allocate                  ( Type type, HostHandle host_handle,
                                               Chain* chain, void* prius = NULL );
 Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

 //
 // Systems' API
 //
 // Call these from systems that use the DCS
 //

  Type*             GetTypesThatImplement     ( Type type, u32& count );
___________________________________________________________________________________________________

 //returns whether component type implements interface
 bool              TypeImplements            ( Type type, Type interface );
namespace DynamicComponent
{
  // Hosts' API

 Component*        Allocate                  ( Type type, HostHandle host_handle,
                                               Chain* chain, void* prius = NULL );
 Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

 //
 // Systems' API
 //
 // Call these from systems that use the DCS
 //

  Type*             GetTypesThatImplement     ( Type type, u32& count );
  bool              TypeImplements            ( Type type, Type interface );
___________________________________________________________________________________________________

 //returns the number of components of type that are currently allocated
 u32               GetNumAllocated           ( Type type );
namespace DynamicComponent
{
  // Hosts' API

 Component*        Allocate                  ( Type type, HostHandle host_handle,
                                               Chain* chain, void* prius = NULL );
 Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

 //
 // Systems' API
 //
 // Call these from systems that use the DCS
 //

  Type*             GetTypesThatImplement     ( Type type, u32& count );
  bool              TypeImplements            ( Type type, Type interface );
  u32               GetNumAllocated           ( Type type );
___________________________________________________________________________________________________

 //returns an array of pointers to all allocated components of type, their count,
 // and their size
 Component**       GetComponents             ( Type type, u32& count );
 //returns an array of all components of type (including unallocated instances!),
 // an array of the indices of allocated components within that array,
 // and the count of indices
 Component*        GetComponentsIndexed      ( Type type, u16*& indices, u32& count );
namespace DynamicComponent
{
  // Hosts' API

 Component*        Allocate                  ( Type type, HostHandle host_handle,
                                               Chain* chain, void* prius = NULL );
 Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

 //
 // Systems' API
 //
 // Call these from systems that use the DCS
 //

  Type*             GetTypesThatImplement     ( Type type, u32& count );
  bool              TypeImplements            ( Type type, Type interface );
  u32               GetNumAllocated           ( Type type );
  Component**       GetComponents             ( Type type, u32& count );
  Component*        GetComponentsIndexed      ( Type type, u16*& indices, u32& count );
___________________________________________________________________________________________________

 //updates all components of those types that want to be updated in the given UpdateStage
 void              UpdateComponents          ( UpdateStage::Enum stage );
namespace DynamicComponent
{
  // Hosts' API

 Component*        Allocate                  ( Type type, HostHandle host_handle,
                                               Chain* chain, void* prius = NULL );
 Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

 //
 // Systems' API
 //
 // Call these from systems that use the DCS
 //

  Type*             GetTypesThatImplement     ( Type type, u32& count );
  bool              TypeImplements            ( Type type, Type interface );
  u32               GetNumAllocated           ( Type type );
  Component**       GetComponents             ( Type type, u32& count );
  Component*        GetComponentsIndexed      ( Type type, u16*& indices, u32& count );
  void              UpdateComponents          ( UpdateStage::Enum stage );
___________________________________________________________________________________________________

 //frees a component that was allocated without a host, and is not in any chain
 void              Free                      ( Type type, ComponentHandle& component_handle );
namespace DynamicComponent
{
  // Hosts' API

 Component*        Allocate                  ( Type type, HostHandle host_handle,
                                               Chain* chain, void* prius = NULL );
 Component*        ResolveHandle             ( Type type, ComponentHandle component_handle );
 Component*        Get                       ( Type type, HostHandle host_handle, Chain chain );
 Component*        GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
 Component**       GetComponents             ( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 Component**       GetComponentsThatImplement( Type type, HostHandle host_handle,
                                               Chain chain, u32& count );
 void              Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                               ComponentHandle& component_handle );
 void              FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

 //
 // Systems' API
 //
 // Call these from systems that use the DCS
 //

  Type*             GetTypesThatImplement     ( Type type, u32& count );
  bool              TypeImplements            ( Type type, Type interface );
  u32               GetNumAllocated           ( Type type );
  Component**       GetComponents             ( Type type, u32& count );
  Component*        GetComponentsIndexed      ( Type type, u16*& indices, u32& count );
  void              UpdateComponents          ( UpdateStage::Enum stage );
  void              Free                      ( Type type, ComponentHandle& component_handle );
___________________________________________________________________________________________________

 //returns the current PPU UpdateStage::Enum.
 // will be UpdateStage::None unless UpdateComponents() is on the stack.
 UpdateStage::Enum GetCurrentUpdateStage      ( );
namespace DynamicComponent
{
  // Hosts' API

    Component*       Allocate                  ( Type type, HostHandle host_handle,
                                                 Chain* chain, void* prius = NULL );
    Component*       ResolveHandle             ( Type type, ComponentHandle component_handle );
    Component*       Get                       ( Type type, HostHandle host_handle, Chain chain );
    Component*       GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
    Component**      GetComponents             ( Type type, HostHandle host_handle,
                                                 Chain chain, u32& count );
    Component**      GetComponentsThatImplement( Type type, HostHandle host_handle,
                                                 Chain chain, u32& count );
    void             Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                                 ComponentHandle& component_handle );
    void             FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

    //
    // Systems' API
    //
    // Call these from systems that use the DCS
    //

  Type*             GetTypesThatImplement     ( Type type, u32& count );
  bool              TypeImplements            ( Type type, Type interface );
  u32               GetNumAllocated           ( Type type );
  Component**       GetComponents             ( Type type, u32& count );
  Component*        GetComponentsIndexed      ( Type type, u16*& indices, u32& count );
  void              UpdateComponents          ( UpdateStage::Enum stage );
  void              Free                      ( Type type, ComponentHandle& component_handle );
  UpdateStage::Enum GetCurrentUpdateStage     ( );
___________________________________________________________________________________________________

    //returns true iff type updates in stage
    u8                GetTypeUpdateStages         ( Type type );
}
namespace DynamicComponent
{
  // Hosts' API

    Component*          Allocate                  ( Type type, HostHandle host_handle,
                                                    Chain* chain, void* prius = NULL );
    Component*          ResolveHandle             ( Type type, ComponentHandle component_handle );
    Component*          Get                       ( Type type, HostHandle host_handle, Chain chain );
    Component*          GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
    Component**         GetComponents             ( Type type, HostHandle host_handle,
                                                    Chain chain, u32& count );
    Component**         GetComponentsThatImplement( Type type, HostHandle host_handle,
                                                    Chain chain, u32& count );
    void                Free                      ( Type type, HostHandle host_handle, Chain& chain,
                                                    ComponentHandle& component_handle );
    void                FreeChain                 ( HostHandle host_handle, Chain& chain );

#define COMPONENT_CAST(component, type) 
  ((type##Component*)ValidCast(component, DynamicComponent::type))
  inline Component* ValidCast                 ( Component* component, Type type );

    // Systems' API

    Type*               GetTypesThatImplement     (   Type type, u32& count );
    bool                TypeImplements            (   Type type, Type interface );
    u32                 GetNumAllocated           (   Type type );
    Component**         GetComponents             (   Type type, u32& count );
    Component*          GetComponentsIndexed      (   Type type, u16*& indices, u32& count );
    void                UpdateComponents          (   UpdateStage::Enum stage );
    void                Free                      (   Type type, ComponentHandle& component_handle );
    UpdateStage::Enum   GetCurrentUpdateStage     (   );
    u8                  GetTypeUpdateStages       (   Type type );
}
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System

• Implementation by Example
   o API
   o Script Events: Type Registration
   o Navigation: Allocation & Init
   o Shots: Asynchronous Update
Script Events : Type Registration

• Script Events are Components
   o Hosted by the System
   o Possibly related to a Game Object


• Registered (allocated) from Lua
   o When conditions are met, call back


• Satisfaction:
   1.Updated: poll their conditions
   2.Notified by gameplay
Script Events : Type Registration

Notified             Updated

 •   Checkpoint       • Location
 •   Damage           • Timer
 •   Death            • Visible
 •   NumAlive
 •   Active
 •   Custom
      o Reload
      o Zoom
      o Grapple
      o SeatEnter
Script Events: Type Registration
  namespace DynamicComponent
  {
      typedef u16 Type;
      Type    unregistered_type       = 0xFFFF;
      Type    TypeRegistrar::RegisterType(
          const char*                 name,
          Type                        base_type           = unregistered_type,
          UpdateStage::Enum           update_stages       = UpdateStage::None,
          AsyncUpdateStage::Enum      async_update_stages = AsyncUpdateStage::None);
  }
Script Events: Type Registration
  namespace DynamicComponent
  {
      typedef u16 Type;
      Type    unregistered_type       = 0xFFFF;
      Type    TypeRegistrar::RegisterType(
          const char*                 name,
          Type                        base_type           = unregistered_type,
          UpdateStage::Enum           update_stages       = UpdateStage::None,
          AsyncUpdateStage::Enum      async_update_stages = AsyncUpdateStage::None);
  }




  using namespace DynamicComponent;

  void ScriptEventSystem::Init()
  {
  m_event_type        = TypeRegistrar::RegisterType("ScriptEvent");
  m_checkpoint_type   = TypeRegistrar::RegisterType("CheckpointEvent", m_event_type);
  m_location_type     = TypeRegistrar::RegisterType(
      "LocationEvent",
      m_event_type,                  //base class is ScriptEvent
      UpdateStage::PostUpdate,       //automatically updated on PPU during PostUpdate
      AsyncUpdateStage::PreUpdate);  //and on the SPU during the PreUpdate stage
  }
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System

• Implementation by Example
   o API
   o Script Events: Type Registration
   o Navigation: Allocation & Init
   o Shots: Asynchronous Update
Navigation : Allocation & Initialization

• NavComponents are hosted by Game Objects

• Updated by the Navigation system
Navigation : Allocation & Initialization

• Remember the API call to allocate a component:
  //allocate a component of type, add it to host's component chain,
  //  and optionally park a prius in the component
  //  returns null if no space is available for allocation
  Component*        DynamicComponent::Allocate( Type type, HostHandle host_handle,
                                                Chain* chain, void*   prius = NULL );




• WTF is a prius?
Navigation : Allocation & Initialization

• Remember the API call to allocate a component:
   //allocate a component of type, add it to host's component chain,
   //  and optionally park a prius in the component
   //  returns null if no space is available for allocation
   Component*        DynamicComponent::Allocate( Type type, HostHandle host_handle,
                                                 Chain* chain, void*   prius = NULL );




 • WTF is a prius?
    o initialization data
    o Runtime or design-time data
 
 • void* But is that safe!?
Navigation : Allocation & Initialization
• Initialization
   o NavQuery is the Prius for a NavComponent
   o NavQuery::Submit() allocates a NavComponent, and
     passes itself as the prius.
NavComponent* NavQuery::Submit(GameObject* host)
{
  DynamicComponent::Type        type      = GetComponentType(); //virtual member of NavQuery
  DynamicComponent::Component*  component = host->AllocateComponent(type, this);
  NavComponent*                 nav       = COMPONENT_CAST(component, Nav);
  return nav;
}



• host->AllocateComponent()?  Helper in GameObject:
DynamicComponentComponent*
  GameObject::AllocateComponent(DynamicComponent::Type type, void* prius)
{
  return DynamicComponent::Allocate(type, m_handle, &m_component_chain, prius);
}
Navigation : Allocation & Initialization

• Gameplay code example
void FollowerBot::Initialize(GameObject* target)
{
  Nav::GameObjectQuery source_query  (this);    //query closest point to game object
  Nav::GameObjectQuery target_query  (target);
  Nav::PathQuery       path_query    (source_query, target_query);

  Nav::PathComponent*  m_path        = path_query.Submit();
}




• When navigation components are updated, endpoints
  and path are dynamically recomputed on SPU
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System

• Implementation by Example
   o API
   o Script Events: Type Registration
   o Navigation: Allocation & Init
   o Shots: Asynchronous Update
Shots : Asynchronous Update

• Hosted by Game Object
• Replaces Projectile GameObjects

• Two DynamicComponent Type hierarchies:
   o Shot represents a state machine
       Notified
   o ShotAction represents the state of a Shot
       Updated
       Shared
Shots : Asynchronous Update
  #ifndef SPU //PPU only

  class ShotMoveForward : public ShotAction
  {
    DERIVED_COMPONENT(ShotMoveForward, ShotAction)

  public:

    virtual void    ParkPrius    (void* prius);
    virtual void    Update       (UpdateStage::Enum stage);

  #else        //SPU only

  struct ShotMoveForward
  {
    puspu_vec4      m_location    ALIGNED(16);    //shadows ShotAction::m_next_location on PPU

  #endif       //PPU & SPU shared

    puspu_vec4      m_direction;
    f32             m_speed;
  }                               __attribute__((aligned(16)));




• ShotAction::m_next_location on PPU and
  ShotMoveForward::m_location on SPU share the same address
Shots : Asynchronous Update

• How?  "Sentinel"
// async components must indicate where their async data begins
#define BEGIN_ASYNC_COMPONENT_DATA                        
    u32 m_async_data[0] __attribute__((aligned(16)));     




class ShotAction : public DynamicComponent::Component
{
  COMPONENT(ShotAction);

  // ...

  DynamicComponent::Handle    m_shot;
  DynamicComponent::Type      m_shot_type;

  BEGIN_ASYNC_COMPONENT_DATA

  vec4f                       m_next_location;
};
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System

• Implementation by Example
A Dynamic Component Architecture
   for High Performance Gameplay


• Purpose

• The Dynamic Component System

• Implementation by Example

• Thank You!
• Questions
A Dynamic Component Architecture
    for High Performance Gameplay

• Visit me on the Web:
  http://www.TerranceCohen.com


• Follow me on Twitter:
  http://twitter.com/terrance_cohen


• Connect with me on LinkedIn:
  http://www.linkedin.com/in/terrancecohen


• Ask me anything:
  http://www.formspring.me/terrancecohen
A Dynamic Component Architecture
      for High Performance Gameplay

Terrance Cohen
Lead Systems Engineer
Insomniac Games
www.TerranceCohen.com
Twitter: @terrance_cohen

More Related Content

PDF
Internship final report@Treasure Data Inc.
PDF
Performance van Java 8 en verder - Jeroen Borgers
PDF
Writing Asynchronous Programs with Scala & Akka
PPTX
Practical Malware Analysis: Ch 4 A Crash Course in x86 Disassembly
PDF
Julie Michelman - Pandas, Pipelines, and Custom Transformers
PPTX
Paws: A Perl AWS SDK - YAPC Europe 2015
PDF
Killzone Shadow Fall: Creating Art Tools For A New Generation Of Games
PPTX
Practical Malware Analysis: Ch 5: IDA Pro
Internship final report@Treasure Data Inc.
Performance van Java 8 en verder - Jeroen Borgers
Writing Asynchronous Programs with Scala & Akka
Practical Malware Analysis: Ch 4 A Crash Course in x86 Disassembly
Julie Michelman - Pandas, Pipelines, and Custom Transformers
Paws: A Perl AWS SDK - YAPC Europe 2015
Killzone Shadow Fall: Creating Art Tools For A New Generation Of Games
Practical Malware Analysis: Ch 5: IDA Pro

What's hot (9)

PDF
2014-02-20 | Akka Concurrency (Vienna Scala User Group)
PPTX
Akka Actor presentation
PPTX
The dark side of Akka and the remedy - bp.scala meetup
PDF
[UniteKorea2013] The Unity Rendering Pipeline
KEY
Building Distributed Systems in Scala
PDF
Course 102: Lecture 22: Package Management
PPT
Orchid Programming
PDF
2.4 Optimizing your Visual COBOL Applications
PDF
CNIT 126 4: A Crash Course in x86 Disassembly
2014-02-20 | Akka Concurrency (Vienna Scala User Group)
Akka Actor presentation
The dark side of Akka and the remedy - bp.scala meetup
[UniteKorea2013] The Unity Rendering Pipeline
Building Distributed Systems in Scala
Course 102: Lecture 22: Package Management
Orchid Programming
2.4 Optimizing your Visual COBOL Applications
CNIT 126 4: A Crash Course in x86 Disassembly
Ad

Viewers also liked (6)

PDF
Building Gameplay
PPTX
Gameplay
PPT
Gameplay design patterns presentation at dragon's lair, stockholm, sweden 201...
PDF
Gameplay Concept Tool
PPTX
Designing Core Gameplay for Everyone - GDC 2012
PDF
From Experiment Gameplay to the Wonderful World of Goo
Building Gameplay
Gameplay
Gameplay design patterns presentation at dragon's lair, stockholm, sweden 201...
Gameplay Concept Tool
Designing Core Gameplay for Everyone - GDC 2012
From Experiment Gameplay to the Wonderful World of Goo
Ad

Similar to GDC 2010 - A Dynamic Component Architecture for High Performance Gameplay - May, 2010 (20)

PPT
GDC 2010 - A Dynamic Component Architecture for High Performance Gameplay
PDF
Style & Design Principles 03 - Component-Based Entity Systems
PPTX
Video Games Style Minitheme by Slidesgo.pptx
PPTX
Initial design (Game Architecture)
PPTX
98 374 Lesson 06-slides
PPTX
Game object models - Game Engine Architecture
PDF
Game Programming 02 - Component-Based Entity Systems
PPTX
Beginning direct3d gameprogramming02_overviewofhalandcom_20160408_jintaeks
PPTX
PDF
a data driven game object system
PDF
State-Based Scripting in Uncharted 2: Among Thieves
PDF
IntroToEngineDevelopment.pdf
PDF
OGDC 2014_Entity system in mobile game development_Mr. Cody nguyen
PPT
Game development
PPT
Cse191 01
PDF
Educational Game Design Thesis
KEY
StateScriptingInUncharted2
PDF
Game Models - A Different Approach
PDF
Creating Video Games From Scratch Sky Con
PDF
Component-Based Entity Systems (Demo)
GDC 2010 - A Dynamic Component Architecture for High Performance Gameplay
Style & Design Principles 03 - Component-Based Entity Systems
Video Games Style Minitheme by Slidesgo.pptx
Initial design (Game Architecture)
98 374 Lesson 06-slides
Game object models - Game Engine Architecture
Game Programming 02 - Component-Based Entity Systems
Beginning direct3d gameprogramming02_overviewofhalandcom_20160408_jintaeks
a data driven game object system
State-Based Scripting in Uncharted 2: Among Thieves
IntroToEngineDevelopment.pdf
OGDC 2014_Entity system in mobile game development_Mr. Cody nguyen
Game development
Cse191 01
Educational Game Design Thesis
StateScriptingInUncharted2
Game Models - A Different Approach
Creating Video Games From Scratch Sky Con
Component-Based Entity Systems (Demo)

Recently uploaded (20)

PPT
Teaching material agriculture food technology
PPTX
sap open course for s4hana steps from ECC to s4
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Electronic commerce courselecture one. Pdf
PDF
Approach and Philosophy of On baking technology
PDF
Machine learning based COVID-19 study performance prediction
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
KodekX | Application Modernization Development
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
Teaching material agriculture food technology
sap open course for s4hana steps from ECC to s4
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
20250228 LYD VKU AI Blended-Learning.pptx
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Empathic Computing: Creating Shared Understanding
Encapsulation_ Review paper, used for researhc scholars
Review of recent advances in non-invasive hemoglobin estimation
Electronic commerce courselecture one. Pdf
Approach and Philosophy of On baking technology
Machine learning based COVID-19 study performance prediction
The Rise and Fall of 3GPP – Time for a Sabbatical?
KodekX | Application Modernization Development
Programs and apps: productivity, graphics, security and other tools
MIND Revenue Release Quarter 2 2025 Press Release
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Per capita expenditure prediction using model stacking based on satellite ima...

GDC 2010 - A Dynamic Component Architecture for High Performance Gameplay - May, 2010

  • 1. A Dynamic Component Architecture for High Performance Gameplay Terrance Cohen Lead Systems Engineer Insomniac Games
  • 2. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example • Questions (note slide #)
  • 3. A Dynamic Component Architecture for High Performance Gameplay • Purpose o Statement of Problem o Proposed Solution • The Dynamic Component System • Implementation by Example
  • 4. Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy o Memory: binds data @ compile time  Allocated throughout lifetime
  • 5. Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence  Arrays of non-homogeneous objects  Virtual dispatch  Fragmented instance data
  • 6. Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence o Architecture: capability <=> inheritance  Fixed at compile time  Fully determined by class  Change capabilities -> change hierarchy
  • 7. Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence o Architecture: capability <=> inheritance • "What we're used to" • But select the best tool for the job.
  • 8. Purpose : Statement of Problem • Monolithic / deep Game Object hierarchy: o Memory: binds data @ compile time o Performance: poor cache coherence o Architecture: capability <=> inheritance • "What we're used to" • But select the best tool for the job. • There's a better way!
  • 9. A Dynamic Component Architecture for High Performance Gameplay • Purpose o Statement of Problem o Proposed Solution • The Dynamic Component System • Implementation by Example
  • 10. Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime
  • 11. Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime • Simple! • Thank you for coming!
  • 12. Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime • Simple! • Thank you for coming! o Oh, you want details !?!
  • 13. Purpose : Proposed Solution • Construction of Game Object through composition of components at runtime • Small chunks • Represent a data transformation
  • 14. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System o Features • Implementation by Example
  • 15. The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1 type) o Resistance 2 - "Early Adopters" (32 types) o Ongoing (295 types as of May 1st 2010)  Majority of new gameplay code  Large portions of old gameplay refactored
  • 16. The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1 type) o Resistance 2 - "Early Adopters" (32 types) o Ongoing (295 types as of May 1st 2010)  Majority of new gameplay code  Large portions of old gameplay refactored • So it’s mature.
  • 17. The Dynamic Component System • Evolution o Resistance 1 - Proof of Concept (1 type) o Resistance 2 - "Early Adopters" (32 types) o Ongoing (295 types as of May 1st 2010)  Majority of new gameplay code  Large portions of old gameplay refactored • So it’s mature. (No, not that way.)
  • 18. The Dynamic Component System • Side-by-side implementation o Not necessary to refactor existing code o Coexist with components • General solution
  • 19. The Dynamic Component System • Does not address matters of o Reflection o Serialization o Data building o Instance versioning o ... those things are handled separately  outside the scope of this discussion
  • 20. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System o Features • Implementation by Example
  • 21. Dynamic Component System : Features • Components • High-performance • Dynamic • System
  • 22. Dynamic Component System : Features • Components o Originally Aspects o Base Component class  8 bytes of administrative data o Allocated from pools  One pool per concrete type  "Roster" indexes instances  "Partition" separates allocated/free instances
  • 23. Dynamic Component System : Features • Components • High-performance o Small, constant-time operations  Allocate/free  Resolve handle  Get type  Type implements (derived from) o No instance copying
  • 24. Dynamic Component System : Features • Components • High-performance o Updates per-type (per-pool)  Cache friendly o Encourage async update  e.g. on SPU  Roster: contiguous list of alloc'd instances  Roster up to partition is DMA list
  • 25. Dynamic Component System : Features • Components • High-performance o Resolving handle  Small, constant-time operation:  Index into Pool  Compare generation  Return Component*
  • 26. Dynamic Component System : Features • Components • High-performance • Dynamic o Runtime composition of game objects  Dynamically alter behavior without baggage o Component allocated == in use o Pool sizes == max concurrent allocations
  • 27. Dynamic Component System : Features • Components • High-performance • Dynamic o High-frequency alloc() & free()  alloc():  test for availability  make handle from index & generation  increment Roster Partition  Component::Init()
  • 28. Dynamic Component System : Features • Components • High-performance • Dynamic o High-frequency alloc() & free()  alloc():  free():  Component::Deinit()  swap Roster index with Partition-adjacent index  decrement Partition  increment generation
  • 34. Dynamic Component System : Features • Components • High-performance • Dynamic • System o Not all-or-nothing! o Examples:  Conversation  Script Events  Shots: no game object
  • 35. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update
  • 36. namespace DynamicComponent                                                                          {                                                                                                     //                                                                                                  // Hosts' API                                                                                       //                                                                                                  // Call these from GameObjects (or other objects) that host Dynamic Components                      //                                                                                                ___________________________________________________________________________________________________                                                                                                     //allocate a component of type, add it to host's component chain,                                   //  and optionally park a prius in the component                                                    //  returns null if no space is available for allocation                                            Component*        Allocate                  ( Type type, HostHandle host_handle,                                                                  Chain* chain, void* prius = NULL );                    
  • 37. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); ___________________________________________________________________________________________________ //resolve a ComponentHandle to a Component // returns NULL if component_handle is null or is a stale handle // (i.e. component instance has been reused) Component* ResolveHandle ( Type type, ComponentHandle component_handle );
  • 38. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); ___________________________________________________________________________________________________ //get one component of type that belongs to host Component* Get ( Type type, HostHandle host_handle, Chain chain );
  • 39. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); ___________________________________________________________________________________________________ //get the first Component in host's chain that implements the type interface Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain );
  • 40. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); ___________________________________________________________________________________________________ //get all Components of type in host's chain, up to a max of count instances. // count should be passed with the size of the component array. // on return, count will contain the number of matching components, up to the specified limit. Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count );
  • 41. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); ___________________________________________________________________________________________________ //get all Components in host's chain that implement type's interface. // count should be passed with the size of the component array. // on return, count will contain the number of matching components, up to the specified limit. Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count );
  • 42. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); ___________________________________________________________________________________________________ //free the component from host's component chain void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle );
  • 43. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); ___________________________________________________________________________________________________ //free all of the components in host's component chain // (GameObjects automatically free their component chain when they are destroyed) void FreeChain ( HostHandle host_handle, Chain& chain );
  • 44. namespace DynamicComponent { // // Hosts' API // // Call these from GameObjects (or other objects) that host Dynamic Components // Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); ___________________________________________________________________________________________________ //downcast a Component* to one of its subclasses. // please use this instead of the c-style '(Type*)object' so that casts are checked in debug //Example: // HeadComponent* my_head = COMPONENT_CAST(component_ptr, Head); // #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type );
  • 45. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); ___________________________________________________________________________________________________ // // Systems' API // // Call these from systems that use the DCS // //get a list of component types that implement the interface of the given component type // count should be passed with the size of the types array. // on return, count will contain the number of matching component types, // up to the specified limit. Type* GetTypesThatImplement ( Type type, u32& count );
  • 46. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // // Systems' API // // Call these from systems that use the DCS // Type* GetTypesThatImplement ( Type type, u32& count ); ___________________________________________________________________________________________________ //returns whether component type implements interface bool TypeImplements ( Type type, Type interface );
  • 47. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // // Systems' API // // Call these from systems that use the DCS // Type* GetTypesThatImplement ( Type type, u32& count ); bool TypeImplements ( Type type, Type interface ); ___________________________________________________________________________________________________ //returns the number of components of type that are currently allocated u32 GetNumAllocated ( Type type );
  • 48. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // // Systems' API // // Call these from systems that use the DCS // Type* GetTypesThatImplement ( Type type, u32& count ); bool TypeImplements ( Type type, Type interface ); u32 GetNumAllocated ( Type type ); ___________________________________________________________________________________________________ //returns an array of pointers to all allocated components of type, their count, // and their size Component** GetComponents ( Type type, u32& count ); //returns an array of all components of type (including unallocated instances!), // an array of the indices of allocated components within that array, // and the count of indices Component* GetComponentsIndexed ( Type type, u16*& indices, u32& count );
  • 49. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // // Systems' API // // Call these from systems that use the DCS // Type* GetTypesThatImplement ( Type type, u32& count ); bool TypeImplements ( Type type, Type interface ); u32 GetNumAllocated ( Type type ); Component** GetComponents ( Type type, u32& count ); Component* GetComponentsIndexed ( Type type, u16*& indices, u32& count ); ___________________________________________________________________________________________________ //updates all components of those types that want to be updated in the given UpdateStage void UpdateComponents ( UpdateStage::Enum stage );
  • 50. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // // Systems' API // // Call these from systems that use the DCS // Type* GetTypesThatImplement ( Type type, u32& count ); bool TypeImplements ( Type type, Type interface ); u32 GetNumAllocated ( Type type ); Component** GetComponents ( Type type, u32& count ); Component* GetComponentsIndexed ( Type type, u16*& indices, u32& count ); void UpdateComponents ( UpdateStage::Enum stage ); ___________________________________________________________________________________________________ //frees a component that was allocated without a host, and is not in any chain void Free ( Type type, ComponentHandle& component_handle );
  • 51. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // // Systems' API // // Call these from systems that use the DCS // Type* GetTypesThatImplement ( Type type, u32& count ); bool TypeImplements ( Type type, Type interface ); u32 GetNumAllocated ( Type type ); Component** GetComponents ( Type type, u32& count ); Component* GetComponentsIndexed ( Type type, u16*& indices, u32& count ); void UpdateComponents ( UpdateStage::Enum stage ); void Free ( Type type, ComponentHandle& component_handle ); ___________________________________________________________________________________________________ //returns the current PPU UpdateStage::Enum. // will be UpdateStage::None unless UpdateComponents() is on the stack. UpdateStage::Enum GetCurrentUpdateStage ( );
  • 52. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // // Systems' API // // Call these from systems that use the DCS // Type* GetTypesThatImplement ( Type type, u32& count ); bool TypeImplements ( Type type, Type interface ); u32 GetNumAllocated ( Type type ); Component** GetComponents ( Type type, u32& count ); Component* GetComponentsIndexed ( Type type, u16*& indices, u32& count ); void UpdateComponents ( UpdateStage::Enum stage ); void Free ( Type type, ComponentHandle& component_handle ); UpdateStage::Enum GetCurrentUpdateStage ( ); ___________________________________________________________________________________________________ //returns true iff type updates in stage u8 GetTypeUpdateStages ( Type type ); }
  • 53. namespace DynamicComponent { // Hosts' API Component* Allocate ( Type type, HostHandle host_handle, Chain* chain, void* prius = NULL ); Component* ResolveHandle ( Type type, ComponentHandle component_handle ); Component* Get ( Type type, HostHandle host_handle, Chain chain ); Component* GetComponentThatImplements( Type type, HostHandle host_handle, Chain chain ); Component** GetComponents ( Type type, HostHandle host_handle, Chain chain, u32& count ); Component** GetComponentsThatImplement( Type type, HostHandle host_handle, Chain chain, u32& count ); void Free ( Type type, HostHandle host_handle, Chain& chain, ComponentHandle& component_handle ); void FreeChain ( HostHandle host_handle, Chain& chain ); #define COMPONENT_CAST(component, type) ((type##Component*)ValidCast(component, DynamicComponent::type)) inline Component* ValidCast ( Component* component, Type type ); // Systems' API Type* GetTypesThatImplement ( Type type, u32& count ); bool TypeImplements ( Type type, Type interface ); u32 GetNumAllocated ( Type type ); Component** GetComponents ( Type type, u32& count ); Component* GetComponentsIndexed ( Type type, u16*& indices, u32& count ); void UpdateComponents ( UpdateStage::Enum stage ); void Free ( Type type, ComponentHandle& component_handle ); UpdateStage::Enum GetCurrentUpdateStage ( ); u8 GetTypeUpdateStages ( Type type ); }
  • 54. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update
  • 55. Script Events : Type Registration • Script Events are Components o Hosted by the System o Possibly related to a Game Object • Registered (allocated) from Lua o When conditions are met, call back • Satisfaction: 1.Updated: poll their conditions 2.Notified by gameplay
  • 56. Script Events : Type Registration Notified Updated • Checkpoint • Location • Damage • Timer • Death • Visible • NumAlive • Active • Custom o Reload o Zoom o Grapple o SeatEnter
  • 57. Script Events: Type Registration   namespace DynamicComponent   {       typedef u16 Type;       Type    unregistered_type       = 0xFFFF;       Type    TypeRegistrar::RegisterType(           const char*                 name,           Type                        base_type           = unregistered_type,           UpdateStage::Enum           update_stages       = UpdateStage::None,           AsyncUpdateStage::Enum      async_update_stages = AsyncUpdateStage::None);   }
  • 58. Script Events: Type Registration   namespace DynamicComponent   {       typedef u16 Type;       Type    unregistered_type       = 0xFFFF;       Type    TypeRegistrar::RegisterType(           const char*                 name,           Type                        base_type           = unregistered_type,           UpdateStage::Enum           update_stages       = UpdateStage::None,           AsyncUpdateStage::Enum      async_update_stages = AsyncUpdateStage::None);   }   using namespace DynamicComponent;   void ScriptEventSystem::Init()   {   m_event_type        = TypeRegistrar::RegisterType("ScriptEvent");   m_checkpoint_type   = TypeRegistrar::RegisterType("CheckpointEvent", m_event_type);   m_location_type     = TypeRegistrar::RegisterType(       "LocationEvent",       m_event_type,                  //base class is ScriptEvent       UpdateStage::PostUpdate,       //automatically updated on PPU during PostUpdate       AsyncUpdateStage::PreUpdate);  //and on the SPU during the PreUpdate stage   }
  • 59. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update
  • 60. Navigation : Allocation & Initialization • NavComponents are hosted by Game Objects • Updated by the Navigation system
  • 61. Navigation : Allocation & Initialization • Remember the API call to allocate a component:   //allocate a component of type, add it to host's component chain,   //  and optionally park a prius in the component   //  returns null if no space is available for allocation   Component*        DynamicComponent::Allocate( Type type, HostHandle host_handle,                                                 Chain* chain, void* prius = NULL ); • WTF is a prius?
  • 62. Navigation : Allocation & Initialization • Remember the API call to allocate a component:   //allocate a component of type, add it to host's component chain,   //  and optionally park a prius in the component   //  returns null if no space is available for allocation   Component*        DynamicComponent::Allocate( Type type, HostHandle host_handle,                                                 Chain* chain, void* prius = NULL ); • WTF is a prius? o initialization data o Runtime or design-time data   • void* But is that safe!?
  • 63. Navigation : Allocation & Initialization • Initialization o NavQuery is the Prius for a NavComponent o NavQuery::Submit() allocates a NavComponent, and passes itself as the prius. NavComponent* NavQuery::Submit(GameObject* host) {   DynamicComponent::Type        type      = GetComponentType(); //virtual member of NavQuery   DynamicComponent::Component*  component = host->AllocateComponent(type, this);   NavComponent*                 nav       = COMPONENT_CAST(component, Nav);   return nav; } • host->AllocateComponent()?  Helper in GameObject: DynamicComponentComponent*   GameObject::AllocateComponent(DynamicComponent::Type type, void* prius) {   return DynamicComponent::Allocate(type, m_handle, &m_component_chain, prius); }
  • 64. Navigation : Allocation & Initialization • Gameplay code example void FollowerBot::Initialize(GameObject* target) {   Nav::GameObjectQuery source_query  (this);    //query closest point to game object   Nav::GameObjectQuery target_query  (target);   Nav::PathQuery       path_query    (source_query, target_query);   Nav::PathComponent*  m_path        = path_query.Submit(); } • When navigation components are updated, endpoints and path are dynamically recomputed on SPU
  • 65. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example o API o Script Events: Type Registration o Navigation: Allocation & Init o Shots: Asynchronous Update
  • 66. Shots : Asynchronous Update • Hosted by Game Object • Replaces Projectile GameObjects • Two DynamicComponent Type hierarchies: o Shot represents a state machine  Notified o ShotAction represents the state of a Shot  Updated  Shared
  • 67. Shots : Asynchronous Update   #ifndef SPU //PPU only   class ShotMoveForward : public ShotAction   {     DERIVED_COMPONENT(ShotMoveForward, ShotAction)   public:     virtual void    ParkPrius    (void* prius);     virtual void    Update       (UpdateStage::Enum stage);   #else        //SPU only   struct ShotMoveForward   {     puspu_vec4      m_location    ALIGNED(16);    //shadows ShotAction::m_next_location on PPU   #endif       //PPU & SPU shared     puspu_vec4      m_direction;     f32             m_speed;   }                               __attribute__((aligned(16))); • ShotAction::m_next_location on PPU and ShotMoveForward::m_location on SPU share the same address
  • 68. Shots : Asynchronous Update • How?  "Sentinel" // async components must indicate where their async data begins #define BEGIN_ASYNC_COMPONENT_DATA                             u32 m_async_data[0] __attribute__((aligned(16)));      class ShotAction : public DynamicComponent::Component {   COMPONENT(ShotAction);   // ...   DynamicComponent::Handle    m_shot;   DynamicComponent::Type      m_shot_type;   BEGIN_ASYNC_COMPONENT_DATA   vec4f                       m_next_location; };
  • 69. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example
  • 70. A Dynamic Component Architecture for High Performance Gameplay • Purpose • The Dynamic Component System • Implementation by Example • Thank You! • Questions
  • 71. A Dynamic Component Architecture for High Performance Gameplay • Visit me on the Web: http://www.TerranceCohen.com • Follow me on Twitter: http://twitter.com/terrance_cohen • Connect with me on LinkedIn: http://www.linkedin.com/in/terrancecohen • Ask me anything: http://www.formspring.me/terrancecohen
  • 72. A Dynamic Component Architecture for High Performance Gameplay Terrance Cohen Lead Systems Engineer Insomniac Games www.TerranceCohen.com Twitter: @terrance_cohen

Editor's Notes

  • #2: Follow me on Twitter: http://twitter.com/terrance_cohen Connect with me on LinkedIn: http://www.linkedin.com/in/terrancecohen Ask me a question: http://www.formspring.me/terrancecohen
  • #3: At a high level, I have three sections to this discussion First, we&apos;ll talk about, &quot;Why are we here?&quot; Not, &quot;Why are we here on this earth,&quot; that&apos;s outside the scope of this presentation.  I mean, &quot;What do I hope you&apos;ll conclude from this.&quot; We&apos;ll discuss the problem we&apos;re trying to solve, and my approach to a solution Second, we&apos;ll talk about details of my solution, which I call the Dynamic Component System. We&apos;ll discuss features of the system, and why it&apos;s a good solution And third, we&apos;ll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
  • #4: First we&apos;ll talk about the problem we&apos;re trying to solve.
  • #5: This is the traditional OO game object based gameplay model Member data allocated throughout lifetime, even when not in use Some designs will allocate some data separately from the game object, e.g. a physics instance But this is counter to the architecture, rather than central to the architecture, And each system is likely to roll it’s own solution, since the unifying architecture doesn’t support it
  • #6: Encourages iteration over arrays of non-homogeneous objects Encourages virtual dispatch in the most unpredictable patterns Instance data fragmented by unused elements These are general issues with performance under OO
  • #7: Capabilities of an object are fixed at compile time, fully determined by class Changing capabilities means changing hierarchy often impossible without code duplication or multiple inheritance of implementation both have serious drawbacks Changing capabilities through multiple inheritance: Some will argue that there are no serious drawbacks to MI Beyond the scope of this discussion Even for strong proponents of such architecture, should agree that it&apos;s not a good solution to this  problem Messy unification of disparate hierarchies
  • #8: &quot;What we&apos;re used to,&quot; so easy to overlook flaws Step back.  Select the best tool for the job.
  • #10: So here&apos;s my attempt at a solution.  It&apos;s worked well for us.  I hope it&apos;ll work well for you.
  • #14: Everything that the Game Object represents can be broken-down into small chunks Each component represents a data transformation Ultimately, that&apos;s all the game is doing e.g. state machine + states e.g. model animation physics ai/logic sensing send/receive messaging causing damage
  • #15: So now we&apos;ll talk about my solution which I call the Dynamic Component System. First we&apos;ll talk at a high level about what is the system
  • #18: Not in the “adults only” sense. It’s been exercised.
  • #19: Side-by-side implementation Not necessary to refactor existing code Game objects in the traditional (or &quot;legacy&quot;) monolithic model can coexist and interoperate with components The solution is general - doesn&apos;t require a particular game architecture. Some environment-specific implementation details
  • #20: sorry if you were looking for tips on those things if you&apos;re interested in my thoughts on those subjects, please contact me afterward
  • #21: Now we&apos;ll discuss features of the system, a.k.a. why I think it&apos;s a good solution.
  • #23: Components Originally called Aspects from AOP Derived from base Component class 12 bytes of administrative data &quot;Payload&quot; can be detached &amp; treated as POD for processing in separate memory spaces Allocated from pools One pool per concrete type Homogeneous type instances per pool Each pool is indexed with a &quot;partition&quot; value separating free from allocated instances Called the &quot;Roster&quot;
  • #24: High-performance All operations, except for &quot;search&quot;, are small constant-time Allocate/free Resolve handle Get type Type implements (derived from) No instance copying manipulations are done on the Roster rather than the instance pool
  • #25: High-performance Updates are performed per-type (per-pool) Cache friendly Designed to encourage &amp; simplify async update e.g. on SPU Roster contains contiguous list of pool indices of allocated instances Roster up to partition is DMA list
  • #26: High-performance: References between components normally handled by holding/resolving handles
  • #27: Dynamic: Runtime composition of game objects Objects can substantially alter any aspect without carrying around any &quot;baggage&quot; from other states Recommended idiom: component is allocated IFF actively in use Pool sizes need only accommodate max concurrent allocations
  • #28: Dynamic: Results: High-frequency alloc() &amp; free() Small constant-time operations: alloc(): test for availability make handle from index &amp; generation increment roster partition call Init on allocated component
  • #29: Dynamic Results: High-frequency alloc() &amp; free() Small constant-time operations: free(): call Deinit swap index in roster with partition-adjacent index decrement partition increment generation So let&apos;s take an example to put some of these pieces together. We&apos;ll look at an example of freeing a dynamic component instance.
  • #30: Here&apos;s the prototype for DynamicComponent::Free().  It takes... So here&apos;s an example. We have a pool of instances of some given component type. We have a roster, which is an array of indices into the instance pool.  (Note that all of the instances in the pool are of the same type, so they are of equal size.  So the value at a roster index is itself just an index into the pool. You can see that we have a partition value, which separates roster indices representing allocated vs. free instances.
  • #31: Alright.  Now we&apos;re going to free the component represented by the 3rd roster element, which is currently index 3 in the pool.
  • #32: So what we&apos;ll do is swap the 3rd and 4th roster elements.
  • #33: Now we&apos;re freeing the 4th roster element, which represents the 3rd instance in the pool. Since we swapped the roster entry for the element to be freed into the partition-adjacent roster entry, all we have to do to free that instance is...
  • #34: ... decrement the partition. And voila, we&apos;ve free&apos;d a component instance with a few very small constant-time operations, and we didn&apos;t touch the instance data, only indices.
  • #35: System Doesn&apos;t need to completely replace a standard game object model Can completely replace standard game object model Other systems host components Conversation Script Events Shots No game object
  • #36: At a high level, I have three sections to this discussion So now we&apos;re digging into implementation details of the system APIs always a good place to start
  • #49: Get familiar with GetComponentsIndexed()
  • #53: IFF if and only if
  • #55: At a high level, I have three sections to this discussion First, we&apos;ll talk about our purpose here. We&apos;ll discuss the problem we&apos;re trying to solve, and my approach to a solution Second, we&apos;ll talk about details of my solution, which I call the Dynamic Component System. We&apos;ll discuss features of the system, and why it&apos;s a good solution And third, we&apos;ll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
  • #56: x Script Events are Components Possibly related to a Game Object, but Hosted by the Script Event System Allocated on-demand from Lua scripts When specified conditions are met, callback to script Two modes of testing for satisfaction: Some event types are updated automatically by the Dynamic Component System, and poll their conditions Other event types are notified of occasions during gameplay that may cause them to become satisfied
  • #58: Types are registered through the DynamicComponent::TypeRegistrar. The registrar is responsible for keeping track of the types registered with the system, Their base classes for testing which types implement which interfaces And during which update stages each type wants to be updated by the DCS
  • #59: e.g. Say the ScriptEventSystem just has a base type and two concrete event types. The base class is a component type named ScriptEvent.  We&apos;ll register two component type that are subclass of ScriptEvent To illustrate type registration, one will be notified, and one will be an event that updates both on PPU and asynchronously, e.g. on an SPU.  So we&apos;ll use LocationEvent for example. Upon system initialization, it registers both types LocationEvents update on the SPU during PreUpdate to poll various conditions for satisfaction.  It&apos;ll stash the results  back in the component LocationEvents also update on the PPU during PostUpdate for an opportunity to invoke script callbacks if they&apos;re satisfied Note, for even better performance, polling components don&apos;t need to update on PPU at all.  If SPU job determines that an event is satisfied, it can add the component to a shared &quot;invoke list&quot; to be processed after all ScriptEvents are updated. That way, only satisfied events will touch the PPU on any given frame.
  • #60: At a high level, I have three sections to this discussion First, we&apos;ll talk about our purpose here. We&apos;ll discuss the problem we&apos;re trying to solve, and my approach to a solution Second, we&apos;ll talk about details of my solution, which I call the Dynamic Component System. We&apos;ll discuss features of the system, and why it&apos;s a good solution And third, we&apos;ll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
  • #61: NavComponents are hosted by Game Objects (usually Bots) to query the navigation database (mesh + dynamic obstructors) Updated by the Navigation system, not automatically by the Dynamic Component System For navigation-specific load balancing Interesting initialization idiom
  • #62: WTF is a prius? In Dynamic Component parlance, a prius is, &quot;A lightweight vehicle for transporting initialization data.&quot; Opportunity to pass runtime or design-time data to a component instance. Pirus is simply passed to the initialization method of a component instance upon allocation. But is that safe!?! Component must cast to an assumed type!
  • #63: WTF is a prius? In Dynamic Component parlance, a prius is, &quot;A lightweight vehicle for transporting initialization data.&quot; Opportunity to pass runtime or design-time data to a component instance. Pirus is simply passed to the initialization method of a component instance upon allocation. But is that safe!?! Component must cast to an assumed type!
  • #64: Interesting initialization idiom A NavQuery is the Prius for a NavComponent NavQuery::Submit() allocates a NavComponent, and passes itself as the prius.
  • #65: Obviously highly simplified, but meant to convey the point that that a Nav::Query is a prius, whose Submit() method returns the result of DynamicComponent::Allocate(),passing itself as void* prius.
  • #66: At a high level, I have three sections to this discussion First, we&apos;ll talk about our purpose here. We&apos;ll discuss the problem we&apos;re trying to solve, and my approach to a solution Second, we&apos;ll talk about details of my solution, which I call the Dynamic Component System. We&apos;ll discuss features of the system, and why it&apos;s a good solution And third, we&apos;ll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
  • #67: x Hosted by Game Object that fired the Shot Completely replace the Projectile type of GameObject Two DynamicComponent Type hierarchies: Shot represents a state machine Don&apos;t update They are notified of events by their current ShotAction(s) ShotActions represent the states of a Shot Shared among different Shot types Automatically &amp; asynchronously updated by the Dynamic Component System
  • #68: The ShotMoveForward component type has different declarations on the PPU and on an SPU On the PPU, it is a polymorphic type, derived from ShotAction On the SPU, however, it is a POD type This allows us to operate on instances in an object-oriented way on the PPU, without a need to fix-up vtables in a different address space Note that m_location is the first member of ShotMoveForward on SPU, whereas m_next_location is a member of the base class ShotAction on the PPU.
  • #69: &quot;Sentinel&quot; data member identifies start of SPU instance This is achieved by placing a &quot;sentinel&quot; in the base class declaration identifying where an instance of the class begins when being DMA&apos;d to an SPU. The sentinel is a zero-sized array member 
  • #70: What we&apos;ve discussed First, we talked about our purpose here. We discussed the problem we wre trying to solve, and my approach to a solution Second, we talked about details of my solution, which I call the Dynamic Component System. We discussed features of the system, and why it&apos;s a good solution And third, we dug into implementation details of the system, Using a few systems of dynamic components for illustration purposes
  • #71: What we&apos;ve discussed First, we talked about our purpose here. We discussed the problem we wre trying to solve, and my approach to a solution Second, we talked about details of my solution, which I call the Dynamic Component System. We discussed features of the system, and why it&apos;s a good solution And third, we dug into implementation details of the system, Using a few systems of dynamic components for illustration purposes
  • #72: What we&apos;ve discussed First, we talked about our purpose here. We discussed the problem we wre trying to solve, and my approach to a solution Second, we talked about details of my solution, which I call the Dynamic Component System. We discussed features of the system, and why it&apos;s a good solution And third, we dug into implementation details of the system, Using a few systems of dynamic components for illustration purposes
  • #73: Closing thoughts. Tricky aspect: components that share data or otherwise communicate 2 options: Select one to own the data, other references through owner by resolving handle E.g. ShotActions call into Shot to notify of events Scatter-gather idiom PU update stages gather inputs for &amp; scatter outputs from SPU processes Involves copying Better for async processing