Delivered at GDC Canada 2010, this presentation detailed a dynamic component architecture used in the Resistance franchise to represent aspects of entity and systems' behavior. This component system addresses several weaknesses of the traditional game object model for high-performance gameplay, particularly in multi-threaded or multi-processor environments. The system can be layered on top of a traditional game object model, so a codebase can gradually migrate to this new architecture.
Scene Graphs & Component Based Game EnginesBryan Duggan
A presentation I made at the Fermented Poly meetup in Dublin about Scene Graphs & Component Based Game Engines. Lots of examples from my own game engine BGE - where almost everything is a component. Get the code and the course notes here: https://github.com/skooter500/BGE
www.denizoguz.com-For an in company JDK 7 orientation I have prepared a presentation which summaries new features of JDK 7. I would like to make it public for everyone who needs it.
"Reactive Programming with JavaScript" by Giorgio Natili
JavaScript is an asynchronous and almost single-thread language. Learning how to manage its asynchronous nature is perhaps the most important part of becoming an effective JavaScript programmer. Reactive programming tools in JavaScript provide a powerful way of “wrapping” the asynchronous callbacks into a more readable and maintainable code base. In this talk, I'll highlight the pros and cons of different reactive programming approaches and practices by demonstrating how to use Redux and Angular 2.x as the building blocks of a scalable architecture for your web app.
Scene Graphs & Component Based Game EnginesBryan Duggan
A presentation I made at the Fermented Poly meetup in Dublin about Scene Graphs & Component Based Game Engines. Lots of examples from my own game engine BGE - where almost everything is a component. Get the code and the course notes here: https://github.com/skooter500/BGE
www.denizoguz.com-For an in company JDK 7 orientation I have prepared a presentation which summaries new features of JDK 7. I would like to make it public for everyone who needs it.
"Reactive Programming with JavaScript" by Giorgio Natili
JavaScript is an asynchronous and almost single-thread language. Learning how to manage its asynchronous nature is perhaps the most important part of becoming an effective JavaScript programmer. Reactive programming tools in JavaScript provide a powerful way of “wrapping” the asynchronous callbacks into a more readable and maintainable code base. In this talk, I'll highlight the pros and cons of different reactive programming approaches and practices by demonstrating how to use Redux and Angular 2.x as the building blocks of a scalable architecture for your web app.
BugRaptors Test Automation Accelerator helps clients overcome challenges, and speed up the automation of their functional and regression testing. The robust framework provided by the solution enables early automation, which helps develop test scripts during the design and development phases of the software development life cycle (SDLC). BugRaptors Test Automation Accelerator enables end-to-end test automation of applications spanning multiple technologies. It supports multiple test tools such as Selenium IDE, Selenium WebDriver and QTP etc. It allows frequent releases of applications by reducing the maintenance effort without compromising on the quality of testing.
Iterator - a powerful but underappreciated design patternNitin Bhide
Iterator design pattern is described in GoF ‘Design Patterns’ book. It is used at many places (e.g. Sql Cursor is a ‘iterator’), C++ standard template library uses iterators heavily. .Net Linq interfaces are based IEnumerable (i.e. iterator). However, I don’t see projects creating/using ‘custom’ iterator classes. Many problems can be solved ‘elegantly’ by use of customized iterators. This talk is about ‘power of iterators’ and how custom iterators can solve common problems and help create modular/reusable code components.
Key Discussion Points
Typical examples of iterators in common use.
Kind of problems that can be ‘elegantly’ solved with iterators
When to use custom iterators?
How write custom iterators in C++/C#
From webinar I did on TechGig
http://www.techgig.com/expert-speak/Iterator-a-powerful-but-underappreciated-pattern-449
Java has a solid Memory Model, and there are a couple of excellent libraries for concurrency. When you start working with threads however, pitfalls start appearing - especially if the program is supposed to be fast and correct. This session shows proven solutions for some typical problems, showing how to view program code from a concurrency perspective: Which threads share which data, and how? How to reduce the impact of locks? How to avoid them altogether - and when is that worth it?
Core Java Programming Language (JSE) : Chapter X - I/O Fundamentals WebStackAcademy
Java I/O (Input and Output) is used to process the input and produce the output.
Java uses the concept of a stream to make I/O operation fast. The java.io package contains all the classes required for input and output operations.
We can perform file handling in Java by Java I/O API.
GDC 2010 - A Dynamic Component Architecture for High Performance Gameplay - M...Terrance Cohen
This presentation will detail a dynamic component architecture used in the Resistance franchise to represent aspects of entity and systems' behavior. This component system addresses several weaknesses of the traditional game object model for high-performance gameplay, particularly in multi-threaded or multi-processor environments. Dynamic components are allocated and deallocated on-demand from efficient memory pools, and the system provides a convenient framework for running updates in parallel and on different processors such as SPUs. The system can be layered on top of a traditional game object model, so a codebase can gradually migrate to this new architecture. The presentation will discuss motivations and goals of the system as well as implementation details.
0507 057 01 98 * Adana Çukurova Klima Servisleri, Adana Çukurova Klima Servisi, Adana Çukurova Klima Servisleri, Arçelik Klima Servisi Adana Çukurova, Beko Klima Servisi Adana Çukurova, Demirdöküm Klima Servisi Adana Çukurova, Vestel Klima Servisi Adana Çukurova, Aeg Klima Servisi Adana Çukurova, Bosch Klima Servisi Adana Çukurova, Ariston Klima Servisi Adana Çukurova, Samsung Klima Servisi Adana Çukurova, Siemens Klima Servisi Adana Çukurova, Profilo Klima Servisi Adana Çukurova, Fujitsu Klima Servisi Adana Çukurova, Baymak Klima Servisi Adana Çukurova, Sharp Klima Servisi Adana Çukurova, Mitsubishi Klima Servisi Adana Çukurova, Alaska Klima Servisi Adana Çukurova, Aura Klima Servisi Adana Çukurova, Adana Çukurova Klima Servisleri, Alarko Klima Servisi Adana Çukurova
BugRaptors Test Automation Accelerator helps clients overcome challenges, and speed up the automation of their functional and regression testing. The robust framework provided by the solution enables early automation, which helps develop test scripts during the design and development phases of the software development life cycle (SDLC). BugRaptors Test Automation Accelerator enables end-to-end test automation of applications spanning multiple technologies. It supports multiple test tools such as Selenium IDE, Selenium WebDriver and QTP etc. It allows frequent releases of applications by reducing the maintenance effort without compromising on the quality of testing.
Iterator - a powerful but underappreciated design patternNitin Bhide
Iterator design pattern is described in GoF ‘Design Patterns’ book. It is used at many places (e.g. Sql Cursor is a ‘iterator’), C++ standard template library uses iterators heavily. .Net Linq interfaces are based IEnumerable (i.e. iterator). However, I don’t see projects creating/using ‘custom’ iterator classes. Many problems can be solved ‘elegantly’ by use of customized iterators. This talk is about ‘power of iterators’ and how custom iterators can solve common problems and help create modular/reusable code components.
Key Discussion Points
Typical examples of iterators in common use.
Kind of problems that can be ‘elegantly’ solved with iterators
When to use custom iterators?
How write custom iterators in C++/C#
From webinar I did on TechGig
http://www.techgig.com/expert-speak/Iterator-a-powerful-but-underappreciated-pattern-449
Java has a solid Memory Model, and there are a couple of excellent libraries for concurrency. When you start working with threads however, pitfalls start appearing - especially if the program is supposed to be fast and correct. This session shows proven solutions for some typical problems, showing how to view program code from a concurrency perspective: Which threads share which data, and how? How to reduce the impact of locks? How to avoid them altogether - and when is that worth it?
Core Java Programming Language (JSE) : Chapter X - I/O Fundamentals WebStackAcademy
Java I/O (Input and Output) is used to process the input and produce the output.
Java uses the concept of a stream to make I/O operation fast. The java.io package contains all the classes required for input and output operations.
We can perform file handling in Java by Java I/O API.
GDC 2010 - A Dynamic Component Architecture for High Performance Gameplay - M...Terrance Cohen
This presentation will detail a dynamic component architecture used in the Resistance franchise to represent aspects of entity and systems' behavior. This component system addresses several weaknesses of the traditional game object model for high-performance gameplay, particularly in multi-threaded or multi-processor environments. Dynamic components are allocated and deallocated on-demand from efficient memory pools, and the system provides a convenient framework for running updates in parallel and on different processors such as SPUs. The system can be layered on top of a traditional game object model, so a codebase can gradually migrate to this new architecture. The presentation will discuss motivations and goals of the system as well as implementation details.
0507 057 01 98 * Adana Çukurova Klima Servisleri, Adana Çukurova Klima Servisi, Adana Çukurova Klima Servisleri, Arçelik Klima Servisi Adana Çukurova, Beko Klima Servisi Adana Çukurova, Demirdöküm Klima Servisi Adana Çukurova, Vestel Klima Servisi Adana Çukurova, Aeg Klima Servisi Adana Çukurova, Bosch Klima Servisi Adana Çukurova, Ariston Klima Servisi Adana Çukurova, Samsung Klima Servisi Adana Çukurova, Siemens Klima Servisi Adana Çukurova, Profilo Klima Servisi Adana Çukurova, Fujitsu Klima Servisi Adana Çukurova, Baymak Klima Servisi Adana Çukurova, Sharp Klima Servisi Adana Çukurova, Mitsubishi Klima Servisi Adana Çukurova, Alaska Klima Servisi Adana Çukurova, Aura Klima Servisi Adana Çukurova, Adana Çukurova Klima Servisleri, Alarko Klima Servisi Adana Çukurova
Unity - Internals: memory and performanceCodemotion
by Marco Trivellato - In this presentation we will provide in-depth knowledge about the Unity runtime. The first part will focus on memory and how to deal with fragmentation and garbage collection. The second part will cover implementation details and their memory vs cycles tradeoffs in both Unity4 and the upcoming Unity5.
This presentation is about the following points ,
What is synchronization,
Methods to configure synchronization,
Test setting method,
Wait method,
WaitProperty method,
Exist method,
Sync method,
ave time learning on your own. Start Building with React, MongoDB, Express, & Node. The MERN Stack.
Learning a new JavaScript framework is difficult. You can spend weeks learning new concepts. If an online example doesn’t work, you may spend countless hours Googling, searching Stack Overflow and blogs for the solution.
Take the fast track and learn from an experienced Senior Software Engineer and professional instructor!
About this Course
This highly interactive course features a large amount of student labs and hands-on coding. You will be taught how to assemble the complete stack required to build a modern web app using React.js, MongoDB (a NoSQL database) and Express (a framework for web application servers). This course will also cover many other tools that go into building a complete web application: React Router, React-Bootstrap, Redux, Babel, and Webpack.
What You Will Learn
• How to use modern JavaScript features
• Webpack
• Node & Express
• Reading and writing data to a MongoDB database
• Babel
• React
• State Management with Redux
• Mongoose
• And More!
This full day course will give you a hands-on, deep dive into React Native. In this course, you will learn how to build cross-platform mobile applications from scratch using Facebook's React Native.
We Love Performance! How Tic Toc Games Uses ECS in Mobile Puzzle GamesUnity Technologies
Tic Toc Games recently implemented Unity's Entity Component System (ECS) in their mobile puzzle engine, which brought both great performance improvements and faster iteration time. This intermediate-level session will explain why ECS is able to process data much faster, how they increased iteration speed using ECS, and their experience learning and working with Unity's ECS package.
Garth Smith - Tic Toc Games
Ansiblefest 2018 Network automation journey at robloxDamien Garros
In December 2017, Roblox’s network was managed in a traditional way without automation.
To sustained its growth, the team had to deploy 2 datacenters, a global network and multiple point of presence around the world in few months, the only solution to be able to achieve that was to automate everything.
6 months later, the team has made tremendous progress and many aspects of the network lifecycle has been automated from the routers, switches to the load balancers.
Synopsis
This talk is a retrospective of Roblox’s journey into Network automation:
How we got started and how we automated an existing network.
How we organized the project around Github and an DCIM/IPAM solution (netbox),
How Docker helped us to package Ansible and create a consistent environment.
How we managed many roles and variations of our design in single project
How we have automated the provisioning of our F5 Load Balancers.
For each point, we’ll cover what was successful, what was more challenging and what limitations we had to deal with.
This course teaches you the concepts of Angular. You will learn how to utilize Components, Annotations, Views, Event Handlers, Directives and more. In Angular everything is a Component and this course takes a component-centric approach. We will use Components as the main point of discussion and you will learn about other concepts in Angular in the context of Components.
UiPath Test Automation using UiPath Test Suite series, part 3DianaGray10
Welcome to UiPath Test Automation using UiPath Test Suite series part 3. In this session, we will cover desktop automation along with UI automation.
Topics covered:
UI automation Introduction,
UI automation Sample
Desktop automation flow
Pradeep Chinnala, Senior Consultant Automation Developer @WonderBotz and UiPath MVP
Deepak Rai, Automation Practice Lead, Boundaryless Group and UiPath MVP
The Art of the Pitch: WordPress Relationships and SalesLaura Byrne
Clients don’t know what they don’t know. What web solutions are right for them? How does WordPress come into the picture? How do you make sure you understand scope and timeline? What do you do if sometime changes?
All these questions and more will be explored as we talk about matching clients’ needs with what your agency offers without pulling teeth or pulling your hair out. Practical tips, and strategies for successful relationship building that leads to closing the deal.
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...DanBrown980551
Do you want to learn how to model and simulate an electrical network from scratch in under an hour?
Then welcome to this PowSyBl workshop, hosted by Rte, the French Transmission System Operator (TSO)!
During the webinar, you will discover the PowSyBl ecosystem as well as handle and study an electrical network through an interactive Python notebook.
PowSyBl is an open source project hosted by LF Energy, which offers a comprehensive set of features for electrical grid modelling and simulation. Among other advanced features, PowSyBl provides:
- A fully editable and extendable library for grid component modelling;
- Visualization tools to display your network;
- Grid simulation tools, such as power flows, security analyses (with or without remedial actions) and sensitivity analyses;
The framework is mostly written in Java, with a Python binding so that Python developers can access PowSyBl functionalities as well.
What you will learn during the webinar:
- For beginners: discover PowSyBl's functionalities through a quick general presentation and the notebook, without needing any expert coding skills;
- For advanced developers: master the skills to efficiently apply PowSyBl functionalities to your real-world scenarios.
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Albert Hoitingh
In this session I delve into the encryption technology used in Microsoft 365 and Microsoft Purview. Including the concepts of Customer Key and Double Key Encryption.
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Jeffrey Haguewood
Sidekick Solutions uses Bonterra Impact Management (fka Social Solutions Apricot) and automation solutions to integrate data for business workflows.
We believe integration and automation are essential to user experience and the promise of efficient work through technology. Automation is the critical ingredient to realizing that full vision. We develop integration products and services for Bonterra Case Management software to support the deployment of automations for a variety of use cases.
This video focuses on the notifications, alerts, and approval requests using Slack for Bonterra Impact Management. The solutions covered in this webinar can also be deployed for Microsoft Teams.
Interested in deploying notification automations for Bonterra Impact Management? Contact us at sales@sidekicksolutionsllc.com to discuss next steps.
Connector Corner: Automate dynamic content and events by pushing a buttonDianaGray10
Here is something new! In our next Connector Corner webinar, we will demonstrate how you can use a single workflow to:
Create a campaign using Mailchimp with merge tags/fields
Send an interactive Slack channel message (using buttons)
Have the message received by managers and peers along with a test email for review
But there’s more:
In a second workflow supporting the same use case, you’ll see:
Your campaign sent to target colleagues for approval
If the “Approve” button is clicked, a Jira/Zendesk ticket is created for the marketing design team
But—if the “Reject” button is pushed, colleagues will be alerted via Slack message
Join us to learn more about this new, human-in-the-loop capability, brought to you by Integration Service connectors.
And...
Speakers:
Akshay Agnihotri, Product Manager
Charlie Greenberg, Host
Transcript: Selling digital books in 2024: Insights from industry leaders - T...BookNet Canada
The publishing industry has been selling digital audiobooks and ebooks for over a decade and has found its groove. What’s changed? What has stayed the same? Where do we go from here? Join a group of leading sales peers from across the industry for a conversation about the lessons learned since the popularization of digital books, best practices, digital book supply chain management, and more.
Link to video recording: https://bnctechforum.ca/sessions/selling-digital-books-in-2024-insights-from-industry-leaders/
Presented by BookNet Canada on May 28, 2024, with support from the Department of Canadian Heritage.
Neuro-symbolic is not enough, we need neuro-*semantic*Frank van Harmelen
Neuro-symbolic (NeSy) AI is on the rise. However, simply machine learning on just any symbolic structure is not sufficient to really harvest the gains of NeSy. These will only be gained when the symbolic structures have an actual semantics. I give an operational definition of semantics as “predictable inference”.
All of this illustrated with link prediction over knowledge graphs, but the argument is general.
5. A Dynamic Component Architecture
for High Performance Gameplay
Terrance Cohen
Lead Systems Engineer
Insomniac Games
6. A Dynamic Component Architecture
for High Performance Gameplay
• Purpose
• The Dynamic Component System
• Implementation by Example
• Questions (note slide #)
7. A Dynamic Component Architecture
for High Performance Gameplay
• Purpose
o Statement of Problem
o Proposed Solution
• The Dynamic Component System
• Implementation by Example
8. Purpose : Statement of Problem
• Monolithic / deep Game Object hierarchy
o Memory: binds data @ compile time
Allocated throughout lifetime
9. 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
10. 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
11. 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.
12. 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!
13. A Dynamic Component Architecture
for High Performance Gameplay
• Purpose
o Statement of Problem
o Proposed Solution
• The Dynamic Component System
• Implementation by Example
14. Purpose : Proposed Solution
• Construction of Game Object through composition of
components at runtime
15. Purpose : Proposed Solution
• Construction of Game Object through composition of
components at runtime
• Simple!
• Thank you for coming!
16. Purpose : Proposed Solution
• Construction of Game Object through composition of
components at runtime
• Simple!
• Thank you for coming!
o Oh, you want details !?!
17. Purpose : Proposed Solution
• Construction of Game Object through composition of
components at runtime
• Small chunks
• Represent a data transformation
18. A Dynamic Component Architecture
for High Performance Gameplay
• Purpose
• The Dynamic Component System
o Features
• Implementation by Example
19. 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
20. 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.
21. 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.)
22. The Dynamic Component System
• Side-by-side implementation
o Not necessary to refactor existing code
o Coexist with components
• General solution
23. 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
24. A Dynamic Component Architecture
for High Performance Gameplay
• Purpose
• The Dynamic Component System
o Features
• Implementation by Example
26. 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
27. 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
28. 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
29. Dynamic Component System : Features
• Components
• High-performance
o Resolving handle
Small, constant-time operation:
Index into Pool
Compare generation
Return Component*
30. 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
31. 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()
32. 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
38. Dynamic Component System : Features
• Components
• High-performance
• Dynamic
• System
o Not all-or-nothing!
o Examples:
Conversation
Script Events
Shots: no game object
39. 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
40. 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 );
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 );
___________________________________________________________________________________________________
//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 );
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 );
___________________________________________________________________________________________________
//get one component of type that belongs to host
Component* Get ( Type type, HostHandle host_handle, Chain chain );
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 );
___________________________________________________________________________________________________
//get the first Component in host's chain that implements the type interface
Component* GetComponentThatImplements( Type type, 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 );
___________________________________________________________________________________________________
//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 );
45. 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 );
46. 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 );
47. 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 );
48. 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 );
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
//
//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 );
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 );
___________________________________________________________________________________________________
//returns whether component type implements interface
bool TypeImplements ( Type type, Type interface );
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 );
___________________________________________________________________________________________________
//returns the number of components of type that are currently allocated
u32 GetNumAllocated ( Type type );
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 );
___________________________________________________________________________________________________
//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 );
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
//
// 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 );
54. 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 );
55. 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 ( );
56. 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 );
}
57. 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 );
}
58. 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
59. 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
60. Script Events : Type Registration
Notified Updated
• Checkpoint • Location
• Damage • Timer
• Death • Visible
• NumAlive
• Active
• Custom
o Reload
o Zoom
o Grapple
o SeatEnter
61. 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);
}
62. 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
}
63. 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
64. Navigation : Allocation & Initialization
• NavComponents are hosted by Game Objects
• Updated by the Navigation system
65. 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?
66. 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!?
67. 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);
}
68. 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
69. 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
70. 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
71. 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
72. 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;
};
73. A Dynamic Component Architecture
for High Performance Gameplay
• Purpose
• The Dynamic Component System
• Implementation by Example
74. A Dynamic Component Architecture
for High Performance Gameplay
• Purpose
• The Dynamic Component System
• Implementation by Example
• Thank You!
• Questions
75. 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
76. A Dynamic Component Architecture
for High Performance Gameplay
Terrance Cohen
Lead Systems Engineer
Insomniac Games
www.TerranceCohen.com
Twitter: @terrance_cohen
Editor's Notes
Waiting for people to arrive
Waiting for people to arrive
Waiting for people to arrive
Waiting for people to arrive
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
At a high level, I have three sections to this discussion First, we'll talk about, "Why are we here?" Not, "Why are we here on this earth," that's outside the scope of this presentation. I mean, "What do I hope you'll conclude from this." We'll discuss the problem we're trying to solve, and my approach to a solution Second, we'll talk about details of my solution, which I call the Dynamic Component System. We'll discuss features of the system, and why it's a good solution And third, we'll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
First we'll talk about the problem we're trying to solve.
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
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
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's not a good solution to this problem Messy unification of disparate hierarchies
"What we're used to," so easy to overlook flaws Step back. Select the best tool for the job.
So here's my attempt at a solution. It's worked well for us. I hope it'll work well for you.
Everything that the Game Object represents can be broken-down into small chunks Each component represents a data transformation Ultimately, that's all the game is doing e.g. state machine + states e.g. model animation physics ai/logic sensing send/receive messaging causing damage
So now we'll talk about my solution which I call the Dynamic Component System. First we'll talk at a high level about what is the system
Not in the “adults only” sense. It’s been exercised.
Side-by-side implementation Not necessary to refactor existing code Game objects in the traditional (or "legacy") monolithic model can coexist and interoperate with components The solution is general - doesn't require a particular game architecture. Some environment-specific implementation details
sorry if you were looking for tips on those things if you're interested in my thoughts on those subjects, please contact me afterward
Now we'll discuss features of the system, a.k.a. why I think it's a good solution.
Components Originally called Aspects from AOP Derived from base Component class 12 bytes of administrative data "Payload" can be detached & 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 "partition" value separating free from allocated instances Called the "Roster"
High-performance All operations, except for "search", 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
High-performance Updates are performed per-type (per-pool) Cache friendly Designed to encourage & simplify async update e.g. on SPU Roster contains contiguous list of pool indices of allocated instances Roster up to partition is DMA list
High-performance: References between components normally handled by holding/resolving handles
Dynamic: Runtime composition of game objects Objects can substantially alter any aspect without carrying around any "baggage" from other states Recommended idiom: component is allocated IFF actively in use Pool sizes need only accommodate max concurrent allocations
Dynamic: Results: High-frequency alloc() & free() Small constant-time operations: alloc(): test for availability make handle from index & generation increment roster partition call Init on allocated component
Dynamic Results: High-frequency alloc() & free() Small constant-time operations: free(): call Deinit swap index in roster with partition-adjacent index decrement partition increment generation So let's take an example to put some of these pieces together. We'll look at an example of freeing a dynamic component instance.
Here's the prototype for DynamicComponent::Free(). It takes... So here'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.
Alright. Now we're going to free the component represented by the 3rd roster element, which is currently index 3 in the pool.
So what we'll do is swap the 3rd and 4th roster elements.
Now we'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...
... decrement the partition. And voila, we've free'd a component instance with a few very small constant-time operations, and we didn't touch the instance data, only indices.
System Doesn'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
At a high level, I have three sections to this discussion So now we're digging into implementation details of the system APIs always a good place to start
Get familiar with GetComponentsIndexed()
IFF if and only if
At a high level, I have three sections to this discussion First, we'll talk about our purpose here. We'll discuss the problem we're trying to solve, and my approach to a solution Second, we'll talk about details of my solution, which I call the Dynamic Component System. We'll discuss features of the system, and why it's a good solution And third, we'll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
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
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
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'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'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'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're satisfied Note, for even better performance, polling components don'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 "invoke list" to be processed after all ScriptEvents are updated. That way, only satisfied events will touch the PPU on any given frame.
At a high level, I have three sections to this discussion First, we'll talk about our purpose here. We'll discuss the problem we're trying to solve, and my approach to a solution Second, we'll talk about details of my solution, which I call the Dynamic Component System. We'll discuss features of the system, and why it's a good solution And third, we'll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
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
WTF is a prius? In Dynamic Component parlance, a prius is, "A lightweight vehicle for transporting initialization data." 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!
WTF is a prius? In Dynamic Component parlance, a prius is, "A lightweight vehicle for transporting initialization data." 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!
Interesting initialization idiom A NavQuery is the Prius for a NavComponent NavQuery::Submit() allocates a NavComponent, and passes itself as the prius.
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.
At a high level, I have three sections to this discussion First, we'll talk about our purpose here. We'll discuss the problem we're trying to solve, and my approach to a solution Second, we'll talk about details of my solution, which I call the Dynamic Component System. We'll discuss features of the system, and why it's a good solution And third, we'll dig into implementation details of the system, Using a few systems of dynamic components for illustration purposes
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'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 & asynchronously updated by the Dynamic Component System
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.
"Sentinel" data member identifies start of SPU instance This is achieved by placing a "sentinel" in the base class declaration identifying where an instance of the class begins when being DMA'd to an SPU. The sentinel is a zero-sized array member
What we'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's a good solution And third, we dug into implementation details of the system, Using a few systems of dynamic components for illustration purposes
What we'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's a good solution And third, we dug into implementation details of the system, Using a few systems of dynamic components for illustration purposes
What we'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's a good solution And third, we dug into implementation details of the system, Using a few systems of dynamic components for illustration purposes
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 & scatter outputs from SPU processes Involves copying Better for async processing