- Home /
Can you add a hold frame in a sprite sheet?
I have a sprite sheet animation on a Plane in a 3D environment that I would like to play and then have it hold on frame 1 (or a selected frame) for a few seconds and play again. I would like to be able to control the hold time in the inspector so I can offset the hold if more then one sprite is used.
here is a script with some of my notes and a failed attempt at using an IEnumerator commented out.
using UnityEngine;
using System.Collections;
public class SpriteSheetAnimator : MonoBehaviour
{
//vars for the whole sheet
public int colCount = 5;
public int rowCount = 5;
//vars for animation
public int colNumber = 0; //Zero Indexed
public int rowNumber = 0; //Zero Indexed
public int totalCells = 24;
//public int holdFrame = 0;
//public int holdLength = 0;
public int fps = 12;
//public bool _loopAnimation = true; //loop by default = still needs work.
//Maybe this should be a private var
private Vector2 offset;
//private float delay = 2.0f;
// private float maxWait = 4.0f;
//Update
void Update () { SetSpriteAnimation(colCount,rowCount,rowNumber,colNumber,totalCells,fps); }
//SetSpriteAnimation
void SetSpriteAnimation(int colCount ,int rowCount ,int rowNumber ,int colNumber,int totalCells,int fps ){
// Calculate index
int index = (int)(Time.time * fps);
// Repeat when exhausting all cells
index = index % totalCells;
// Size of every cell
float sizeY = 1.0f / rowCount;
float sizeX = 1.0f / colCount;
Vector2 size = new Vector2(sizeX,sizeY);
// 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.
float offsetX = (uIndex+colNumber) * size.x;
float offsetY = (1.0f - size.y) - (vIndex + rowNumber) * size.y;
Vector2 offset = new Vector2(offsetX,offsetY);
renderer.material.SetTextureOffset ("_MainTex", offset);
renderer.material.SetTextureScale ("_MainTex", size);
}
// IEnumerator EffectsSpacer(){
//set to hold at frame 1
// yield return StartCoroutine(Wait(delay));
//after wait for random range 1-4 rinse and repeat.
//
// }
// IEnumerator Wait (float delay) {
// float timer = Time.time + delay;
// while (Time.time < timer) {
// yield return null;
// }
// }
}
The animation plays and I can change frame rates I just can't add a hold to the sprite sheet for the needed effect.
Any ideas?
Answer by Giantbean · Jun 09, 2014 at 09:46 PM
This code sets a delay in the animation and holds at frame 1. Its not perfect but it is doing the trick.
using UnityEngine;
using System.Collections;
public class SpriteSheetAnimator : MonoBehaviour
{
//vars for the whole sheet
public int colCount = 5;
public int rowCount = 5;
//vars for animation
public int totalCells = 24;
public int hold = 0;
public float delay =0.0f;
public int fps = 12;
private int colNumber = 0; //Zero Indexed
private int rowNumber = 0; //Zero Indexed
private Vector2 offset;
void Start(){
//hold must be a multiple of the totalCells
hold = (totalCells*hold);
}
//Update
void Update () {
int modTime = (int)(Time.time * (fps + delay)) % (totalCells + hold);
if (modTime > hold){
SetSpriteAnimation(colCount,rowCount,rowNumber,colNumber,totalCells,fps);
}
}
//SetSpriteAnimation
void SetSpriteAnimation(int colCount ,int rowCount ,int rowNumber ,int colNumber,int totalCells,int fps ){
// Calculate index
int index = (int)(Time.time * (fps + delay));
// Repeat when exhausting all cells
index = index % totalCells;
// Size of every cell
float sizeY = 1.0f / rowCount;
float sizeX = 1.0f / colCount;
Vector2 size = new Vector2(sizeX,sizeY);
// 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.
float offsetX = (uIndex+colNumber) * size.x;
float offsetY = (1.0f - size.y) - (vIndex + rowNumber) * size.y;
Vector2 offset = new Vector2(offsetX,offsetY);
renderer.material.SetTextureOffset ("_MainTex", offset);
renderer.material.SetTextureScale ("_MainTex", size);
}
}
Answer by incorrect · Jun 09, 2014 at 06:11 PM
You can use animator component and edit animation to make the needed frame last longer then other. Just move those animation keys in animation editor.
why did you post the same answer again? If you believe your answer is correct then explain why in a comment rather then parroting yourself in a "new" answer. I have tested using the animator and it did not work for my needs. Please delete your duplicate answer and if you feel your method will work explain how in a comment on your first answer.
Thank you.
Oh, c'mon, that was just my browser's glitch.
An interesting suggestion but it does not answerer the question so much as bring up new questions.
" I would like to be able to control the hold time in the inspector so I can offset the hold if more then one sprite is used. "
If I have a coded solution I can change one float number in the inspector and the same sprite will play at different times offsetting the animation. Is this possible with your solution or would I need to create multiple animations? Also I am using a sprite sheet not a .png sequence. Wouldn't I need a sequence of frames to use the animator?
I am looking for a robust and reusable solution and as I am not very familiar with the animator and animation properties I do not believe your suggestion answers my question even if it is a possible alternative solution.
Thank you anyways.
I just wanted to say that in most cases it is a bad idea to make animation manualy from script switching sprites and all that stuff. There is an Animator component that works nice and does exactly what your code is supposed to do. You just add Animator to the GameObject and make Animation for it. The Animation will be represented by a sequence of frames (you can define the length of each frame, that is what you need). Then you add this animation to your animator component and enjoy the result. By the way, you can make several states in Animator and switch between them, so the 'idle' state will play through all frames and 'hold' will be the desired hold-frame. Just tweak transitions and you'll get it.
I did animation the way you want it to work and it was not worth it at all. Try looking for some tutorials like this one. You'll realize that it's much easier to work with Unity then you'd expected. You're just think like a programmer, not a game developer. :P
O$$anonymous$$ Sorry the posts were 8 hours apart so i did not notice it was a browser glitch.
Thanks for the suggestion and explanation. I got the code working the way I wanted however I do see your point. I feel like it would need a lot of tweaking on each instance of the animation. Funny thing is I'm an artist and an animator not a programer but since I was working in code I got stuck in that $$anonymous$$dset.
Thanks
P.S. The link you gave looks like a great tutorial. I will have to try out the techniques in both 2D and 3D games to see how it works with sprite sheets.
Thanks again.
Your answer
Follow this Question
Related Questions
Unity got Lag/Delay when change scene, How do I Fix it? 2 Answers
How to stop animated texture looping in Unity Indie? 2 Answers
pre-render an explosion animation? 0 Answers
Turning 2D Sprite Into Ashes 2 Answers
3,2,1 go! before gameplay starts 1 Answer