Skip to content

Instantly share code, notes, and snippets.

@patricknelson
Last active May 15, 2021 22:08
Show Gist options
  • Save patricknelson/2696f245f3b744b7c8a1a26921701191 to your computer and use it in GitHub Desktop.
Save patricknelson/2696f245f3b744b7c8a1a26921701191 to your computer and use it in GitHub Desktop.
Override the material and texture of default SteamVR HTC Vive controllers in Unity.
using UnityEngine;
using Valve.VR;
/// <summary>
/// Override the material and texture of the HTC Vive controllers, with your own material after SteamVR has loaded and
/// applied the original material. This is useful to help preserve interactions in the model itself.
///
/// NOTE: This is only compatible with the default HTC vive controllers (see UpdateControllerMaterial() below).
///
/// Modified by Patrick Nelson / chunk_split (pat@catchyour.com) from original "OverrideControllerTexture" class
/// by Mr_FJ (from https://steamcommunity.com/app/358720/discussions/0/357287304420388604/) to allow override of full
/// material instead of just textures and also utilize the latest SteamVR_Events model.
///
/// See also: https://forum.unity.com/threads/changing-the-htc-vive-controller-model-with-a-custom-hand-model.395107/
/// </summary>
public class OverrideControllerMaterial : MonoBehaviour
{
#region Public variables
[Header("Variables")]
public Material defaultMaterial;
public bool fixTiling = true; // Check this to correct the texture orientation.
#endregion
void OnEnable ()
{
//Subscribe to the event that is called by SteamVR_RenderModel, when the controller and it's associated material has been loaded completely.
SteamVR_Events.RenderModelLoaded.Listen(OnControllerLoaded);
}
void OnDisable ()
{
//Unsubscribe to the event if this object is disabled.
SteamVR_Events.RenderModelLoaded.Remove(OnControllerLoaded);
}
/// <summary>
/// Override the material of each of the parts, with your custom material.
/// </summary>
/// <param name="newMaterial">Override material</param>
/// <param name="modelTransform">Transform of the gameobject, which has the SteamVR_RenderModel component.</param>
/// <param name="modelTransform">Correct the texture orientation (if it looks offset incorrectly)</param>
public void UpdateControllerMaterial(Material newMaterial, Transform modelTransform, bool fixTiling = true)
{
if (fixTiling) {
// Internally aligns the textures so that they wrap properly around our models the same as the original
// "onepointfive" texture. Prevents you from having to manually flip/rotate the texture yourself in PhotoShop.
newMaterial.mainTextureScale = new Vector2(1, -1);
}
modelTransform.Find("body").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("button").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("led").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("lgrip").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("rgrip").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("scroll_wheel").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("sys_button").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("trackpad").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("trackpad_scroll_cut").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("trackpad_touch").GetComponent<MeshRenderer>().material = newMaterial;
modelTransform.Find("trigger").GetComponent<MeshRenderer>().material = newMaterial;
}
/// <summary>
/// Call this method, when the "RenderModelLoaded" event is triggered.
/// </summary>
/// <param name="controllerRenderModel"></param>
/// <param name="success"></param>
void OnControllerLoaded(SteamVR_RenderModel controllerRenderModel, bool success)
{
UpdateControllerMaterial(defaultMaterial, controllerRenderModel.gameObject.transform, fixTiling);
}
}
@qmisslin
Copy link

qmisslin commented Apr 1, 2020

Yes @patriknelson, that's it, juste add "using Valve.VR" at the top of the script. I was able to make it work without any problem with Universal Render Pipeline in Unity version 2019.3.2.

The only other detail I noticed is that you have to do a mirror (flip up with the bottom) of an image when you want to use it as an albedo texture for the controller. I made this modification for example on a skin downloaded from this reddit : https://www.reddit.com/r/Vive/wiki/skins#wiki_how_to_install_skins

Thank you for your work !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment