Animated Texture Extended - play just once.

I’m using the Animated Texture Extended script ( Animated Texture Extended on Community Wiki) to animate my characters (sprite-like textures on quads).

Everything works well while I’m working on looped animations - like running or walking. The problem appeared when I tried to make an Attack animation - triggered just once when player makes certain Input.

The animation is not synched to play from the first frame each time player pushes the button - so sometimes it starts from Frame one, sometimes the second, third and so on.

Now, after Google crusade, I found out ( Similar Problem Link ) that it’s because the Script is animating the said texture from the Start of the game, not from the point of Player Input. Normally I would just use the script from the above link, but… well… I’ve got a few looong scripts which are already accesing the variables from the Script in the first link, so messing with it would most probably wreck my whole project, as I’m still in the Newbie phase.

Is there a way to tweak the first script so it starts playing on calling a certain Function, not from the Start of the game?

Here’s the problematic Script, for convenience:

+++++++++++++++++++++

#pragma strict

//vars for the whole sheet
var colCount	: int =  4;
var rowCount	: int =  4;
 
//vars for animation
var rowNumber	: int =  0; //Zero Indexed
var colNumber	: int =  0; //Zero Indexed
var totalCells	: int =  4;
var fps		: int = 10;
private var offset	: Vector2;  //Maybe this should be a private var
 
//Update
function Update () { SetSpriteAnimation(colCount,rowCount,rowNumber,colNumber,totalCells,fps);  }
 
//SetSpriteAnimation
function SetSpriteAnimation(colCount : int,rowCount : int,rowNumber : int,colNumber : int,totalCells : int,fps : int){
 
	// Calculate index
	var index : int = Time.time * fps;
	// Repeat when exhausting all cells
	index = index % totalCells;
 
	// Size of every cell
	var size = Vector2 (1.0 / colCount, 1.0 / rowCount);
 
	// split into horizontal and vertical index
	var uIndex = index % colCount;
	var vIndex = index / colCount;
 
	// build offset
	// v coordinate is the bottom of the image in opengl so we need to invert.
	offset = Vector2 ((uIndex+colNumber) * size.x, (1.0 - size.y) - (vIndex+rowNumber) * size.y);
 
	renderer.material.SetTextureOffset ("_MainTex", offset);
	renderer.material.SetTextureScale  ("_MainTex", size);
}

You need to add a local timer you control (rather than using Time.time), and have some sort of control variable that tells the animation when to stop. Adding a simple float timer and bool control variable gives:

#pragma strict
 
//vars for the whole sheet
var colCount    : int =  4;
var rowCount    : int =  4;
 
//vars for animation
var rowNumber   : int =  0; //Zero Indexed
var colNumber   : int =  0; //Zero Indexed
var totalCells  : int =  4;
var fps        : int = 10;
private var offset  : Vector2;  //Maybe this should be a private var

private var isPlaying : boolean = false;    // control variable
private var timer : float = 0.0;            // animation timer
 
//Update
function Update (){

    // only update animation if we are playing
    if(isPlaying){

        SetSpriteAnimation(colCount,rowCount,rowNumber,colNumber,totalCells,fps);
    }
}
 
//SetSpriteAnimation
function SetSpriteAnimation(colCount : int,rowCount : int,rowNumber : int,colNumber : int,totalCells : int,fps : int){
 
    // update timer
    timer += Time.deltaTime;

    // Calculate index
    var index : int = timer * fps;      // using timer instead of Time.time
    // Repeat when exhausting all cells
    index = index % totalCells;

    // work out the index of our final frame
    var finalFrameIndex : int = colNumber * colCount + rowNumber + totalCells - 1;

    Debug.Log(finalFrameIndex + ", " +index);

    // check if we have hit the final frame
    if(index >= finalFrameIndex){
        // stop playing
        isPlaying = false;

        // clamp to final frame
        index = finalFrameIndex;
    }
 
    // Size of every cell
    var size = Vector2 (1.0 / colCount, 1.0 / rowCount);
 
    // split into horizontal and vertical index
    var uIndex = index % colCount;
    var vIndex = index / colCount;
 
    // build offset
    // v coordinate is the bottom of the image in opengl so we need to invert.
    offset = Vector2 ((uIndex+colNumber) * size.x, (1.0 - size.y) - (vIndex+rowNumber) * size.y);
 
    renderer.material.SetTextureOffset ("_MainTex", offset);
    renderer.material.SetTextureScale  ("_MainTex", size);

    
}

public function FireOneShot(){
    
    // reset local timer
    timer = 0.0;

    // start playing
    isPlaying = true;
}

Calling the FireOneShot() function should do what you need :slight_smile:

I’d also recommend reading up on Unity’s inbuilt sprite animation system. Check out Michael Cumming and Ray Wenderlich’s tutorials for a great intro to the system :smiley: