Component Based Game Design

Published on June 2016 | Categories: Documents | Downloads: 48 | Comments: 0 | Views: 286
of 34
Download PDF   Embed   Report

Component based game design

Comments

Content


Theory and Practice of Game
Object Component
Architecture
Marcin Chady
Radical 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 Model
CCharacter
+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()
*
*
Alex
PhysicsBehaviour
TouchBehaviour
CharacterIntentionBehaviour
MotionTreeBehaviour
CollisionActionBehaviour
PuppetBehaviour
CharacterMotionBehaviour
MotionStateBehaviour
RagdollBehaviour
CharacterSolverBehaviour
HealthBehaviour
RenderBehaviour
SensesInfoBehaviour
HitReactionBehaviour
GrabSelectionBehaviour
GrabbableBehaviour

TargetableBehaviour
AudioEmitterBehaviour
FightVariablesBehaviour

ThreatReceiverBehaviour


Helicopter
PhysicsBehaviour
TouchBehaviour
CharacterIntentionBehaviour
MotionTreeBehaviour
CollisionActionBehaviour
PuppetBehaviour



CharacterSolverBehaviour
HealthBehaviour
RenderBehaviour

HitReactionBehaviour

GrabbableBehaviour
GrabBehavior
TargetableBehaviour
AudioEmitterBehaviour
FightVariablesBehaviour
EmotionalStateBehaviour
ThreatReceiverBehaviour
FEDisplayBehaviour

Pedestrian(HLOD)
PhysicsBehaviour

CharacterIntentionBehaviour
MotionTreeBehaviour

PuppetBehaviour




HealthBehaviour
RenderBehaviour



GrabbableBehaviour
GrabBehaviour
TargetableBehaviour
AudioEmitterBehaviour

EmotionalStateBehaviour

FEDisplayBehaviour
CharacterPedBehaviour
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 AttachableBehaviour
then 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 behaviours
b.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 Attributes
in [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
N
u
m
b
e
r

o
f

u
n
i
q
u
e

t
y
p
e
s
Behaviour Usage
0.00%
10.00%
20.00%
30.00%
40.00%
50.00%
60.00%
70.00%
80.00%
R
e
n
d
e
r
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
H
i
t
R
e
a
c
t
i
o
n
B
e
h
a
v
i
o
u
r
G
r
a
b
b
a
b
l
e
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
H
e
a
l
t
h
B
e
h
a
v
i
o
u
r
C
h
a
r
a
c
t
e
r
I
n
t
e
n
t
i
o
n
B
e
h
a
v
i
o
u
r
T
a
r
g
e
t
S
e
l
e
c
t
i
o
n
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
T
h
r
e
a
t
R
e
c
e
i
v
e
r
B
e
h
a
v
i
o
u
r
C
h
a
r
a
c
t
e
r
S
o
l
v
e
r
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
S
h
o
u
l
d
e
r
C
o
n
F
i
x
u
p
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
S
c
a
r
y
M
o
n
s
t
e
r
B
e
h
a
v
i
o
u
r
W
a
l
k
i
n
g
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
H
e
a
l
t
h
S
h
a
d
e
r
B
e
h
a
v
i
o
u
r
L
O
D
R
e
n
d
e
r
B
e
h
a
v
i
o
u
r
e
n
g
i
n
e
:
:
T
r
i
g
g
e
r
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
A
I
F
l
y
i
n
g
P
a
t
r
o
l
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
H
e
l
i
c
o
p
t
e
r
M
o
v
e
m
e
n
t
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
T
a
n
k
I
n
t
e
n
t
i
o
n
B
e
h
a
v
i
o
u
r
T
a
n
k
A
i
m
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
P
o
i
s
o
n
R
e
a
c
t
i
o
n
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
V
e
h
i
c
l
e
B
e
h
a
v
i
o
u
r
A
m
b
i
e
n
t
p
r
o
t
o
:
:
A
u
t
o
T
a
r
g
e
t
i
n
g
B
e
h
a
v
i
o
u
r
T
a
g
B
e
h
a
v
i
o
u
r
e
n
g
i
n
e
:
:
R
a
g
d
o
l
l
L
O
D
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
D
e
c
a
l
B
e
h
a
v
i
o
u
r
e
n
g
i
n
e
:
:
A
d
v
e
r
t
i
s
e
m
e
n
t
B
e
h
a
v
i
o
u
r
e
n
g
i
n
e
:
:
N
I
S
P
l
a
y
e
r
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
L
i
g
h
t
D
e
c
a
l
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
M
i
s
s
i
l
e
J
B
e
h
a
v
i
o
u
r
T
h
r
e
a
t
B
a
l
l
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
Z
o
n
e
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
B
l
o
b
S
h
a
d
o
w
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
G
r
o
u
n
d
S
p
i
k
e
B
e
h
a
v
i
o
u
r
e
n
g
i
n
e
:
:
L
i
g
h
t
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
T
r
a
n
s
f
o
r
m
a
t
i
o
n
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
I
n
f
e
c
t
e
d
P
e
d
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
D
i
s
t
r
i
c
t
B
e
h
a
v
i
o
u
r
p
r
o
t
o
:
:
S
t
a
y
O
n
N
a
v
m
e
s
h
B
e
h
a
v
i
o
u
r
Implicit “Class Hierarchy”
Implicit “Class Hierarchy”
Summary
 Designs change
 Class hierarchies don’t like change
 Components do, but not without
some sacrifices
Questions

Sponsor Documents

Or use your account on DocShare.tips

Hide

Forgot your password?

Or register your new account on DocShare.tips

Hide

Lost your password? Please enter your email address. You will receive a link to create a new password.

Back to log-in

Close