I know this might be late a late responce to your question, but I happened to have made a solution while making something for VRChat.
This script moves textures based on changing their UV offset, which might be different from what you are looking for. Although it is a great alternative.
I recently made a script that works by moving the textures on a shader applied to a material. It works with three different textures, and using a bone rotation from 0-2 (1 is default) on the x and y axis, it moves the texture up and down and side to side. You will need to know how to write in C# to modify the script for your needs. This script was made originally made to move textures on a surface to replicate the movement of an eye.
Here is the shader code that the materials need to have when you put them into the script:
Shader "Custom/MultilayeredShader"
{
Properties
{
_MainTex ("Eye Texture", 2D) = "white" {}
_SecondTexture("Lower Eyelid", 2D) = "white" {}
_ThirdTexture("Upper Eyelid", 2D) = "white" {}
_GlossinessEyelids ("Smoothness Eyelids", Range(0,1)) = 0.5
_MetallicEyelids ("Metallic Eyelids", Range(0,1)) = 0.0
_GlossinessEye("Smoothness Eye", Range(0,1)) = 0.5
_MetallicEye("Metallic Eye", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="transparent" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
sampler2D _SecondTexture;
sampler2D _ThirdTexture;
sampler2D _FourthTexture;
struct Input
{
float2 uv_MainTex;
float2 uv_SecondTexture;
float2 uv_ThirdTexture;
float2 uv_FourthTexture;
};
half _GlossinessEyelids;
half _MetallicEyelids;
half _GlossinessEye;
half _MetallicEye;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = (1, 1, 1, 1) + tex2D(_MainTex, IN.uv_MainTex).a * (tex2D(_MainTex, IN.uv_MainTex) - (1, 1, 1, 1));//base white and add eye on top
c = c + (tex2D(_SecondTexture, IN.uv_SecondTexture).a) * (tex2D(_SecondTexture, IN.uv_SecondTexture) - c);//add lower eyelid on top
c = c + (tex2D(_ThirdTexture, IN.uv_ThirdTexture).a) * (tex2D(_ThirdTexture, IN.uv_ThirdTexture) - c); // add upper eyelid on top
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = ((tex2D(_SecondTexture, IN.uv_SecondTexture).a+tex2D(_ThirdTexture, IN.uv_ThirdTexture).a) * _MetallicEyelids) + ((((tex2D(_SecondTexture, IN.uv_SecondTexture).a + tex2D(_ThirdTexture, IN.uv_ThirdTexture).a)*-1)+1) * _MetallicEye);
o.Smoothness = ((tex2D(_SecondTexture, IN.uv_SecondTexture).a + tex2D(_ThirdTexture, IN.uv_ThirdTexture).a) * _GlossinessEyelids) + ((((tex2D(_SecondTexture, IN.uv_SecondTexture).a + tex2D(_ThirdTexture, IN.uv_ThirdTexture).a)*-1) + 1) * _GlossinessEye);;
o.Alpha = c.a;
}
ENDCG
//float lerp(float v0, float v1, float t) {
// return
//}
}
FallBack "Diffuse"
}
Here is the script code (It takes the bones, and eye materials with the shader applied as inputs):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EyeDriver : MonoBehaviour
{
// Start is called before the first frame update
public Material eyeL;
public Transform eyeLbone;
public Transform upperLeft;
public Transform lowerLeft;
public Transform eyeRbone;
public Transform upperRight;
public Transform lowerRight;
public Material eyeR;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
//left eye
float y;
float x;
if (eyeLbone != null || eyeL != null)
{
//left eye code
x = ((eyeLbone.localRotation.eulerAngles.x - 1)*-1);//turn the 0 to 2 to -1 to 1. Then inverse it.
y = ((eyeLbone.localRotation.eulerAngles.y - 1)) / 20; //turn the 0-2 to -1 to 1. then make it move slower up and down.
if ((eyeLbone.localRotation.eulerAngles.x - 1) > 0) //if it is negative.. (going towards center of face)
{
x = (x / 8);
eyeL.SetTextureOffset("_MainTex", new Vector2(x, y)); //make it move slower towards the center of the face
}
else
{
x = (x / 4);
eyeL.SetTextureOffset("_MainTex", new Vector2(x, y)); //else make it move normal speed aka 1/4 speed.
}
}
//right eye
if(eyeRbone != null || eyeR != null)
{
x = (eyeRbone.localRotation.eulerAngles.x - 1);
y = (eyeRbone.localRotation.eulerAngles.y - 1) / 20;
if ((eyeRbone.localRotation.eulerAngles.x - 1) > 0)
{
eyeR.SetTextureOffset("_MainTex", new Vector2((x / 4), y));
}
else
{
eyeR.SetTextureOffset("_MainTex", new Vector2((x / 8), y));
}
}
//upperright
if (upperRight != null || eyeR != null)
{
Transform bone = upperRight;
string texture = "_ThirdTexture";
y = ((0.0175f*((bone.localRotation.eulerAngles.y - 2) * (bone.localRotation.eulerAngles.y - 2)))-0.05f);
if ((bone.localRotation.eulerAngles.y - 1) > 0)
{
eyeR.SetTextureOffset(texture, new Vector2(0, y));
}
else
{
eyeR.SetTextureOffset(texture, new Vector2(0, y));
}
}
//loweright
if (lowerRight != null || eyeR != null)
{
Transform bone = lowerRight;
string texture = "_SecondTexture";
y = ((0.0175f * ((bone.localRotation.eulerAngles.y - 2) * (bone.localRotation.eulerAngles.y - 2))) - 0.05f);
if ((bone.localRotation.eulerAngles.y - 1) > 0)
{
eyeR.SetTextureOffset(texture, new Vector2(0, y));
}
else
{
eyeR.SetTextureOffset(texture, new Vector2(0, y));
}
}
//upperleft
if (upperLeft != null || eyeL != null)
{
Transform bone = upperLeft;
string texture = "_ThirdTexture";
y = ((0.0175f * ((bone.localRotation.eulerAngles.y - 2) * (bone.localRotation.eulerAngles.y - 2))) - 0.05f);
if ((bone.localRotation.eulerAngles.y - 1) > 0)
{
eyeL.SetTextureOffset(texture, new Vector2(0, y));
}
else
{
eyeL.SetTextureOffset(texture, new Vector2(0, y));
}
}
//lowerleft
if (lowerLeft != null || eyeL != null)
{
Transform bone = lowerLeft;
string texture = "_SecondTexture";
y = ((0.0175f * ((bone.localRotation.eulerAngles.y - 2) * (bone.localRotation.eulerAngles.y - 2))) - 0.05f);
if ((bone.localRotation.eulerAngles.y - 1) > 0)
{
eyeL.SetTextureOffset(texture, new Vector2(0, y));
}
else
{
eyeL.SetTextureOffset(texture, new Vector2(0, y));
}
}
}
}
The script part of this code is just a proof of concept, the math in the code will need to be changed to fit your needs.