data driven development the technology behind live-ops

Post on 16-Dec-2015

215 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Data Driven Development

The Technology Behind Live-Ops

About Me

Daniel MenardCo-founder and CEO

First Spin Out

Products

•Power Based

• Short Burst + Long Tail

•Qualitative

•Reviews

Services

• Stamina Based

• Survival + Build Up

•Quantitative

•React to Players

Products and Services

Commit Graphs

Game Launch

Commit GraphsGame

Launch

•Code Quality

•Analytics

•Ongoing Production

Effects on Tech

•Now a major concern

•Must be able to add and remove features easily

•Maintenance dwarfs production

Code Quality

•Key metrics and balancing

• Log everything

• Free solutions available

•Prioritize analysis capabilities

Analytics

•Real-Time Data

• Time Lagged Data

•No Data

•Wrong Data

Analytics

•Only require designers to add content• Good tools• Configuration data

•Changes informed by analytics

•Regular Patches• Regular QA• Submit to App Stores

Ongoing Production

Deliver

GatherAnalyse

Adjust

Tightening the Loop

7 day review

1-30 days

•Decouple data from logic code

•Create a data model for your game

•Game becomes it’s own “runtime” for your data

•Configuration files

Data Driven Development

•Data can be made accessible to all

•Better code

• Flat class hierarchy

•Objects become containers for data

Why should you care

Designer Data

LevelsBalance SettingsItem Definitions

Player Data

ProgressionInventoryAchievementsHigh Scores

Runtime Data

HealthScoreCombo Counter

Class Separation

Anti-Pattern: Configuration Classes

•Classes which extend and only override defaults

•Configuration should be moved to data class and injected

•Create new classes only when consuming different data

Data Model

Shop Item- Key- Name- Price- Icon- Requirements- Costs- Trigger- Effects

Shop Group- Key- Name- Items

Requirement- Text- LUA Function

Effect- Text- LUA Function

Trigger- Key

Cost- Text- LUA Function- Mutator

1

*

1

*

*

*

*

*

*

Spectrum

Virtual Machine

Scripted Bindings

Domain Specific

Language

Configuration Files

Entirely Hardcoded

Over-Engineering

•Be pragmatic

•Balance customizability with schedule

•Don’t reinvent the wheel, use scripting languages

•Pick one and stick with it• LUA, Javascript, Python, many available

•Make sure you can interop easily

•Use it as a configuration language too• JSON, Lua Pickle

Scripting Language

• Tolua++• Code generation from headers

•Create regular C++ class

•Make accessible to LUA

LUA Binding

enemiesData = CCDictionary:create()

-- BOOMERdata = BoomerData:create("Boomer1")data:setWeaknessDamageType(DamageType_All)data:setEnemyType(EnemyType_Boomer)data:setImpactType(ImpactType_Explosion)data:setCanBeThrown(true)data:setIndependent(true)data:setSoundPrefix("Boomer")data:addAnimationFile("boomer_animations")data:addAnimationFile("boomer_explode")enemiesData:setObject(data, data:getKey():getCString())

Example

function parseNeighbourhood(neighbourhoodDefinition)local neighbourhood = NeighbourhoodData:create(neighbourhoodDefinition.key);

neighbourhood:setCollectionMapPosition(neighbourhoodDefinition.collectionMapPosition); neighbourhood:setCollectionTimeMs(neighbourhoodDefinition.collectionTimeMs); neighbourhood:setImagePath(neighbourhoodDefinition.imagePath); neighbourhood:setMapPosition(neighbourhoodDefinition.mapPosition); neighbourhood:setSoundKey(neighbourhoodDefinition.soundKey); neighbourhood:setZOrder(neighbourhoodDefinition.zOrder);

if neighbourhoodDefinition.coinReward ~= nil then neighbourhood:setCoinReward(neighbourhoodDefinition.coinReward); end

if neighbourhoodDefinition.toothReward ~= nil then neighbourhood:setToothReward(neighbourhoodDefinition.toothReward); end

return neighbourhood;end

local levels = CCArray:create();

local neighbourhoodDefinitions = loadFileSafe("Scripts/Data/neighbourhoods.lua", {ccc3=ccc3, ccp=ccp});for key, neighbourhoodDefinition in pairs(neighbourhoodDefinitions) do levels:addObject(parseNeighbourhood(neighbourhoodDefinition));end

Example

return{ { key="Neighbourhood1", collectionMapPosition=ccp(741, 1120), collectionTimeMs=(60 * 60 * 1000), imagePath="Images/UI/Map/map_redlight01.png", mapPosition=ccp(191, 795), soundKey="Env_RedLight", toothReward=1, zOrder=4 }, …}

Example

Player Data

•Player data depends on designer data

•Designer data is expected to change

• Isolate them from each other

•Database-style keys

•Necessary because Apple delivery is slow• 1-3 weeks spent in review• Android is much better

•Necessary to keep binary small• 50-100MB over-the-air limits• Universal apps

Downloader

•Restrictions on downloading executable code• No DLLs• Scripts a gray zone

•Bandwidth costs• No longer covered by the store

Considerations

•Ability to segment content by• Platform• Device capabilities• Test group

• Security

•Data Consistency

Requirements

• Simple HTTP Client

• JSON Manifest File

•Package files

•Cryptographic Signatures

Our implementation

{"manifest_version": 1,"name": "Big Action Mega Fight","version": "2","url": "http://update.dblstallion.com/bamf/manifest.php?{...}" "files": [

{"name": "patch1.dz","url": "

http://update.dblstallion.com/bamf/patch1.dz","signature":

"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvb…"}

]}

Manifest File

• SHA-1 Hash, signed with private key

•Public key in game memory

• Ensures data consistency

• Ensures data is yours

Signatures

A/B Testing

1

2A 2B

3

50% 50%

•Always maintain a control group

•Can test multiple options (not just 2)

•Need a lot of time to determine winner

• Some groups will never merge back

A/B Testing

•Have a way to update someone’s save file

• Format may change

•Designer data may change

•Do not risk data loss• Unit Testing• QA

Save File Transformation

Thank You!

www.doublestalliongames.com

dan@dblstallion.com@dblstallion

top related