1 / 33

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 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

evelia
Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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

  3. A Bit Of History

  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

  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.

  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

  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 • MacMiniserver 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

  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

  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

  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

  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

  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

  17. 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

  18. Scenes & Prefabs

  19. Custom Setup Steps

  20. 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

  21. Code Structure publicclassGameTimeInjector : GameResourcesInjector<GameObject> { [SerializeField] privatestring _pauseControllerObject = "PauseEventController"; publicoverridevoid Inject () { GameTime_gameTime = GetComponent<GameTime>(); PauseEventControllerpauseController = GameResources.GetLoadedObject(_pauseControllerObject).GetComponent<PauseEventController>(); pauseController.AddPauseableObjects(_gameTime); } }

  22. 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

  23. Code Structure • Listener pattern • Reduces dependencies between modules • Uses the dictionary of objects to connect listeners and distributors

  24. Code Structure publicclassDriveAutoSaverInjector : GameResourcesInjector<GameObject> { [SerializeField] privatestring _saveStateDataObject = "StateManager"; [SerializeField] privatestring _gameStateObject = "Game"; publicoverridevoid Inject() { AutoSaverautoSaver = gameObject.GetComponent<AutoSaver>(); GameStategamestate = GameResources.GetLoadedObject(_gameStateObject).GetComponent<GameState>(); gamestate.PostEndOfRaceListeners.Add(autoSaver); } }

  25. 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

  26. 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

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

  28. 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

  29. 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

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

  31. That’s It • Any Questions david@paperseven.com

More Related