Creating Your Building Blocks Modular Component AI Systems Brett Laming, Rockstar Leeds Joel McGinnis, CCP Alex Champandard, AiGameDev.com
Overview 1. Brett Laming Component systems revisited 2. Joel McGinnis Behaviour and Design Patterns 3. Alex Champandard Performance and Multi-threading
Part 1. Brett Laming COMPONENT SYSTEMS REVISITED
Component Systems What are they? No single definition Potentially Smart objects COM Game object / entity architectures Plug-ins Message based, data driven Fairly certain class cOgre : class cMonster is wrong
Background class cThrowingKnife : public cRangedWeapon, public cMeleeWeapon DEEP CLASS
Background class cWeapon : public cDynamicProp class cRangedWeapon : public cWeapon class cBow : public cRangedWeapon class cBallista : public cRangedWeapon, public cStaticProp, !public cDynamicProp DEEP CLASS
Background class cWeapon : public cGameObj { cGameObj* CreateAmmo(); // Reloading not for melee eState mState; eAttackMode mAttackMode; eAmmoType mAmmoType; // Ranged weapons only int mAmmoCount; }; DEEP CLASS FAT CLASS
Background DEEP CLASS FAT CLASS PLUGIN
Background DEEP CLASS FAT CLASS PLUGIN DATA DRIVEN
Damned if you do… Don’t believe it. We get the problems
Component Broad Classification Key Properties Defined I/O Interchangeable
System Organisation Compartmentalization
Reusable A.I. 5 key levels of organisation Output gameplay. Input gameplay world INHERITANCE STRUCTURE Taxonomy World Organisation Component Name Parents – Children Disciplined gameplay Good organisation DATA FLOW PARALLELIZATION Purposeful data A.I. Gameplay Homogenous Batches / Jobs Sensible lifetimes Good reusable A.I. COMPARTMENTALIZATION Data boundaries Smart objects and DLC
Inheritance Object Base Classification Name Classification cHuman • RTTI queries cLiving cDog • Ability to sort by class Name cExterior cGameObj cArea • RTTI factory creation cInterior • Ability to serialise Combined cDrivingSeat cSeat • Data driven approach cGunnerSeat • Shallow hierarchy cVehicle cCar cWeapon cPistol
RTTI Power typedef int RttiType DECLARE_RTTI_TYPE IMPLEMENT_RTTI_META_BEGIN IMPLEMENT_RTTI_META_END RTTI_CLASSIFY_AND_ADD( mpSeat, cSeat, p_obj ); cWeapon *p_wep = DynamicCast<cWeapon*>(p_obj); cRegistry ::Instance().Create( R_STR(“cColt45”) ); virtual void Serialise( cAttributeReader &rdr ); virtual void Serialise( cAttributeWriter &wtr ); rdr << PTR_IS_OWNED( mpSeats ) With a pre compile step, you can make it extremely efficient indeed!
Structure Spatial class cThing { cGameObj RttiType mRTTI; • }; • Reference frame class cGameObj : public cThing { • World transform public: private: Functional cGameObj *mpParent; cGameObj *mpFirstChild; cGameObj *mpNextSibling; • Composition cMat4 mLocalTransform; • Aggregation }; • Dependency tracking • Conflict resolution • Job ordering
Structure & Inheritance cWorld cWorldRegion cWorldRegion cWorldRegion cInterior cInterior cExterior cVehicle cLiving cLiving cCar cDog cHuman cSkeleton cSeat cSeat* cWeapon* cDrivingSeat cGunnerSeat cTurret cLiving* cLiving* cGameObject* cHuman cHuman cWeapon cPistol cBrain cBrain cSensory cSensory
Data Flow Data Flow cWorld • World State A.I cWorldRegion cGameObj Gameplay World State cInterior cBullet Changes to structure cVehicle • Not inside dt! cCar • Upstream Message cSeat cSeat* cWeapon* • Downstream Message cDrivingSeat cGunnerSeat cTurret Changes to properties cLiving* cLiving* cHuman cHuman • Downstream Signalling cBrain cBrain • Upstream Signalling • Spatial Barrier Message cSensory cSensory
Compartmentalization Smart Objects cVehicle cCar Reconstructable by RTTI Near free cSeat cPhysics* cSeat* cWeapon* cDrivingSeat cGunnerSeat Given good structure cLiving* cLiving* External instructions A.I., animation etc… cHuman Carried by signalling cBrain cSensory
Parallelization The ideal… … is still a way off A.I./gameplay still parallelizes! cLiving* cLiving* Even in game graphs! cBrett cJoel Indirection Aliasing cLiving* Candidates cAlex Leaf output animation, navigation, cSensory cSensory component update Leaf input cInterior cInterior sensory info, blackboards, ray tests
All things being good… cWorld cWorldRegion cWorldRegion cWorldRegion cInterior cInterior cExterior cVehicle cLiving cLiving cCar cDog cHuman cSkeleton cSeat cSeat* cWeapon* cDrivingSeat cGunnerSeat cLiving* cLiving* cGameObject* cHuman cHuman cWeapon cPistol cBrain cBrain cSensory cSensory
Design Tricks 1 Remove temptation class cPhysicalProperties { Minimal data public: inline float Volume() const; Per frame stack inline float Mass() const { Minimal lifetime return Volume() * mDensity; } Use new/delete boundary! inline float BoundsRadius() const; Pools inline bool IsCarriable( cAABB grasp, float force ) const; Favour derivation inline bool IsThrowable( float force ) const; No equation contradiction private: No duplicate data cAABB mBoundingBox; float mDensity; }; Potential deep class problem? Generalise
Design Tricks 2 Locality of reference class cProjectile : public cGameObj { Abstraction + composition public: DECLARE_POOL( ... ); Placement new cProjectile() : mpPhysics( &mNullPhysics ) { } Embedded lists void SetGravity( ... ) { mpPhysics->Add( mGravity ); } Pools private: iPhysics *mpPhysics; cGravity mGravity; Minimise NULL checks static cDummyPhysics mNullPhysics; }; Non-virtual pathways Use RTTI filtering Many virtual pointers Package once and carry downstream
Conclusions Gameplay gives us fun buttons to press! Tight game-play Good, reusable A.I. Think Minimal classes Data life time Locality of reference Use Generalisation RTTI Placement new/delete Pools Nothing is really that un-surmountable!
Part 2. Joel McGinnis AI DESIGN PATTERNS
What are the pressures? Resources Cycles Memory Design specificity
CA for AI Flexibility Performance balancing
Word of warning Paradigm not architecture So we’ll be looking at patterns
TAKING IT APART
Pattern (anti) “Where shall we put the data?” “Lets just put it on the AIComponent ” AIComponent “That seems like a bad idea, lets not do it”
So what do you have? Behavior Target Tree manager Pathfinder Perception Tracking Movement controller
What you consume Focal point Targetable object Cover markup Interaction point Trigger volume Granularity is Good!
Component matrix Behavior Targeting Movement Entities Pathfinding Cover Tree system Controller Tree Sniper Component Targeting Target Movement component Tree Heavy Component Targeting Target Movement component Barrel Target Cover Point Terminal Target
PUTTING IT BACK TOGETHER
Substitution Perception Behavior Tree Pathfinder Targeting Animation Standard movement
Substitution Perception Behavior Tree Pathfinder Targeting Animation Big creature Standard movement movement
Substitution What did we gain? Required: Wasn't enough to COM, signaling, ship but... interface, messaging Minimal investment Nice prototype Answered design Leverage hierarchy questions sooner OOP under the CA
Find Via Registration Target Selection Targetable
Find Via Registration Target Selection Targetable Targeting System
Find Via Registration Target Selection Targetable Targeting System
Find Via Registration What did we gain? Required: Reduced search Life-cycle space management Scoping Simplify construction of behavior
Late construction of types Target Selection Targetable
Late construction of types Target Selection Targetable
Late construction of types What did we gain? Required: The ability to Data driven(?) change our minds Light weight Load balancing Try it everywhere Keep it where most effective
Things to keep in mind Simplest affordances – greatest benefit Prefer small and light-weight CA Lots of little components
Part 3. Alex Champandard PERFORMANCE & MULTI-THREADING
You Must Be Wondering… “How do you reconcile this modularity with high performance on all hardware?”
Demo Interlude Example Component Influence Maps Come back at 3:00 for details!
Recommend
More recommend