VRChat Avatar Creation Tips

Here's some notes of mine for working with VRChat avatars. These notes are not meant to be a full tutorial.

Starting out

Skim through the VRChat Creators documentation for Avatars. Install Unity through the VRChat Creator Companion or through Unity Hub as Setting up the SDK recommends. If you're starting with an avatar base model, then most of the instructions in Creating Your First Avatar will be unnecessary, but it's still a good idea to know about these steps if you want to modify much about the avatar.

Blender

Many avatars come with their 3d models as both a Blender (".blend" extension) file and an FBX file. The Blender file is the original file that the model was created in, and the FBX file is the model in a format that is best for importing into Unity. (This is the same relationship as Photoshop PSD files and PNG files, etc.) If you want to edit the model, you should use the original Blender file instead of importing the FBX file into Blender. If you use the FBX file, then the model may lose some of its original properties such as which lines are marked sharp, which will make shadows look worse on the model.

After you make changes to the model, you should save the blend file and then export the model to FBX format for use with Unity. Always export the blend file to FBX with the Armature -> "Add Leaf Bones" option off, or else the model will have extra bones added that Unity doesn't have any need for, negatively impacting your avatar's performance and performance rank.

New Image/Model Resources

Whenever you change a texture or FBX file, if you save your version as a new file instead of overwriting the original textures/FBX, then it's important that in Unity you copy over the original file's settings in the Property Inpsector window. You should compare the original file and the new file's settings and make sure they're the same. For textures you'll likely need to copy some quality and mipmap settings. For FBX files, you may have to copy the the Rig -> "Animation Type" (to Humanoid) and the options in the Model page about "normals". Another way to copy the file settings is to duplicate the original file within Unity and then save over the duplicated file.

VRCFury

Use VRCFury for setting up expressions menu options and toggles. Really. It's great. The VRChat SDK's standard way for setting up expression menu options and toggles requires making custom animations with Unity's full animation editor, which is overcomplicated for this task and very easy to make mistakes in. You often even need separate animations for turning toggles on and turning toggles off if you're using Write Defaults set to off as recommended for VRChat; VRCFury lets you not worry about this while it handles things the right way. VRCFury is not all-or-nothing: it still lets you add your own custom animations to an avatar if you need to in addition to its own animations.

Versioning with Git

You can use Git to version your project, and optionally you can use GitHub or GitLab to host and back up the project. (If you're using a nonfree avatar base, you'll want to make a private repo when using GitHub/etc.) This is a great way to back up your project, to keep track of changes you make to it, and to help share your project with collaborators.

If you're not familiar with Git, you will need to put some effort into learning how to use it. I recommend the Pro Git book, available for free online.

Make sure to install Git, Git LFS, and GitHub Desktop.

Include these files, .gitattributes and .gitignore, in the root of your project. They stop temporary files from being checked in and enable Git LFS for large files. These config files are based on the configs from the official but discontinued GitHub for Unity plugin, with some small additions for tools like GIMP, Substance Painter, and VRCFury.

.gitattributes

* text=auto

# Unity files
*.meta -text merge=unityyamlmerge diff
*.unity -text merge=unityyamlmerge diff
*.asset -text merge=unityyamlmerge diff
*.prefab -text merge=unityyamlmerge diff
*.mat -text merge=unityyamlmerge diff
*.anim -text merge=unityyamlmerge diff
*.controller -text merge=unityyamlmerge diff
*.overrideController -text merge=unityyamlmerge diff
*.physicMaterial -text merge=unityyamlmerge diff
*.physicsMaterial2D -text merge=unityyamlmerge diff
*.playable -text merge=unityyamlmerge diff
*.mask -text merge=unityyamlmerge diff
*.brush -text merge=unityyamlmerge diff
*.flare -text merge=unityyamlmerge diff
*.fontsettings -text merge=unityyamlmerge diff
*.guiskin -text merge=unityyamlmerge diff
*.giparams -text merge=unityyamlmerge diff
*.renderTexture -text merge=unityyamlmerge diff
*.spriteatlas -text merge=unityyamlmerge diff
*.terrainlayer -text merge=unityyamlmerge diff
*.mixer -text merge=unityyamlmerge diff
*.shadervariants -text merge=unityyamlmerge diff

# Image formats
*.psd filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.bmp filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.tiff filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.iff filter=lfs diff=lfs merge=lfs -text
*.pict filter=lfs diff=lfs merge=lfs -text
*.dds filter=lfs diff=lfs merge=lfs -text
*.xcf filter=lfs diff=lfs merge=lfs -text
*.spp filter=lfs diff=lfs merge=lfs -text

# Audio formats
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.aiff filter=lfs diff=lfs merge=lfs -text
*.aif filter=lfs diff=lfs merge=lfs -text
*.mod filter=lfs diff=lfs merge=lfs -text
*.it filter=lfs diff=lfs merge=lfs -text
*.s3m filter=lfs diff=lfs merge=lfs -text
*.xm filter=lfs diff=lfs merge=lfs -text

# Video formats
*.mov filter=lfs diff=lfs merge=lfs -text
*.avi filter=lfs diff=lfs merge=lfs -text
*.asf filter=lfs diff=lfs merge=lfs -text
*.mpg filter=lfs diff=lfs merge=lfs -text
*.mpeg filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text

# 3D formats
*.fbx filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text
*.max filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.dae filter=lfs diff=lfs merge=lfs -text
*.mb filter=lfs diff=lfs merge=lfs -text
*.ma filter=lfs diff=lfs merge=lfs -text
*.3ds filter=lfs diff=lfs merge=lfs -text
*.dfx filter=lfs diff=lfs merge=lfs -text
*.c4d filter=lfs diff=lfs merge=lfs -text
*.lwo filter=lfs diff=lfs merge=lfs -text
*.lwo2 filter=lfs diff=lfs merge=lfs -text
*.abc filter=lfs diff=lfs merge=lfs -text
*.3dm filter=lfs diff=lfs merge=lfs -text

# Build
*.dll filter=lfs diff=lfs merge=lfs -text
*.pdb filter=lfs diff=lfs merge=lfs -text
*.mdb filter=lfs diff=lfs merge=lfs -text

# Packaging
*.zip filter=lfs diff=lfs merge=lfs -text
*.7z filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.rar filter=lfs diff=lfs merge=lfs -text
*.tar filter=lfs diff=lfs merge=lfs -text

.gitignore

[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Bb]uild/
[Bb]uilds/
[Ll]ogs/

# Uncomment this line if you wish to ignore the asset store tools plugin
# [Aa]ssets/AssetStoreTools*

# Visual Studio cache directory
.vs/

# Gradle cache directory
.gradle/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db

# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta

# Unity3D generated file on crash reports
sysinfo.txt

# Builds
*.apk
*.unitypackage

# Crashlytics generated file
crashlytics-build.properties

*.blend1
*.blend1.meta
.DS_Store

*.painter_lock
*.painter_lock.meta

# Files generated by VRCFury on build
Assets/_VRCFury

If you're using Xiexes-Unity-Shaders, you must remove its contained .gitignore file or at least remove the line "Textures/Shadow Ramps/Generated/" from it, or else Git will ignore an important folder and your avatar will be missing its shadows if the project is re-cloned without the ignored files. (The included .gitignore file seems intended for the project's own repository, not for the repository of a project that uses it.)

Related Pages

If you're working with the NKD Protogen base model specifically, then I have a separate page with tips for working with that at NKD Protogen Setup Notes.