Lessons learnt from making a hit mobile game with Unity 3D

33
Lessons learnt from making a hit mobile game with Unity 3D David Jefferies, Technical Director PaperSeven Ltd

description

Lessons learnt from making a hit mobile game with Unity 3D. David Jefferies, Technical Director PaperSeven Ltd. A Bit Of History. Used Unity to prototype Split/Second 2 The game + engine was large ~2mil lines code Turnaround times were slow - PowerPoint PPT Presentation

Transcript of Lessons learnt from making a hit mobile game with Unity 3D

Page 1: Lessons learnt from making a hit mobile game with Unity 3D

Lessons learnt from making a hit mobile game with Unity 3D

David Jefferies, Technical DirectorPaperSeven Ltd

Page 2: Lessons learnt from making a hit mobile game with Unity 3D

A Bit Of History• Used Unity to prototype Split/Second 2• The game + engine was large ~2mil lines code• Turnaround times were slow• Unity helped the developers test out

gameplay ideas quickly

Page 3: Lessons learnt from making a hit mobile game with Unity 3D

A Bit Of History

Page 4: Lessons learnt from making a hit mobile game with Unity 3D

A Bit Of History• At one point we even considered making S/S 2

with Unity• Unity renderer was about 80% at efficient

rendering models as S/S 2• Replace editor, asset pipeline and game

engine with Unity

Page 5: Lessons learnt from making a hit mobile game with Unity 3D

2010 - 2011• Unity was widely seen as a capable

prototyping tool• Definitely not a commercial game engine

Page 6: Lessons learnt from making a hit mobile game with Unity 3D

Unity• I think the reality is different

– Model Importer– Dependency Checker– Renderer– Extensible Editor– C# code

This is what I want. I don’t want to write these modules again.

Page 7: Lessons learnt from making a hit mobile game with Unity 3D

Made In Chelsea Game• 9 months to develop• 4 coders, 4 artists plus contractors • Producer/GD• iOS and Facebook initially, Android update• Free with IAPs• #2 in the AppStore charts• 19k ratings at 4.5 stars• 10 hours in length if you rushed through• Won ‘Best Game’ in the Broadcast Digital Awards 2014

Page 8: Lessons learnt from making a hit mobile game with Unity 3D

Made In Chelsea Game

Page 9: Lessons learnt from making a hit mobile game with Unity 3D

Made In Chelsea Game

Page 10: Lessons learnt from making a hit mobile game with Unity 3D

How We Made It• Exclusively C#• Used Prime31 plugins for most native code - IAPS, Twitter

and Facebook authentication etc • Coders used a mixture of MonoDevelop and .Net• MacMini server build machine that built iOS, Facebook

and eventually Android • Mainly developed on PC except for the iOS specific bits

which were kept to a minimum

Page 11: Lessons learnt from making a hit mobile game with Unity 3D

Learnings• It’s easy to get something up and running• This is a great strength of Unity• However, not all features scale well from

prototype to full production• It’s this understanding which is vital

Page 12: Lessons learnt from making a hit mobile game with Unity 3D

Memory• Rule [1]– Never write code that allocates while the game is

running– All allocations at load time– Same rules as C++ but it’s trickier with C#– Unity’s memory profiler is your friend

Page 13: Lessons learnt from making a hit mobile game with Unity 3D

Memory• Know the difference between class and struct• We never use foreach loops• Use a heap safe Dictionary • Raycast was only exception• Use object pools. No runtime instantiation

Page 14: Lessons learnt from making a hit mobile game with Unity 3D

Exceptions• Rule [2]– Always use Fast but no Exceptions in production

code– Speeds up managed to native calls by 3X– Managed code exceptions are still thrown– Write the exception to a log file and crash– Send the log file to your metrics server

Page 15: Lessons learnt from making a hit mobile game with Unity 3D

Exceptionsvoid HandleLog(string logString, string stackTrace, LogType type) { string log = DateTime.UtcNow.ToString("HH:mm:ss") + " " + type.ToString() + " :\t" + logString; if (!string.IsNullOrEmpty(stackTrace)) { log = log + "\n\tstackTrace :\n" + stackTrace; } using (StreamWriter file = new StreamWriter(Application.persistentDataPath + "/logs" + "/LogFile_" + logSessionID + ".log", true)) { file.WriteLine(log); } if (type == LogType.Exception) { PlayerPrefs.SetInt(APP_CRASHED_KEY, 1); } }

Page 16: Lessons learnt from making a hit mobile game with Unity 3D

Scenes & Prefabs• Prefabs are a great way of encapsulating code and data• When placed directly in a scene they make it un-

mergeable• If a prefab is edited in a scene and not applied it

becomes unique to that scene• References were forever being lost• Rule [4] No references between different prefabs

Page 17: Lessons learnt from making a hit mobile game with Unity 3D
Page 18: Lessons learnt from making a hit mobile game with Unity 3D

Scenes & Prefabs• Rule [5] Have a scene structure that

determines which prefabs to load & initialise– Load all the prefabs in the level folder– Custom intialisation steps to manage initialisation

dependencies– Inject dependencies into the components– Start game

Page 19: Lessons learnt from making a hit mobile game with Unity 3D

Scenes & Prefabs

Page 20: Lessons learnt from making a hit mobile game with Unity 3D

Custom Setup StepsAwake

Load AssetBundles

Load Prefabs

HandleInitFirstTime

SetupDependencies

HandleInit

Update

Page 21: Lessons learnt from making a hit mobile game with Unity 3D

Code Structure• No Singletons• Loaded prefabs are available as a dictionary to

all classes• Dependency injectors push dependencies into

the components• Injectors are destroyed after being run

Page 22: Lessons learnt from making a hit mobile game with Unity 3D

Code Structurepublic class GameTimeInjector : GameResourcesInjector<GameObject> {

[SerializeField] private string _pauseControllerObject = "PauseEventController";

public override void Inject (){

GameTime _gameTime = GetComponent<GameTime>();PauseEventController pauseController =

GameResources.GetLoadedObject(_pauseControllerObject).GetComponent<PauseEventController>();

pauseController.AddPauseableObjects(_gameTime);}

}

Page 23: Lessons learnt from making a hit mobile game with Unity 3D

Code Structure• Common Library shared between all games• Lives in the Plugins Folder• Enforces the rule that game code cannot exist

in the library• We use a repository within a repository• Warnings as Errors using gmcs.rsp & smcs.rsp

Page 24: Lessons learnt from making a hit mobile game with Unity 3D

Code Structure• Listener pattern• Reduces dependencies between modules• Uses the dictionary of objects to connect

listeners and distributors

Page 25: Lessons learnt from making a hit mobile game with Unity 3D

Code Structurepublic class DriveAutoSaverInjector : GameResourcesInjector<GameObject> { [SerializeField] private string _saveStateDataObject = "StateManager"; [SerializeField] private string _gameStateObject = "Game";

public override void Inject() { AutoSaver autoSaver = gameObject.GetComponent<AutoSaver>(); GameState gamestate = GameResources.GetLoadedObject(_gameStateObject).GetComponent<GameState>(); gamestate.PostEndOfRaceListeners.Add (autoSaver); }}

Page 26: Lessons learnt from making a hit mobile game with Unity 3D
Page 27: Lessons learnt from making a hit mobile game with Unity 3D

Over Air Update• Rule [6] – All prefabs are built as asset bundles– This allows us to update all of the game data over the air– Versions.xml exists on Amazon AWS and serves new

prefabs to the game– Next time the game runs it loads the new downloaded

prefabs rather than the bundles prefabs– Use [SerializeField] attribute for private variables

Page 28: Lessons learnt from making a hit mobile game with Unity 3D

Out Of Memory• Write guard file when app launches• Delete it when app enters the background• If you launch and the file is there then ran out of

memory• Tell user to reset their device• Log with metrics server• Use assembly stripping

Page 29: Lessons learnt from making a hit mobile game with Unity 3D

Source Control• Internal Git repository hosted on our network• Everyone in the studio uses the Git client• Problems with empty directories / meta files

Page 30: Lessons learnt from making a hit mobile game with Unity 3D

Auto Build• Hook into Unity’s build process• Have a config file that defines all the build settings• We use TeamCity• Building iOS more difficult than it should be• Upload to TestFlight / HockeyApp• Signed with Enterprise profile

Page 31: Lessons learnt from making a hit mobile game with Unity 3D

Auto Build• We use Mind Candy’s Teamcity Unity3D runner• https://

github.com/mindcandy/Teamcity-unity3d-build-runner-plugin– iOS Build is fiddly– Write build number– Build Project– Build Xcode Archive– Build IPA– Upload to TestFlight– Lots of messing around with Provisioning Profiles

Page 32: Lessons learnt from making a hit mobile game with Unity 3D

Performance• Scaled some features depending on device• Fast but no Exceptions• No memory allocations• Do all possible calculations at build time

Page 33: Lessons learnt from making a hit mobile game with Unity 3D

That’s It• Any Questions

[email protected]