Overview
This is the text version of a work in progress guide about how to create your first VRChat World using a Unity-only workflow. I plan to record a video version using this script by the end of the summer. I have decided to upload what I have here in the meantime so I can gather feedback and finalize the script. The text guide will be updated over the coming weeks and pictures will be added as I record the video version.This is a project-based course which will end with each student having a made a unique room and understanding the basics of world creation, such as using Unity and the VRChat SDK, constructing unique geometry with Probuilder, materials and PBR textures, lighting and lightmapping, the asset store and external models and prefabs, World Space UI, Udon, pickupabbles, and Quest compatibility.
Introduction
Have you ever wanted to make your own world but never knew how to start?
Hi, I’m Iconoclass, I’ve created several different types of worlds and with this tutorial series I will show you that you can create your very own too!
This will be a series approachable by everyone, including those who have never touched 3D. It will use a Unity-only workflow; I believe this is the fastest, most iterable, and most beginner friendly approach to world creation.
This will be a comprehensive beginner course that covers everything one should need to know in building a world, including best practices that will lead to higher framerates, lower world sizes and easier iteration.
Introduction to Unity and VRCSDK
Hi! Welcome to the first tutorial in my how to make your first vrchat world series! In this tutorial, you will learn how to install Unity, navigate it, import the VRCSDK and upload a world! Don’t worry, it won’t be a finished world yet, we just need to make sure that everything works properly before we make a huge time investment!
First, you will need to go to the following link to download the latest version of Unity that VRChat uses. You must be using this exact version or it will not work! Install the Unity Hub as it will be useful in managing multiple Unity versions and platforms; this way, we can easily upload to PC and Quest, and can upgrade Unity when VRChat updates the version of Unity it runs on.
As of recording, as listed on the website, download Unity version 2018.4.2f1, and make sure to check the Android box as this will allow us to also upload for Quest.
Once that is installed, open the Unity Hub and click New at the top right. Name your project, select a location, select the 3D template and hit create! Tip: I recommend putting all your VRChat Unity projects in a folder on your larger hard drive if you have multiple, they can get pretty big!
Once all that is finished, Unity will take a bit to set everything up and then it will open! You should now see the default layout of Unity when you first create a project.
The largest and most prominent window is the scene view; this is a 3D view of your Unity scene. You can use the mouse wheel to zoom in and out. You can use the middle mouse button to pan, and if you hold ALT and left click you can pivot. You can look around by holding the right mouse button and moving your mouse. While doing that, you can also navigate the scene by using the WASD keys, as well as E and Q for ascending and descending.
There should be two objects in the default scene. You can see them in the Hierarchy tab, which is on the left side of the screen by default. If you click on the Main Camera, it will highlight in the editor, a 3-axis gizmo will appear on the object in the scene tab, and information will appear in the rightmost tab, the Inspector. The inspector shows all the information of an object, and each collapsable section is called a component. Every object will have a transform component, which denotes its X Y and Z position, rotation and scale. If you edit the value in the Inspector, the object updates in the Scene view, and vice versa.
At the bottom of the screen should be the Project view, which shows all of the game assets in the project, which can be dragged into the scene.
You can rearrange these panels however you want. For the sake of conformity and ease of learning, I will be keeping the default layout for this series unless I explicitly open a new tab required for the course, which I will make clear. If you ever want to reset to the default layout, you can simply click in the top right corner and select Default, or Window>Layouts>Default.
OK, for the rest of this lesson, we will set up a scene to simply test to ensure that it is possible to upload working worlds to VRChat. First, we need to add a ground plane for the player to stand on. To add an object, go to the Hierarchy, right click ( you can also click Create), and select 3D object>Plane. You can press F in the Scene tab to snap to it. By default, there should be a gizmo on it in the center of the object that has 3 arrows; you can change between the gizmos with the keys W, E, R, and T. We want this plane to be in the center of our scene, also called the origin. To do this, make sure the plane is selected, go to the Inspector, and under the Transform component, click the gear, and click reset. This will reset the position and rotation of the object to 0,0,0 and the scale to 1,1,1.
Now, we need to import the VRChat SDK, which is a Unitypackage. To import a package, go to … or simply drag in the package file from the file explorer. After some processing, you will see a popup; this lists all of the assets in the package, and will come up every time you want to import one. By default, everything not already imported into the project will be checked; this is what we want, so just click import.
After the package has been imported you should see there is a new menu in the menu bar called VRC SDK, go to the search bar in the Project view and type “VRCWorld”. Drag it into the Hierarchy and reset it to the world origin if it isn’t there already.
Now, go to VRC SDK>Show Control Panel, and a new window should pop up, which you can dock if you like. Login and then select the build tab. Now select build and test, and check force non VR. VRChat should launch, and if everything goes well then you should spawn in the scene on top of the plane!
I would recommend closing the VRCSDK window when not in use, as it can slow Unity down. If the window is undocked, you can close it by clicking the x at the top right corner, or you can right click on the tab and select close.
That’s it for this lesson, in the next one we will start building our room!
Probuilder (and VRWorldToolkit and CyanEmu)
In this lesson, we will build the geometry of our room!
But first, we should import two packages that will help with our workflow. The first is CyanEmu, and it allows us to test our world by clicking the play button at the top of the screen; that way, we don’t have to launch VRChat every time we want to test, leading to much faster iteration. The second is VRWorldToolkit, which gives us a bunch of tools to help make our world more optimized and ensure it isn’t broken.
To make our room we will be using Probuilder, which is a package built into Unity. To import it into our project, go to Window>Package manager, and at the top left of the new window, ensure All Packages and Show Preview Packages are checked, and search for Probuilder and click install. After that, search for Progrids, and install that too. This works in tandem with Probuilder and will snap our objects to an easily modifiable grid.
Before we start using Probuilder, there are some settings that should be configured first. Go to Edit>Preferences and then click Probuilder. There are some changes I’d like you to make here from the default settings, and for the sake of time and not having to explain things that many may not understand, I’ll just rapid fire them.
Enable Show Action Notifications
Enable Auto Resize Colliders
Change Static Editor Flags to Everything
Change Collider type to Box Collider
Now you can close the preferences window and open the Probuilder window by going to Tools>Probuilder>Probuilder Window. Progrids should already be in the top left corner, but if it’s not you can go to Tools>Progrids>Progrids Window. You can dock the Probuilder tab just like any other. You can also switch between the icon view if you prefer by right clicking the tab, and selecting Icon mode or Text mode.
Now that that’s done, let’s create our first Probuilder object! Click new shape, select cube, and confirm. You will now see that a cube appears in the scene! If you click the Probuilder icons in the scene view, you will see that on the cube appears vertices, edges, and faces: these are the fundamentals that make up the geometry of all 3D models. If you click on any of them you will be able to move them around in the scene view, and they will snap to the grid set by Progrids: you can increase or decrease the size of the grid by pressing + or _ on the keyboard, and reset the grid to 1 square meter by pressing 0.
We want to make a room, so let’s make a floor. Click new shape, select plane, change the axis to be up, and set the length to be 6 and the width to be 5 and then click build. Reset the transform so that it is at the origin.
Now, decrease the grid size so it is about 0.125m. Then go into face mode (the hotkey is K), select a side face, and scale it down so that the mesh is 0.125m thick horizontally. Now drag it out so that the mesh is the same length as the floor. You can see the dimensions of your Probuilder object by looking at the Probuilder script component in the inspector. The average height of a room is about 2.4m-2.5m, so let’s make it 2.5m tall to snap easily with Progrids. Press ctrl+d to duplicate the wall and drag it over to the other side of the plane. Now press ctrl+k to add a cube and repeat the process to create walls for the remaining sides of the plane, and finally add a ceiling.
You’ve now created a box! But it doesn’t look very much like a room. The biggest thing it’s missing is a window! To make a window, select one of the walls, go into edge select mode and with one of the edges selected press alt+u to add an edge loop. This will add a new loop of edges bisecting your mesh perpendicular to the edge you selected. Your edge loop should be selected after you create it, so drag it out of the way and create 3 more to make a cutout for the window.
Now select the two faces where the window is going to be and press backspace to delete them (don’t press delete; it will delete the entire object!). Now select the edge ring where one of the faces used to be, hold shift and use the gizmo arrows to extrude new faces to bridge the two holes.
There’s a problem: the faces are not actually connected to each other. To fix this, go into vertex select mode and press ctrl+a to select all of the verticies of the mesh, and in the Probuilder tab, click weld verticies. This will merge verticies that occupy the same position in space, also known as overlapping verticies.
To add windows, we’re going to add a cube and just add loop cuts and extrude them inwards to make a window. Now you’re getting the hang of 3D modeling!
If you select vertex colors in the Probuilder tab, you can set faces to a vertex color, which can help with visualization and you can later set those vertex colors to actual materials.
We now have the basic geometry of our room. In the next lesson we will learn about bringing our surfaces to life with materials and textures.
Textures and Materials
Now that we have our geometry, it’s time to apply some detail to the surfaces. The way this is done is through materials. Materials can be applied to the faces of geometry and combine a shader and one or multiple textures. To create a material, right click in the project tab and select Create>Material. The default shader is the standard shader, which is a physically based, or PBR shader.
First, I want you to go to this website, ambientcg.com, and pick a wood floor that you would like to see in your room. When you find one you like, download 1K PNG, extract, and import into Unity by creating a new folder labeled _materials in the project tab and dragging in the folder.
This is going to be the most theory intensive lesson because the knowledge of how PBR shaders work is necessary to make correct, good looking materials. I don’t know how many times I have seen surfaces that look way too shiny and objects with wildly inaccurate reflections on them.
Having a single PBR shader ensures that all materials have consistent shading applied to them, just like in real life. PBR is based on real physical principles, so to understand PBR, you must understand how light interacts with surfaces in the real world. If we drag our material onto, let’s say, the floor we made in the last lesson, we can follow along to see how the standard shader incorporates these principles.
When light hits a surface, some of that light is reflected. In computer graphics, this is referred to as specularity, the amount of reflectivity a surface has. A 100% specular surface would be a perfect mirror, where all of the light that hits it would be reflected at the same angle at which they hit the surface. At the opposite end of the spectrum is diffuse reflection, where light bounces around inside a material before being reflected in a random direction.
You will see that there is a standard shader, and a standard (specular) shader. These are two different ways of thinking about PBR because metals are distinct from non-metals (aka dielectrics). Metals never have a diffuse component while dielectrics typically don’t have a specular component. If your material is not a metal, I would advise to set the metallic slider to 0 or use the specular variant of the standard shader.
The other slider you will see on the Standard shader is smoothness; this controls the clarity of the reflection. Many materials, like a lot of metals, can be quite reflective but that reflection can still be blurry. This is due to the many micro imperfections on the surface invisible to the naked eye but still impact the angle at which rays of light are reflected. (In other programs this gloss or its inverse, roughness)
Another key component of PBR is fresnel; essentially, a surface is more reflective when viewed at more intense angles. Additionally, with transparent surfaces, like water on a lake, they are at their most transmissive when viewed perpendicular to the surface and at their most reflective when viewed parallel to the surface. Fresnel is applied automatically in PBR based on the reflectivity of the material.
Naturally, some light will be absorbed by the materials, but the reflection is what allows them to be visible. The wavelengths that are absorbed, and, more importantly, the ones that are not, is what gives a surface its color. You can set a base color, or use a diffuse or albedo map for different colors across the surface, controlled by the UVs (more on those later).
What’s the difference between a diffuse map and an albedo map? A diffuse map includes directionless shading, whereas an albedo map has all shading removed and put into an ambient occlusion (AO) map. The benefit of this is that the shading inside the material can react to changes in lighting.
So let’s put the albedo and ao maps for our wood floor in the correct slots in our material! Oh, and for the AO to display correctly, click on the texture in the project tab and uncheck where it says sRGB (Color texture), since it is a grayscale texture.
Most every surface exhibits details too small to reasonably recreate with geometry. This is where the normal map comes in. Place it into the appropriate slot, click the Fix Now button that appears and now you should see that the material now really “pops”. What a normal map does is change the angle at which light is reflected for each pixel in the texture. (Each pixel in the normal map represents a vector, where red is horizontal, green is vertical and blue is depth. The “default” blueish purple in a normal map is 50% red, 50% green, and 100% blue, which indicates no change in lighting angle of the corresponding surface.)
Heightmaps are typically used in conjunction with normal maps to fake depth in a material (in Unity by using a technique called parallax mapping), but it breaks when viewed at sharp angles. This should also be set to non sRGB like the AO map. If it appears light green in the project window, I bring it into an image editor like GIMP and re-export it, changing the format to 8bpc GRAY. Or you could just forgo it if you like, it’s not as important as the others.
Now all the texture slots in our material have been filled, we should be able to see how it looks in the scene view. As you can see, a material with a normal map really pops so much more than one without.
We talked a lot about reflection, and as you should see the reflection of the wood floor doesn’t look very accurate. It looks like it’s reflecting the sky! That’s because the reflection in objects is set to the skybox as the default. To change this, we create a reflection probe by right clicking in the hierarchy and going to Lighting>Reflection Probe.
A reflection probe is essentially a 360 camera, capturing from the 6 directions (up down left right forward backward) around it. The resulting image is called a cubemap, and is used for the reflections in objects.
Place the reflection probe in the middle of the room. Under the reflection probe component in the inspector window, there should be two buttons, click on the left one first. This is the bounds, and the objects inside it will have their reflections affected by the probe. The right is the probe origin, or where the reflection probe will capture from.
Because the reflection probe is indoors, we also want to tick on Box Projection (By default the projection of the cubemap is projected as if it is from an infinite distance away, which is great for outdoor areas where there won’t be any parallax. But for indoor areas this means the reflection will be off if the camera or player view is not at the origin of the reflection probe. What box projection does is project the cubemap to the bounds of the reflection probe, which simulates this parallax but also makes clear seams in the projection.)
On the material you can adjust the X and Y scale and offset of the texture. Many texture websites will tell you the scale, so 1m x 1m would be 1×1 but 2m x 2m would be 0.5 x 0.5.
The next important concept to understand is that of material slots. Each polygon is assigned a material, and material slots are a part of the mesh. You can see the assigned materials at the bottom of the inspector window when you click on the object.
UV window and UV stitching
Click on the UV editor in the Probuilder tab. UV coordinates is what tells the mesh how to project the textures onto the faces. The U and V are the 2D axes of the UV space, since X, Y, Z and W are already taken by the 3D space.
We won’t get much into UV editing in this course because Probuilder does most of that for you, but the most useful thing to know is how to stitch UVs. To do that, with the UV window open, click on a face in the scene view and then hold shift and click another connecting face. The UVs will now stitch, and make the texture continue without a seam between the faces.
Now you can find some other textures to finish the room. The next stage is lighting!
Lighting
What we’re going to do in this lesson is create baked lighting for our scene. This means that lighting will be precalculated on your computer so it doesn’t have to be calculated on the player’s, drastically increasing performance and lighting quality. It does this by calculating the lighting for all the static objects and putting that into a lightmap. Dynamic objects (like avatars) are lit by using lighting probes.
To be continued…