- Home /
Using Textures/Sprite Sheet to animate a 3D Object (Without Scripts)
I'm trying to animate a 3D character's face by either changing the texture or only showing a certain part of the material. I have successfully been able to do that with scripts, but the project I am working on does not allow scripts to be used.
Is there a way I can use the Animator to modify the texture/material?
If anyone is wondering what the script I created is. It is a modified version of a "Looping Sprite Sprite Sheet" animation script. I made this one specific for eyes blinking.
public class EyeControler : $$anonymous$$onoBehaviour { //Setting up the Script to take a material with a sprite sheet public int Columns = 3; public int Rows = 10; public float FramesPerSecond = 25f; public int Face = 10; private int NewFaceCheck = 0; public int TimeBettweenBlinks = 60;
public float RunTimeInSeconds
{
get
{
return ((1f / FramesPerSecond) * (Columns * Rows));
}
}
private $$anonymous$$aterial materialCopy = null;
void Start()
{
// Copy its material to itself in order to create an instance not connected to any other
materialCopy = new $$anonymous$$aterial(GetComponent<Renderer>().shared$$anonymous$$aterial);
GetComponent<Renderer>().shared$$anonymous$$aterial = materialCopy;
Vector2 size = new Vector2(1f / Columns, 1f / Rows);
GetComponent<Renderer>().shared$$anonymous$$aterial.SetTextureScale("_$$anonymous$$ainTex", size);
}
void OnEnable()
{
StartCoroutine(UpdateTiling());
}
private IEnumerator UpdateTiling()
{
float x = 0f;
float y = 0f;
int b = Columns;
Vector2 offset = Vector2.zero;
while (true)
{
y = (float)(Face - 1) / Rows; //To select the specific face, numbers go up from the bottom
NewFaceCheck = Face;
for (int j = 0; j <= TimeBettweenBlinks; j++) // x
{
if (j <= Columns - 1)
{
//Start Blink
x = (float)j / Columns;
b = Columns - 1;
} else if(j < TimeBettweenBlinks - Columns + 1)
{
//Check to see if the face updated since this blink started.
//If one does, imediatly ends the current blink and starts the next one.
if (NewFaceCheck != Face)
{
j = TimeBettweenBlinks - Columns + 1;
}
}
else
{
//End Blink
x = (float)b / Columns;
b--;
}
offset.Set(x, y);
GetComponent<Renderer>().shared$$anonymous$$aterial.SetTextureOffset("_$$anonymous$$ainTex", offset);
yield return new WaitForSeconds(1f / FramesPerSecond);
}
}
}
}
Answer by dentalhickory · Dec 07, 2020 at 03:42 AM
Ok, so I found a workaround. What you can do is create a animation that is one frame long and has one of every face in it set to inactive as a property. Each animation should only have one face.
What I did was create a 1 frame animation for each mouth shape and closed eye expressions, then animated blinking by having the key frames set the different eyes as active/inactive.
Once I am satisfied with amount of animations, I go into the animator and have 2 different layers, one for eyes and one for mouths. This works for me, however it caused another problem for me where in darker/ directional lighting, there is a seam line where the eyes and mouth meet the rest of the head. But at least it works.