Project 2: Barrel Bouncer VR Edition

Part 2: Modifications to Your Environment

In this section, you will be modifying your environment to better fit our new scenario and to optimize it for mobile VR performance.

A Note About Scale

In project 1A, we discussed that you should design your scene to scale. It is especially important to revisit that point now that we are in the VR unit, and thus we have copied over the relevant paragraph below, for your reference:

An important thing to consider when completing this portion is making sure that you place the objects in your scene to scale. As we discussed in class, Unity’s default unit is in meters, so thus you should try to think realistically in meters. For example, if you want to place two bushes next to each other, edit their transform’s position to be one meter away from each other. If you have to change their positions to be 100 meters away from each other in order for it to look like they are next to each other, then they are probably way too big anyway and you are probably too far away.

If you did not correctly consider scaling when you initially designed your environment, you will need to go back now and resize everything. If everything is scaled realistically relative to themselves but your environment itself is too big, the easiest way to fix it is to just scale down your Environment GameObject, which will then appropriately scale down all its descendant GameObjects since their transforms are defined relative to the Environment’s. There are a few ways you can determine the best scaling value:

Additionally, you will want to make sure that the floor or ground of your environment is positioned at a y-value of 0, since this will be where the player is standing.

This discussion of realistic scaling and positioning will be important as you modify your environment for the rest of this section as well. For example, you may be able to pick up a ball that is 0.5 meters away from you, but you probably can’t pick up a ball that is 5 meters away from you.

Adding Barrels Into Scene

In this version of the project, you will not be spawning barrels via Raycasting. Rather, they will already be pre-placed within your environment.

For organization, create an empty GameObject centered at origin and name it “Barrels”. All the barrels you create should be children of this GameObject. This GameObject should also be at the root level of the hierarchy; it should not be a child of the Environment since the barrels should not be static (since the barrels are not always stationary as they can be moved and destroyed in the scene). You should also verify that your barrel prefab is not set to static.

Place 10+ instances of your barrels prefabs into your scene accessible to your player. They should be located on the ground and/or on top of other objects in your environment in a realistic way. Make sure to have them in a variety of distances and directions from the player’s initial starting position.

Creating a Bucket of Balls

Instead of instantiating and throwing balls with the left mouse button, the balls will now be pre-placed into the scene and players will be able to pick them up and throw them with the motion controllers. The balls will be in a bucket, which will be placed right in front of the player and will move with the player.

  1. Find a model of a bucket and import it into your project. You may do so using any of the methods described in project 1A (i.e. Asset Store or online sources), as described here.
  2. Place the bucket into the scene as a child GameObject of the OVRCameraRig, somewhere right in front of the player near their waist level so that they can realistically reach into it. Remember that the y-value defines its height above the ground and the z-value defines how far in front of the player it is, both in meters. Additionally, resize the model if necessary.
  3. If you have a script on your ball prefab that destroys the ball 5 seconds after insantiation, comment out that code so that the balls remain in the scene indefinitely. You will handle destroying the ball 5 seconds after its been thrown in a later section.
  4. Place 5+ instances of your ball prefab into your scene as child GameObjects of the Bucket. Once again, the balls should be approximately the size of a tennis ball in order to realistically fit in your hand, so you may need to resize the prefab if necessary if you hadn’t done this correctly in project 1B. Additionally, make sure that the balls are all contained within the bucket and are not overlapping with each other.

The final setup of your bucket of balls may look something like this:

A bucket of balls in the scene

One thing to note is that in its current state, the balls will probably just fall to the ground when the app is run. This is because bucket probably doesn’t have a collider on it. The problem with just adding a mesh collider to the bucket to fix this is that most meshes would have not properly defined its hollow inner part and thus the collider would just be along its outer surface, making it cylindrical. This means your balls would already be inside of this collider, and its Rigidbodies would try to force itself out of the bucket’s collider upon start. There are a few different options on how you could fix that:

Occlusion Culling

Occlusion culling is a performance optimization technique that will only render the GameObjects that you can directly see in your view and ignore everything that you would not be able to see during that frame anyway. In other words, it will not render GameObjects that aren’t in the direction of your camera’s view nor will it render GameObjects that are hidden behind other GameObjects. To learn more about how occlusion culling works, check out this section of the Unity Docs.

Note that occlusion culling can only be performed on static GameObjects, as their positions size are constant and known.

In order to apply occlusion culling to your environment, follow these steps:

  1. In the menu bar, go to Window -> Rendering -> Occlusion Culling.
  2. Click on the Bake button at the bottom of the occlusion window.

Lightmapping

Another optimization that Unity performs to static GameObjects is with lighting: rather than generating all the lighting data in real time during runtime while you play the game, Unity pre-calculates the illumination from the lights and stores this information into a file called a lightmap. This works because static GameObjects will never move, thus it doesn’t make sense to have run-time overhead for determining lighting illumination and shadows on your environment every frame when you can just access the data from a file. To learn more about how lightmapping works, check out this section of the Unity Docs.

Follow the steps below to generate a lightmap:

  1. In the menu bar, go to Window -> Rendering -> Lighting Settings.
  2. In the lighting window, scroll down to the Lightmapping Settings section and change the Lightmap size to the highest value (i.e. 4096). For performance, it is better to have a few large lightmaps, instead of many smaller ones.
  3. Unselect the Auto Generate checkbox at the bottom of the lighting window and then click on the Generate Lighting button. This will create your baked lightmaps.

Note that this subsection could take anywhere from a few minutes to a few hours to complete, depending on the complexity of your environment and the specifications of your machine. It is highly recommended to have your computer do this task overnight if you have a lot going on in your environment.

If you still seem to have trouble trying to get the lighting to bake in a reasonable time, you could try adjusting the following lighting settings:

Previous Section | Go Home | Next Section