34

Theory and Practice of Game Object Component Architecture Marcin Chady Radical Entertainment

Embed Size (px)

Citation preview

Theory and Practice of Game Object Component Architecture

Marcin ChadyRadical Entertainment

Outline

Component-Oriented vs Object-Oriented Programming

Radical’s approach Results from [PROTOTYPE]

What are Game Objects?

Anything that has a representation in the game world Characters, props, vehicles, missiles,

cameras, trigger volumes, lights, etc. Need for a standard ontology

Clarity Uniformity Feature, staff and tool mobility Code reuse Maintenance

E.g. use of modularity/inheritance reduces duplication

A Game Object Class Hierarchy

Drawable(renderable model)

Simulated(rigid body model)

Trigger(volume)

GameObject(transform, refcount)

Prop

Adding Stuff

Drawable(renderable model)

Simulated(rigid body model)

Trigger(volume)

GameObject(transform, refcount)

Animated(animation controller)

Animated(animation controller)

Mix-ins Perhaps?

Drawable(renderable model)

Simulated(rigid body model)

Trigger(volume)

GameObject(transform, refcount)

AnimatedMixin(animation controller)

Animated

AnimatedWithPhysics

Observations

Not every set of relationships can be described in a directed acyclic graph

Class hierarchies are hard to change

Functionality drifts upwards Specialisations pay the memory

cost of the functionality in siblings and cousins

Change

You can ignore it You can resist it Or you can embrace it But you cannot stop it

Component-Based Approach Related to, but not the same as

aspect-oriented programming One class, a container for:

attributes (data) behaviours (logic)

Attributes := list of key-value pairs Behaviour := object with

OnUpdate() and OnMessage()

Components vs Hierarchies

Prop

GameObject

GameObject

Attribute<T> Behaviour

* *

Hulk:UD Object ModelCCharacter

+Renderable+Simulation+Intention+Motion+Locomotion+Sequencer+Charge+Effects+Targetting+Throwing+Attachment*+AI+Health+Scenario+Cloud+Variables

+11 diffferent updates()

CSPHulkPropInstance

+Renderable+Simulation+State machine+Targetting+Throwing+Attachment+AI+Health+Collectable

+Update()

0..1

CCow

+Animation+State machine+AI

+Update()

1

CCivilian

+Renderable+Animation+State machine+Simulation+AI+Health+Throwing

+Update()

AmbientManager

+Civilians+Vehicles+Cows

+Update()

*

*

AlexPhysicsBehaviourTouchBehaviourCharacterIntentionBehaviourMotionTreeBehaviourCollisionActionBehaviourPuppetBehaviourCharacterMotionBehaviourMotionStateBehaviourRagdollBehaviourCharacterSolverBehaviourHealthBehaviourRenderBehaviourSensesInfoBehaviourHitReactionBehaviourGrabSelectionBehaviourGrabbableBehaviour

TargetableBehaviourAudioEmitterBehaviourFightVariablesBehaviour

ThreatReceiverBehaviour

HelicopterPhysicsBehaviourTouchBehaviourCharacterIntentionBehaviourMotionTreeBehaviourCollisionActionBehaviourPuppetBehaviour

CharacterSolverBehaviourHealthBehaviourRenderBehaviour

HitReactionBehaviour

GrabbableBehaviourGrabBehaviorTargetableBehaviourAudioEmitterBehaviourFightVariablesBehaviourEmotionalStateBehaviourThreatReceiverBehaviourFEDisplayBehaviour

Pedestrian(HLOD)PhysicsBehaviour

CharacterIntentionBehaviourMotionTreeBehaviour

PuppetBehaviour

HealthBehaviourRenderBehaviour

GrabbableBehaviourGrabBehaviourTargetableBehaviourAudioEmitterBehaviour

EmotionalStateBehaviour

FEDisplayBehaviourCharacterPedBehaviour

Pedestrian(LLOD)

SensesInfoBehaviour

TargetableBehaviour

PedBehaviour

Prototype Game Objects

Data-Driven Creation

Text or binary Loaded from pipeline Load and go Delayed instancing Dedicated tools Data-driven inheritance

TOD_BeginObject GameObject 1 "hotdog_concession"{ behaviours { PhysicsBehaviour 1 { physicsObject "hotdog_concession" } , RenderBehaviour 1 { drawableSource "hotdog_concession" } , HealthBehaviour 1 { health 2.000000 } , GrabbableBehaviour 1 { grabbableClass "2hnd" } }}TOD_EndObject

Advantages

Endowing with new properties is easy Creating new types of entities is easy Behaviours are portable and reusable Code that talks to game objects is type-

agnostic Everything is packaged and designed to

talk to each other In short: you can write generic code

Disadvantages

In short: you have to write generic code Game objects are typeless and opaque Can’t ask, e.g.

if object has AttachableBehaviourthen attach to it

Code has to treat all objects identically

This is wrong!

Messaging

AttachMessage msg(this);

object->OnMessage(&msg);

Dispatched immediately to all interested behaviours (synchronous operation)

Fast, but not as fast as a function call Use for irregular (unscheduled)

processing Collisions, state transitions, event handling

Can be used for returning values

Attribute Access

The game object must be notified if you modify an attribute

Const accessor Read-only access Cacheable

Non-const accessor Permits writing Not cacheable Sends a notification message to the game

object Free access from object’s own

behaviours

An attribute or not an attribute? Attribute if

accessed by more than one behaviour, or

accessed by external code Otherwise a private member of the

behaviour If not sure, make it an attribute

Game Object Update GameObject::OnUpdate(pass, delta)

for b in behavioursb.OnUpdate(pass, delta)

OnUpdate() and OnMessage() are the only two entry points to a behaviour.

HealthBehaviour Example

void HealthBehaviour::OnMessage(Message* m){ switch (m.type) { case APPLY_DAMAGE: Attribute<float>* healthAttr = GetAttribute(HEALTH_KEY); healthAttr->value -= m.damage; if (healthAttr->value < 0.f) mGameObject->SetLogicState(DEAD); break;

case ATTR_UPDATED: if (m.key == HEALTH_KEY) { Attribute<float>* healthAttr = GetAttribute(HEALTH_KEY); if (healthAttr->value < 0.f) mGameObject->SetLogicState(DEAD); } break; }}

Components in Practice

Behaviours and Attributesin [PROTOTYPE]

Adoption

Some coders were resistant: Too complicated

Don’t know what’s going on Too cumbersome

Calling a function is easier than sending a message

Reading a data member is easier than retrieving an attribute

Don’t like typeless objects Ongoing education

Post-Mortem Survey

0

2

4

6

8

10

12

14

Adoption Coding Debugging Maintenance Reuse Performance Overall

Much worse A little worse About the Same A little better Much better

Post-Mortem Comments

Data-driven creation was the biggest win Prototyping is the biggest win once you

have a library of behaviours Modularity of behaviours was the biggest

win Data inheritance was the biggest win Components are nothing new - no

modern game could be built without them

Performance

GameObject::OnUpdate and OnMessage are easy targets For the critic For the optimiser

Existing optimisations: Message masks Update masks Logic state masks Time-slicing Attribute caching Leaving the back door open

Performance Lessons

Best optimisations are algorithmic: Avoid unnecessary messages, e.g.

object->OnMessage(&message1);if (message1.x)object->OnMessage(&message2);

Prefer attributes over messages Avoid unnecessary updates

Better instrumentation Legalise the back door entrance

Future Improvements

Stateless behaviours Submit batches of objects to

stateless behaviours Better suited for parallel architectures

Message queuing

Prototype’s Data Types

1544 game object definitions 145 unique behaviours 335 unique data types

156 unique prop types alone

0

5

10

15

20

25

30

1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47

Number of behaviours

Num

ber

of u

niqu

e ty

pes

Behaviour Usage

0.00%

10.00%

20.00%

30.00%

40.00%

50.00%

60.00%

70.00%

80.00%R

ende

rBeh

avio

ur

prot

o::H

itRea

ctio

nBeh

avio

ur

Gra

bbab

leB

ehav

iour

prot

o::H

ealth

Beh

avio

ur

Cha

ract

erIn

tent

ionB

ehav

iour

Tar

getS

elec

tionB

ehav

iour

prot

o::T

hrea

tRec

eive

rBeh

avio

ur

Cha

ract

erS

olve

rBeh

avio

ur

prot

o::S

houl

derC

onF

ixup

Beh

avio

ur

prot

o::S

cary

Mon

ster

Beh

avio

ur

Wal

king

Beh

avio

ur

prot

o::H

ealth

Sha

derB

ehav

iour

LOD

Ren

derB

ehav

iour

engi

ne::

Tri

gger

Beh

avio

ur

prot

o::A

IFly

ingP

atro

lBeh

avio

ur

prot

o::H

elic

opte

rMov

emen

tBeh

avio

ur

prot

o::T

ankI

nten

tionB

ehav

iour

Tan

kAim

Beh

avio

ur

prot

o::P

oiso

nRea

ctio

nBeh

avio

ur

prot

o::V

ehic

leB

ehav

iour

Am

bien

t

prot

o::A

utoT

arge

tingB

ehav

iour

Tag

Beh

avio

ur

engi

ne::

Rag

dollL

OD

Beh

avio

ur

prot

o::D

ecal

Beh

avio

ur

engi

ne::

Adv

ertis

emen

tBeh

avio

ur

engi

ne::

NIS

Pla

yerB

ehav

iour

prot

o::L

ight

Dec

alB

ehav

iour

prot

o::M

issi

leJB

ehav

iour

Thr

eatB

allB

ehav

iour

prot

o::Z

oneB

ehav

iour

prot

o::B

lobS

hado

wB

ehav

iour

prot

o::G

roun

dSpi

keB

ehav

iour

engi

ne::

Ligh

tBeh

avio

ur

prot

o::T

rans

form

atio

nBeh

avio

ur

prot

o::I

nfec

tedP

edB

ehav

iour

prot

o::D

istr

ictB

ehav

iour

prot

o::S

tayO

nNav

mes

hBeh

avio

ur

Implicit “Class Hierarchy”

Implicit “Class Hierarchy”

Summary

Designs change Class hierarchies don’t like change Components do, but not without

some sacrifices

Questions