Optimization in VR

Rushil Reddy

VR utlizies 2 cameras which means that you need to account for double the processing power. It also requires a higher than normal frame rate, goggles are very high resolution, and latency + fps drop causes glitching.

Frame Rate:

  • Draw calls come from CPU limit
  • Texture memory usage causes GPU fill rate problem
  • Polycount should not exceed 500k-1 million for VR
  • Gear VR budget should be 100k triangles
  • Batching(Enabled by Default): Takes all the verts and meshes and combines them into single meshes

    Static vs Dynamic Batching: Turning floors, walls, etc into static objects will net a huge performance gain. Static batching is better in almost every case.

    Dynamic Batching: groups objects with the same material and less than 900 vertices

    Texture atlasing to make one single material that many objects can share(by using UV coordinates). Asset store has tools for this. Objects can not be batched if they use + and -scale to flip their geometry Batching is automatic process, so it's hard to know when it is helping you. You could manually batch to try and gain performance(Use Mesh.CombineMeshes)

    Stats Window(Click Stats, next to mute audio and gizmos): Look at Tris and FPS, and how many Batches/saved by Batching Every Shadow costs render time, so turn off on some objects or use baked lighting to help

    Window> Frame Debugger

    Shows what happens on drawing every object in your current frame

    Profiler gives a more detailed look. Window> Profiler

    You can see CPU, green is rendering time, blue is scripts(so if you see a blue spike you know a script is hogging resources. You can click on the spike to see the call stack. And you can see what percentage of resources everything took

    Unity Terrain: Beautiful, expressive, and very expensive to render. Consider using Low Poly terrain or custom instead

    Mip Mapping: Automatically creates low res textures for things far away or small things. So you should turn this on for every texture(Unity will create a few different sizes for optimal usage). Texture Properties> Generate MipMapping

    LOD Groups(Level of Detail): Unity has LOD groups. You can use different models for different levels of detail. These models can be switched out depending on hardware or for objects are far away. So this works for gear, vive, etc. You can change this by build setting and stuff

    Distance Culling: You can make objects disappear at far distances. You can use special layers and the Camera.layerCullDistances function. This makes objects disappear if they are past the threshold distance from the camera. So grass outside of 5 meters

    Lights: Try to use one light per object Don’t use lightmode auto, explicitly set to be important or not important instead Vertex Lighting is cheap, pixel lighting is expensive

    Shadows: High quality ones are expensive, use low quality if possible. Shadow casters increase vert count, turn them off on objects that you don’t need shadows for. Eg: ground doesn’t need shadow

    Baked Lightmaps: Baked light maps can give you beautiful lighting- but only on static geometry You need to bake the map every time you move something A lightmap is a texture of all the lighting, it cannot change but is cheap to render It is expensive in video memory but still good Trading Video Memory for CPU’

    Overdraw: Overdraw is the process of rendering multiple objects on top of each other. Usually because of transparent shaders. Unity has a special tool to see overdraw. Common on mobile with UI. Or if you have a building with a wall and behind that wall there's a ton of buildings and objects. Unity will try to draw them and having to z-sort them will cause lots of overdraw

    Occlusion Culling: Unity Pro feature. Involves not drawing things outside of sight ranges. Solves Overdraw problems

    Code Tips

  • Cache references to GetComponent<> calls. Don’t use it in Update, save it in a variable and call it in Start.
  • Don’t use FindObjectbyName, Type or anything similar.
  • Don’t use SendMessage or BroadcastMessage
  • Use Generics, and don’t use LINQ. (Language Integrated Query)
  • Raycasts and Distance checks are super cheap. Use them liberally