Animated textures on an object with multiple materials

Hi

I have a small city block mesh - currently there are 4 materials - ground, windows, brick and advert.

I would like to animate the ‘advert’ material using a sprite sheet style animation (i.e. a 4x4 grid of images to cycle through).

I have found several scripts that animate textures, such as this, but none that allow for multiple materials on one object and manual selection of the material to animate.

Can anyone point me in the direction of a script that does what I need?

The script you have is hard coded to use a single material. That’s trivial to fix. The last two lines are:

renderer.material.SetTextureOffset ("_MainTex", offset);
renderer.material.SetTextureScale ("_MainTex", size);

That’s just Unity short hand for “set the first material”. If your object has 4 materials, then you’ll have an array of materials, so, simply guess, or use trial and error to work out which one you need. Then do:

renderer.material[Q].SetTextureOffset ("_MainTex", offset);
renderer.material[Q].SetTextureScale ("_MainTex", size);

where Q is actually an integer between 0 and 3. Alternatively, if you are up for a bit of scripting, in your Start() function, go looking through this array of materials for the one you want, and save the index. The materials will all have a unique name, so something like:

var Q : int = 0;

function Start() {
    var i : int;

    for (i = 0; i < 4; i++) {
        Debug.Log(renderer.material*.name);*

if (renderer.material*.name == “advert”)*
Q = i;
}
}
(Not compiled this code, errors may need to be fixed.)

Thanks Graham

That change is throwing up the following compiler errors:

Assets/Scripts/AnimateTiledTexture.js(26,18):
BCE0048: Type ‘UnityEngine.Material’
does not support slicing.

Code:

var uvAnimationTileX = 24; //Here you can place the number of columns of your sheet. 
                           //The above sheet has 24
 
var uvAnimationTileY = 1; //Here you can place the number of rows of your sheet. 
                          //The above sheet has 1
var framesPerSecond = 10.0;
 
function Update () {
 
	// Calculate index
	var index : int = Time.time * framesPerSecond;
	// repeat when exhausting all frames
	index = index % (uvAnimationTileX * uvAnimationTileY);
 
	// Size of every tile
	var size = Vector2 (1.0 / uvAnimationTileX, 1.0 / uvAnimationTileY);
 
	// split into horizontal and vertical index
	var uIndex = index % uvAnimationTileX;
	var vIndex = index / uvAnimationTileX;
 
	// build offset
	// v coordinate is the bottom of the image in opengl so we need to invert.
	var offset = Vector2 (uIndex * size.x, 1.0 - size.y - vIndex * size.y);
 
	renderer.material[3].SetTextureOffset ("_MainTex", offset);
	renderer.material[3].SetTextureScale ("_MainTex", size);
}

You can slice the “materials” array when changing offset/scale for textures:

The above lines :

renderer.material[3].SetTextureOffset ("_MainTex", offset);
renderer.material[3].SetTextureScale ("_MainTex", size);

Need to be :

renderer.materials[3].SetTextureOffset ("_MainTex", offset);
renderer.materials[3].SetTextureScale ("_MainTex", size);

If anyone is looking for a way to change texture scale (or offset) at runtime here is a script I wrote. I hope it helps :slight_smile:

#pragma strict
/*
// This script is released under GPL! 
// Add this script to gameObjects in your scene that have a Mesh Renderer and single or multiple materials.
// Set the materialNumber to the target material listed the Mesh Renderer Materials array to increment it's scale at runtime.
// You can add multiple instances of this script to one game object to target more than one material,
// just set materialNumber to correspond to a different material in each "applied" script instance.
*/

var materialNumber:int = 0; // The target material in the Mesh Renderer Component "materials" array, for single material gameObjects leave it as 0 to select the main texture
var textureDirX:boolean = false; // Dir ="direction" determines if the increment applied to the texture scale is an addition or subtraction (texture "moves" forward or backwards on the texture's X axis
var textureDirY:boolean = false; // As above but for texture's Y axis
var scaleX:float = 6; // The initial X scale value of the target texture
var scaleY:float = 0.5; // The initial Y scale value of the target texture
var speedX:float = 0.05; // Determines the speed of the texture animation or the increment value applied to the texture X scale every Update() 
var speedY:float = 0.05;  // Determines the speed of the texture animation or the increment value applied to the texture Y scale every Update()
var maxX:float = 8; // The maximum texture X scale value before the textureDirX changes 
var minX:float = 3; // The minimum texture X scale value before the textureDirX changes 
var maxY:float = 3; // The maximum texture Y scale value before the textureDirY changes 
var minY:float = 1; // The minimum texture Y scale value before the textureDirY changes 

function Update () {
	// Y axis logic
	if(textureDirY == false){
		scaleY += speedY;
		if(scaleY >maxY) { 
			scaleY = maxY; 
			textureDirY = true;
		}
	} else {
		scaleY -= speedY;
		if(scaleY < minY) { 
			scaleY = minY; 
			textureDirY = false;
		}
	}
	// X axis logic
	if(textureDirX == false){
		scaleX += speedX;
		if(scaleX >maxX) { scaleX = maxX; textureDirX = true;}
	} else {
		scaleX -= speedX;
		if(scaleX < minX) { scaleX = minX; textureDirX = false;}
	}
	// Apply the new scale/scale values to the target texture
	renderer.materials[materialNumber].SetTextureScale("_MainTex", Vector2(scaleX,scaleY));
}