Download presentation
Presentation is loading. Please wait.
Published byZoe Austin Modified over 6 years ago
1
Lessons learnt from making a hit mobile game with Unity 3D
David Jefferies, Technical Director PaperSeven Ltd
2
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 Games programmer since 1995 Starting with Psgynosis, then Rare then joined Climax in 2003 Was technical director of MotoGP’06, MotoGP’07 and Split/Second
3
A Bit Of History S/S engine was very large but also very efficient
Rendering was a big part of the game. Used 84 renderer targets to make up the final image
4
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 Great games are made by great developers not engines. Engines are tools for the developers to express themselves
5
2010 - 2011 Unity was widely seen as a capable prototyping tool
Definitely not a commercial game engine
6
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. You can’t google problems with your internal code!
7
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 We got the opportunity to develop the game for the Channel4 hit show Not the traditional demographic for game development This made it an exciting proposition to write something for a group of people (female 17-28) that were underserved in the game space Handy that Alice was closer to the target group than most game developers
8
Made In Chelsea Game
9
Made In Chelsea Game
10
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 We wrote exclusively in C# although some plugins were written in Javascript (mistake, difficult to debug, can’t use .Net?) We used Prime31 plugins for most native code - IAPS, Twitter and Facebook authentication Programmers used a mixture of MonoDevelop and .Net (well I used .Net) We had a MacMini server build machine that spat out iOS, Facebook and eventually Android builds Mainly developed on PC except for the iOS specific bits which were kept to a minimum 138MB download ended up as 231MB on disk (this is too big by the way) Teamcity running on a MacMini Server Build scripts call a static function to build based on config Build number written to disk and read during that step Archive constructed / then IPA / then uploaded to Testflight Signed with Enterprise profile
11
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 Not going to tell you what’s right or wrong There are many ways of doing things in Unity, most of them are right for some application or other This is how we do it
12
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 The garbage collector will bite you
13
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 I’d like to stop the game if allocations happen, they’re almost always avoidable if the programmer is aware of them Heap safe dictionary is our own class that stores a list of the keys alongside the dictionary which means you can iterate through the keys without having to iterate through the dictionary. This avoids the ienumerator allocation. Physics.Raycast sometimes allocates memory. No way round this unfortunately
14
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 Even transform.position is a native call so 3X speedup on native calls is a big win
15
Exceptions void 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);
16
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
18
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
19
Scenes & Prefabs
20
Custom Setup Steps Awake Load AssetBundles Load Prefabs
HandleInitFirstTime SetupDependencies HandleInit Update
21
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
22
Code Structure public 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); }
23
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
24
Code Structure Listener pattern Reduces dependencies between modules
Uses the dictionary of objects to connect listeners and distributors
25
Code Structure public 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); }
27
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
28
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
29
Source Control Internal Git repository hosted on our network
Everyone in the studio uses the Git client Problems with empty directories / meta files
30
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
31
Auto Build We use Mind Candy’s Teamcity Unity3D runner
iOS Build is fiddly Write build number Build Project Build Xcode Archive Build IPA Upload to TestFlight Lots of messing around with Provisioning Profiles
32
Performance Scaled some features depending on device
Fast but no Exceptions No memory allocations Do all possible calculations at build time i.e. less characters on iPhone4
33
That’s It Any Questions
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.