PPTX

Report
Data Driven Development
The Technology Behind Live-Ops
About Me
Daniel Menard
Co-founder and CEO
First Spin Out
Products and Services
Products
Services
• Power Based
• Stamina Based
• Short Burst + Long Tail
• Survival + Build Up
• Qualitative
• Quantitative
• Reviews
• React to Players
Commit Graphs
Game
Launch
Commit Graphs
Game
Launch
Effects on Tech
• Code Quality
• Analytics
• Ongoing Production
Code Quality
• Now a major concern
• Must be able to add and remove features easily
• Maintenance dwarfs production
Analytics
• Key metrics and balancing
• Log everything
• Free solutions available
• Prioritize analysis capabilities
Analytics
• Real-Time Data
• Time Lagged Data
• No Data
• Wrong Data
Ongoing Production
• Only require designers to add content
• Good tools
• Configuration data
• Changes informed by analytics
• Regular Patches
• Regular QA
• Submit to App Stores
Tightening the Loop
Adjust
Deliver
7 day review
1-30 days
Analyse
Gather
Data Driven Development
• Decouple data from logic code
• Create a data model for your game
• Game becomes it’s own “runtime” for your data
• Configuration files
Why should you care
• Data can be made accessible to all
• Better code
• Flat class hierarchy
• Objects become containers for data
Class Separation
Designer Data
Levels
Player Data
Runtime Data
Balance Settings
Progression
Item Definitions
Inventory
Health
Achievements
Score
High Scores
Combo Counter
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
1
Trigger
- Key
*
Shop Group
- Key
- Name
- Items
1
Shop Item
- Key
- Name
* - Price
- Icon
- Requirements
- Costs
- Trigger
- Effects
* Requirement
- Text
- LUA Function
*
*
Cost
- Text
- LUA Function
- Mutator
*
* Effect
- Text
- LUA Function
Spectrum
Entirely
Hardcoded
Configuration
Files
Domain
Specific
Language
Scripted
Bindings
Virtual
Machine
Over-Engineering
• Be pragmatic
• Balance customizability with schedule
• Don’t reinvent the wheel, use scripting languages
Scripting Language
• 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
LUA Binding
• Tolua++
• Code generation from headers
• Create regular C++ class
• Make accessible to LUA
Example
enemiesData = CCDictionary:create()
-- BOOMER
data = 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
end
return neighbourhood;
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
},
…
}
Player Data
• Player data depends on designer data
• Designer data is expected to change
• Isolate them from each other
• Database-style keys
Downloader
• 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
Considerations
• Restrictions on downloading executable code
• No DLLs
• Scripts a gray zone
• Bandwidth costs
• No longer covered by the store
Requirements
• Ability to segment content by
• Platform
• Device capabilities
• Test group
• Security
• Data Consistency
Our implementation
• Simple HTTP Client
• JSON Manifest File
• Package files
• Cryptographic Signatures
Manifest File
{
"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…"
}
]
}
Signatures
• SHA-1 Hash, signed with private key
• Public key in game memory
• Ensures data consistency
• Ensures data is yours
A/B Testing
50%
2A
1
50%
2B
3
A/B Testing
• 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
Save File Transformation
• Have a way to update someone’s save file
• Format may change
• Designer data may change
• Do not risk data loss
• Unit Testing
• QA
References
• http://www.slideshare.net/KostasAnagnostou/datadriven-game-development
• http://www.igda.org/montreal/vid_liveops
Thank You!
www.doublestalliongames.com
[email protected]
@dblstallion

similar documents