- Home /
Is it possible to change the texture property of a material via Animation clip?
I have a 2d character that has separate sprite sheets for each of their animations - idle, walk, run cycles etc. Those sprite sheets each have associated normal maps as well, so in the animation clip that defines the individual sprites to animate, I'd also like to specify the corresponding texture to load into the normal map slot of my custom material.
The problem is that, while every other property of my material appears to be exposed in the animation window, the normal map texture simply is not, and I can't work out whether there's a reason for this limitation or (even better) a workaround? ![alt text][1]
My current fix is (as can be seen in the screenshot) to create entirely separate materials for each cycle with the correct normal map statically assigned to each, and change the material via the Sprite Renderer.Material Ref property. However, this seems very unwieldy to create separate materials for each animation, and I'd much rather simply animate the texture property of a single material. Has anyone else experienced this issue or got any advice? Thanks. [1]: /storage/temp/79719-animate-normals.jpg
could you put your idle, walk, run cycles all on one texture and just start the animation at the correct frame depending on what animation is supposed to play? then you wont have to change the texture and save memory.
Thanks for the reply, but we have at least 12 different character animation cycles, some containing 60+ frames, so we can't pack them all into one sheet.
you try material.setTexture? https://docs.unity3d.com/ScriptReference/$$anonymous$$aterial.SetTexture.html
Yes, I'm aware I can use SetTexture to do it in code. And I could also create an animation event in the clip that triggers that code. But for the purposes of maintainability, I'd like to keep all the animated properties relating to the animation directly in the clip itself. For some reason, all the other properties of the material are exposed, but not any texture slots.
to my knowledge it is not possible to unload one texture and load another texture from within the animation window without using a script, especially without creating an instance of the material. it is only possible to alter its properties such as vertex coords, uvs, scale, tiling etc.
However maybe someone will correct me if I'm wrong because my experience is with meshRenderers rather than spriteRenderers. $$anonymous$$eshRenders always create instances and i work with $$anonymous$$eshFilters uv coordinates ins$$anonymous$$d to animate textures because they dont create instances of the material. Sorry i dont have a solution to your question
Answer by tanoshimi · Oct 08, 2016 at 08:26 AM
Based on @RomanLed's comments above and my own experience, it seems it's not possible to animate textures of a material directly via an animation clip. The solution I've ended up going for is to create a new StateMachineBehaviour which overrides OnStateEnter attached to each state in my Animator, which assigns the correct _NormalMap texture corresponding to the atlas of sprites used in that state.
public class SetNormalMap : StateMachineBehaviour
{
public Material material;
public Texture2D normalMap;
// This will be called when the animator first transitions to this state.
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
material.SetTexture("_NormalMap", normalMap);
}
}
In hindsight, this might actually be a more elegant solution than my original plan anyway, since it only assigns the texture once when each state is first entered, rather than reassigning the same texture each time an animation clip looped which would be the case either with an animation event or a animated material property.
EDIT to the Script: the _Normal$$anonymous$$ap doesn't work ; _Bump$$anonymous$$ap does
Wanted to say thank you so much for this script as I didn't know you could run scripts like this in the animator states until now and it really has unlocked many possibilities
Answer by talonairk · Mar 28 at 03:28 AM
Thanks for the solution! It wasn't working for me as-is. So I modified it for anyone else that's having trouble: public class SetNormalMap : StateMachineBehaviour { private Renderer _renderer; public Material material; public Texture2D normalMap;
// This will be called when the animator first transitions to this state.
private void Awake()
{
_renderer = FindObjectOfType<PlayerController>().GetComponent<Renderer>();
_renderer.material.EnableKeyword ("_NormalMap");
}
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
_renderer.material.SetTexture("_NormalMap", normalMap);
}
}
If you get any glitches with the normal maps at the start/end of animations, check the blending on your animation states.
Your answer
Follow this Question
Related Questions
2d Animation sprites - right way? 0 Answers
Evenly distributing sprites in an animation 1 Answer
Animating hair over sprite animation 0 Answers
Lighting an Animated Player 0 Answers
How to swap sprites? 1 Answer