380 likes | 510 Views
Building Large Games with Unity3D. Richard Fine, LUUG #4, 2011-August-22. Hello. Is it me you’re looking for? Is it you I’m looking for?. Large Games. Large worlds Large polygon counts Large “Assets” folder Large codebase. You’ve got to get efficient.
E N D
Building Large Games with Unity3D • Richard Fine, LUUG #4, 2011-August-22
Hello • Is it me you’re looking for? • Is it you I’m looking for?
Large Games • Large worlds • Large polygon counts • Large “Assets” folder • Large codebase
You’ve got to get efficient • Working with large worlds requires partitioning into scenes • Working with large polygon counts requires efficient art and culling • Working with large Asset folders requires editor automation • Working with large codebases requires structure, modularity, and fluidity
Splitting your world over multiple scenesUnderstanding Scene Files • While the game is running, it’s all about the Hierarchy - the scene graph • The GameObjects in the hierarchy are what is present and active in the game • Both dynamic objects (player, enemies, pickups) and static objects (environment/backdrop) live in it • A Scene file is like a freeze-dried Hierarchy - saves your GameObjects, their components, and their components’ public fields • (the clue is in the name, really)
Splitting your world over multiple scenesUsing Multiple Scene Files • Large games would put 10000s of objects into the hierarchy • (that is too many objects in the hierarchy!) • So we split the hierarchy up - put different groups of objects into different scene files • Load scene files as and when we need them - either add them to what’s already in the hierarchy, or throw all the old objects away • Unity only lets us edit one scene file at a time, but prefabs can help get around this • Each scene file that you want to ship must be added to the build - then you can access it either by name or by number • Not all scenes need to be in the build. Very useful to make ‘playground’ scenes for working with individual game elements!
Splitting your world over multiple scenesContinuous Worlds • Position objects in each scene correctly relative to other scenes • Establish ‘choke points’ where it would be convenient to load - corridors, airlocks, tunnels, etc • Simplest approach is to use transition volumes: • Place a trigger volume at each choke point; call DontDestroyOnLoad for the volume • Any dynamic objects that enter the volume (player included) get made children of the volume • LoadLevel() then wipes out everything in the old level, but leaves the transition volume and all its children untouched • The new level’s geometry just happens to perfectly match the old level’s geometry, in the vicinity of the transition zone • As objects leave the volume, they stop being children of it
Art OptimisationKnow Your Target • Render budget is part of a bigger picture • Kinda need Pro to see that bigger picture • Statistics window is better than nothing • Design your benchmark configurations • Hardware (GPU, CPU, RAM) • Software (Quality settings) • Target Framerate (60FPS? 30FPS?) • Run experiments! Render some textured polygon soup and see how long it takes.
Art OptimisationA Quick Point About FPS • Once you’ve picked an FPS, convert it to mSPF, and then never look back • Work that takes the same amount of time has a different impact on the FPS at high and low framerates: • An extra 5ms @ 80FPS is a 22FPS drop • An extra 5ms @ 30FPS is a 4FPS drop • Don’t let yourself be misled - use millisecond budgets instead! • 60FPS = 16.6ms/frame; 30FPS = 33.3ms/frame
Makes your game look better Doesn’t make your game look better Art OptimizationTwo Kinds Of Heat
Art OptimizationReducing Overhead • Combine objects into multi-material meshes, instead of using hierarchies • Except if they should move independently • Maybe skip this if the object is large / only bits of it are on-screen at a time • Don’t use more material indices than you have to - put detail into the texture, not different materials • Mark things as ‘static’ if they’ll never move • Choose your shaders carefully - pick them and stick to them • Reuse your materials if you can • ...though you often can’t • Reuse your textures if you can • Try turning on static batching and see if it helps or hurts you
Art OptimisationReducing Payload • Weld your vertices! • Break very large/highpoly objects up, so that the pieces can be culled separately. Don’t just break by position; consider the number of polygons per piece as well. • Remove polygons that the player will never see • Use culling: occlusion (if it works for you) and area-visibility (M2H, RAZOR, etc) • Use a LOD system (and keep your pivots in sensible places) • Use simpler shaders • Target a lower resolution
Art OptimisationProblem? • Some of this advice is contradictory :-) • In the end, it’s all a balancing act • Experiment, experiment, experiment! • Make one change at a time, test it, see if it helped or hurt you, and always try to understand why it did. • Use version control, backups, etc, to make sure you can always rewind if you’ve made things worse
Editor AutomationUnityEditor Kinda Sucks... • No ability to select and edit multiple objects at once • No ability to copy/paste components between game objects • No ability to export scenes back to Max/Maya • No ability to align scene objects to each other • No support for drawing/editing 3D splines • No support for Modifiers/spacewarps (twist, taper, bend, etc) • No autosave
Editor Automation...But That’s OK! • Everything on the previous slide is, or can be, provided by editor extensions • 114 packages in the Asset Store and counting • Editor extensions can manipulate the Hierarchy in exactly the same way as you can at runtime • Editor extensions can add UI elements to Unity using the same UnityGUI system that the runtime uses • They get extra access to modify things like assets, too!
Editor AutomationCustom Inspectors • Replace or extend what Unity usually shows in the Inspector for a given component or asset • Completely control the UI shown. Do things like: • Hide or show fields based on state • Show and edit fields that wouldn’t normally be shown (properties, calculated values) • Add buttons to do useful things • Restrict entered values to a valid range; display the range as a slider • Includes built-in types! • More detail in my recent AltDevBlogADay article
Editor AutomationCustom Assets • You can make your own asset types that sit alongside meshes, textures, etc • Good for ‘pure data’ things, like look-up tables • Better than prefabs because you can’t accidentally drop them into the scene, add extra components, etc • Examples: • Key bindings (multiple presets, or different bindings for different input devices) • Asset tables (e.g. available footstep sounds for each material category) • Pathfinding database • Look into the ScriptableObject class and AssetDatabase.CreateAsset() method
Editor AutomationAsset Processors • Automatically change settings for assets when they’re imported • Easily make the decision based on the asset’s path - e.g. all textures in the ‘Characters’ folder get set to 4096 resolution, all textures in the ‘GUI’ folder get set to the GUI import type, etc • Can save a lot of time over going through assets one-by-one to set anisotropy, resolution, etc • Could also update other objects - e.g. add the asset to a table • Look into the AssetPostprocessor class
Editor AutomationUtilities • Arbitrary code can be added to your project and attached to menu items • Use this for anything you like - custom build steps, exporters, project cleanup, scene verification... • If you need to show UI, use EditorWindow and ScriptableWizard
Working with large codebasesThe Truth, Such As It Is • The people who said you can make games in Unity without programming were lying to you! • Well, maybe that’s a little harsh... • Programming is about describing systems, breaking things down into component parts, and abstract reasoning - it’s not about the code • To describe a system, you have to understand it • Large systems are difficult to understand all in one go, and in game development, they’re a moving target • This all leads to the vital observation...
Visual Studio + C# Working with large codebasesWhat do we do about that? • To change code, you need to understand the code you’re changing: • Keep it readable • Minimise the things you have to remember • Break it down • This has an impact on the tools you use • ‘Visual Programming’ tools tend to suck at changes • MonoDevelop and Javascript just don’t cut it • Resharper is helpful too MonoDevelop + Javascript
Working with large codebasesSource Control • A few points on Source Control: • Use Source Control! It stops you being afraid of making mistakes • Use Source Control! It makes it much easier to experiment with different approaches • Use Source Control! It helps you figure out how the code came to be written the way it is • Even if you’re not able to use it for all of your assets, you can usually still get away with it for scripts - just be careful about moving and renaming files • Personally I use Git; Unity Technologies uses Mercurial internally • I recommend not using Subversion
Working with large codebasesStructuring your components • Try and give each component a single purpose, a single responsibility • It’s OK to have components that don’t do anything on their own! • Strive for a library of simple, single-purpose components, plus a set of ‘glue’ components that sit on top and coordinate them ProximityMine Explosive ProximitySensor AIThreat
Working with large codebasesStructuring your components • Try and give each component a single purpose, a single responsibility • It’s OK to have components that don’t do anything on their own! • Strive for a library of simple, single-purpose components, plus a set of ‘glue’ components that sit on top and coordinate them StealthMine Explosive ProximitySensor AIThreat
Working with large codebasesStructuring your components • Try and give each component a single purpose, a single responsibility • It’s OK to have components that don’t do anything on their own! • Strive for a library of simple, single-purpose components, plus a set of ‘glue’ components that sit on top and coordinate them • This helps isolate bugs, and helps you respond quickly to changes in the gameplay design • If in doubt: What would Unity do? RemoteDetonationMine Explosive ProximitySensor AIThreat
Working with large codebasesKeep things tidy • Part of making a system easy to understand is to hide or remove irrelevancies • Don’t comment out large chunks of code - delete them and let them live on in source control • Delete dead files • Use the [AddComponentMenu] attribute to keep your menus organised • Use folders to make it easy to find scripts when you need them
Working with large codebasesGeneral optimisation tips • Use Invoke/InvokeRepeating/Coroutines that run every few frames instead of Update • Pool objects to avoid framerate spikes • Code expensive algorithms (e.g. pathfinding) to be run over multiple frames • Avoid creating instances of classes during gameplay • Profile to see where you’re spending time and allocating memory. Ideal memory allocated on a regular gameplay frame: zero bytes!
ConclusionSumming Up • Unity’s much like any other game engine, and definitely capable of building large games • You’ve got to be disciplined • You do need someone to play the role of technical artist • Most of the things that help large games will help small games too (you just tend to care less) • I really wanted to show you guys the game I’m working on, but alas, it’s not quite ready yet...
ConclusionThe End • Get in touch: • Email: rfine@tbrf.net • Forums and Unity IRC: Superpig • Check out AltDevBlogADay: http://www.altdevblogaday.com/ • I’m probably not available to come write lots of code for you, but if you need a consultant to spend an afternoon figuring out why your game is running at 5FPS, I might be able to fit you in :-) • Questions?