- Home /
Animated Texture and Instantiation
Hi Everyone,
Over the last couple of months I've been trying to wrap my head around some programming in Unity but I am NOT a programmer, so I've been running into a lot of roadblocks.
I've been working with a script to animate textures that I grabbed from the Unity Wiki:
var uvAnimationTileX = 4;
//Here you can place the number of columns of your sheet.
var uvAnimationTileY = 1;
//Here you can place the number of rows of your sheet.
var framesPerSecond = 1.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.SetTextureOffset ("_MainTex", offset);
renderer.material.SetTextureScale ("_MainTex", size);
}
I'm using this texture on gameObject that is instantiated by another. The texture shows a sequence of numbers counting down. The problem I'm having is that the countdown seems to be based on a global time, rather than the amount of time the object has been around for. I could have a hundred of these objects on screen, all generated at different times, but they will all show the same frame of the texture. Is there a way to have the time based off when the object was instantiated, rather than when the program was first run?
I've gone through the forum as well as the script reference and I can't find anything that describes what I'm looking for.
Any help would be greatly appreciated!
Thanks.
Answer by demize2010 · Jun 10, 2011 at 12:34 AM
Hey man,
You could handle this in multiple ways. Using what you have you could use a boolean that tracks the game state and an offset for the time it actually starts working - for example (remember to add your other variables and code from your first script):
var gameController : <Game Controller Script Name>;
var startTime : float;
function Update(){
if(gameController.countDown){
if(!startTime){
startTime = Time.time;
}
var index : int = Time.time - startTime * framesPerSecond;
//The rest of your script
}
}
A tidier way to do it would be to have a co-routine running every second which counted just shifted the texture offset incrementally. In this pesudo example you kick of the co-routine by sending the startCountDown message to your countdown object.
var index : int = 1;
function startCountDown(){
InvokeRepeating("countDown", 0, 1);
}
function countDown(){
if (index < uvAnimationTileX ){
index ++;
}
else{
index = 1;
}
//The rest of your script
}
EDIT If you are instancing these objects and want them to count from when they are created do this:
var startTime : float;
function Awake(){
startTime = Time.time;
}
function Update(){
var index : int = Time.time - startTime * framesPerSecond;
//The rest of your script
}
}
Hi, Thanks for the response!
I'm trying out your first suggestion and aside from one error it seems to be working just fine. The first time one of the countdown objects is instantiated the game pauses with an error:
"NullReferenceException: Object reference not set to an instance of an object"
If I select the instanced game object (ballCountdown(Clone) it allows me to add an object through the inspected under the Game Controller variable. The only object I can select though is ballCountdown(Clone). If I unpause the game it will run perfectly until the next countdown ball appears, then I have to do this all over again.
The most important part though, is that the textures have the proper offset, so it's almost there.
I'm pretty sure this is the part of the script that's giving me trouble as it's the only part I don't fully understand:
var gameController : destroyAfterTime; var startTime : float;
/ other variables listed here /
function Update(){
if(gameController.countDown){
destroyAfterTime is a script I wrote that will blow up the ball after the countdown has finished. It uses the variable "countDown" to deter$$anonymous$$e how long before the ball detonates.
I think I'm just lost on the term "gameController".
Hey man, I've edited the answer so you can use this on instanced objects. gameController was a variable for a master control script but I suspect you don't need that.
It worked! Thank you so much. I actually understand what's going on in your script which I think it the most important part.
Here's the complete script I used in case anyone wants to use it:
var startTime : float;
var uvAnimationTileX = 4; //Here you can place the number of columns of your sheet.
var uvAnimationTileY = 1; //Here you can place the number of rows of your sheet.
var framesPerSecond = 1.0;
function Awake(){ startTime = Time.time; }
function Update(){
var index : int = Time.time - startTime * 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.SetTextureOffset ("_$$anonymous$$ainTex", offset);
renderer.material.SetTextureScale ("_$$anonymous$$ainTex", size);
}
This script will give your object an animated material that will start from the first frame when the object is instantiated.
Thanks again!