Update 3-13-14
Unity kinda released some really nice 2D tools, I really don't know how relevant or helpful this is now.
I've been working on a 2D side scroller. Being my cheap self I'm not going to bother buying some helpful tool that would probably speed up everything a substantial amount, and created my own method of 2D animation for things in Unity3D. This code does not work with a sprite sheet, but I hope it makes it easy enough for you to incorporate one if you wanted to.
Warnings:
The animation is displayed by updating the meshes material's texture each frame (this can mess up at high frame speeds).
This code is assuming the 2D sprites are moving along the X and Y axis.
When changing directions, it is scaling the transform negatively across it's x axis.
Its assuming default direction facing is right.
Frame speed works in reverse to frame rate, don't get these confused. If you want the frame rate to be 30 seconds, set the frame speed to .033 (1/30).
Check out the game this code was made for!
Unity kinda released some really nice 2D tools, I really don't know how relevant or helpful this is now.
I've been working on a 2D side scroller. Being my cheap self I'm not going to bother buying some helpful tool that would probably speed up everything a substantial amount, and created my own method of 2D animation for things in Unity3D. This code does not work with a sprite sheet, but I hope it makes it easy enough for you to incorporate one if you wanted to.
Warnings:
The animation is displayed by updating the meshes material's texture each frame (this can mess up at high frame speeds).
This code is assuming the 2D sprites are moving along the X and Y axis.
When changing directions, it is scaling the transform negatively across it's x axis.
Its assuming default direction facing is right.
using UnityEngine;
using System.Collections;
public enum Directions{left,right}
public class FlatCharacterAnimation : MonoBehaviour {
public FlatAnimation[] animations;
public string defaultAnimation;
FlatAnimation currentAnimationPlaying;
string animationCurrentlyPlaying = "";
Texture2D[] framesToPlay;
float frameSpeed;
int currentFrame = 0;
Directions directionCharactersFacing = Directions.right;
bool animationIsPlaying;
#region FlatAnimationClass
[System.Serializable]
public class FlatAnimation{
public string name ="";
public Texture2D[] frames;
public float frameSpeed;
public Texture2D[] GetFrames(){
return frames;
}
}
#endregion
public Directions GetDirectionFacing(){
return directionCharactersFacing;
}
public void Play(string animation){
if(animation != animationCurrentlyPlaying){
ChangeAnimation(GetAnimation(animation));
animationIsPlaying = true;
}
}
public void Play(string animation, Directions direction){
if(animation != animationCurrentlyPlaying){
ChangeAnimation(GetAnimation(animation));
animationIsPlaying = true;
}
if(direction != directionCharactersFacing) //make sure players facing right direction, if not, changes direction
ChangeDirectionPlayersFacing(direction);
}
FlatAnimation GetAnimation(string animationName){
for(int i = 0; i < animations.Length; i++){
if(animations[i].name == animationName){
return animations[i];
}
}
Debug.LogWarning("The animation you are trying to play does not exist! Try checking spelling and capitalization");
return null;
}
void ChangeAnimation(FlatAnimation newAnimation){
animationCurrentlyPlaying = newAnimation.name;
framesToPlay = newAnimation.frames;
frameSpeed = newAnimation.frameSpeed;
currentFrame = 0;
}
void ChangeDirectionPlayersFacing(Directions direction){
Vector3 scale;
directionCharactersFacing = direction;
switch(direction){
case Directions.left:
//Debug.Log("Left Direction");
scale = gameObject.transform.localScale;
scale.x *= -1;
gameObject.transform.localScale = scale;
break;
case Directions.right:
//Debug.Log("Left Direction");
scale = gameObject.transform.localScale;
scale.x *= -1;
gameObject.transform.localScale = scale;
break;
}
}
float nextFrameTime;
void UpdateAnimation(){
if(nextFrameTime < Time.time &&framesToPlay != null){
//Debug.Log ("current frame: " + currentFrame + "currentAnimationFrames Legth: "+currentAnimationFrames.Length);
nextFrameTime = frameSpeed+Time.time;
if(currentFrame == framesToPlay.Length-1){
currentFrame = 0;
} else if(currentFrame < framesToPlay.Length){
currentFrame += 1;
}
gameObject.GetComponent<MeshRenderer>().material.mainTexture = framesToPlay[currentFrame];
}
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (animationIsPlaying){
UpdateAnimation();
}
}
}
Setting this up:
Its more than just dragging and dropping the script, but it doesn't take much time. To begin, in case any of you still have graphics and code on the same Game Object, stop it, please. To create your graphics object for this, you can do it three ways.- Create a Primitive Cube. Use this method if your shader for the material is going to ignore light. Scale one of the axis to 0. Reasons for creating a cube over a plane is that a cube has fewer faces than the default plane for some reason in unity. The shader you would use for this on the material would be Unlit>Transparent.
- Create a Primitive Plane. Use this method if your material will not ignore light. This method will have more faces, but in most cases it will not be considered to serious. Make sure the y axis stays 1. The shader you would use on the material for this option would be Transparent/Cutout/YourOption
- Create Your Own Object To Render It. Takes time, more faces than a cube usually, but can be less faces that a plane.
If your developing for a mobile device, consider using option 1. Not so much for the poly count, but for the shader. Unlit shaders take less power to process.
In my example I'm going to be using option 2, and these are the steps.
- Create an Empty Game Object (Cntrl+Shift+N), and rename Enemy
- Create a Primitive Plane and parent it to Enemy. Rename Plane to graphics.
- Set rotations on plane to (90, 180, 0),
- Add Flat Character Animation (Script Above) to graphics object.
- Re-size Animations Size to however animations you need.
- For each animation, set the name(IMPORTANT), frames, and Frame Speed.
Frames are the individual pictures you want to play in sequence for the animation.
To play the animation, grab the instance of the flat character animation, and call either Play(string nameOfAnimation); or Player(string nameOfAnimation, Directions, directionToFace);
Example of the Inspector
Example of the Object in the scene
Check out the game this code was made for!
Comments
Post a Comment