I am attempting to make a top-down game using the 2D Toolkit.
I am looking for a controls that “I press LEFT. While he is walk it is not possible to press any other key.” After the button is released, it should play the “animation” for idle in each direction (1 frame each). While the player is walking they should not be able to interrupt the current walk animation.
Forward Walk: 4 frames/4 Frame rate, Up Walk: 4 frames/4 Frame rate, Left Walk: 2 Frames/8 Frame rate, Right Walk: 2 Frames/8 Frame rate
also, as you hold the movement button, the animation should loop, which at the moment it fails to do, only showing the first and last frames when press/holding and releasing, respectively.
At the moment I am attempting to get my controller working properly, playing different walking animations based on which direction the character is moving. Problems include if multiple buttons are pressed the incorrect animation will play. I have been attempting to rebuild from scratch:
using UnityEngine;
using System.Collections;
public class Animation_Controler : MonoBehaviour
{
tk2dAnimatedSprite anim;
float speed = 0.25f;
int lastButtonPress = 2;
// Use this for initialization
void Start ()
{
anim = GetComponent<tk2dAnimatedSprite>();
}
// Update is called once per frame
void Update ()
{
//Moving Animations
if (Input.GetKey(KeyCode.UpArrow))
{
transform.Translate(0,0,speed * Time.deltaTime,Space.World);
if (Input.GetKeyDown(KeyCode.UpArrow))
{
anim.Play("Walk_Up");
}
lastButtonPress = 0;
}
else if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Translate(-speed * Time.deltaTime,0,0,Space.World);
if (Input.GetKeyDown(KeyCode.LeftArrow))
{
anim.Play("Walk_Left");
}
lastButtonPress = 1;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
transform.Translate(0,0,-speed * Time.deltaTime,Space.World);
if (Input.GetKeyDown(KeyCode.DownArrow))
{
anim.Play("Walk_Forward");
}
lastButtonPress = 2;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
transform.Translate(speed * Time.deltaTime,0,0,Space.World);
if (Input.GetKeyDown(KeyCode.RightArrow))
{
anim.Play("Walk_Right");
}
lastButtonPress = 3;
}
//Idle Animations
else if (lastButtonPress == 0)
{
anim.Play("Up_Idle");
}
else if (lastButtonPress == 1)
{
anim.Play("Left_Idle");
}
else if (lastButtonPress == 2)
{
anim.Play("Forward_Idle");
}
else if (lastButtonPress == 3)
{
anim.Play("Right_Idle");
}
}
}
Maybe this is what you want. You can write this many different ways, I have tried to do it so it is as explanatory as possible.
enum FACING {up, right, down, left }
private var playingOneAnimationLoop:boolean
private var weNeedAnIdle:boolean
private var facing:FACING;
Update()
{
// if you only get to here, one of the walk animations
// is actually playing at this instant
if ( playingOneAnimationLoop ) return;
// if you get to here, we have either JUST finished an
// animation this split-second, or, we're just doing nothing
// if we have JUST finished an anaimtion, it's possible
// the user wants ANOTHER animation, if a key is down
if (Input.GetKey(KeyCode.UpArrow)) { dpUP(); return; }
if (Input.GetKey(KeyCode.RightArrow)) { doRight(); return; }
if (Input.GetKey(KeyCode.DownArrow)) { doDown(); return; }
if (Input.GetKey(KeyCode.LeftArrow)) { doLeft(); return; }
// if you get to here, you have JUST finished the play loop
// this split-second AND nobody is pressing any damned keys
// (or, we're just doing nothing and sitting around)
// if weNeedAnIdle is true it means we have JUST finished
// an animation. we'll simply ONCE (one time) play the
// correct standing anime. ie "set it to" the right image
if ( weNeedAnIdle ) changeToIdle();
}
function doUp()
{
alreadyBusy = true;
anim.Play("Walk_Up");
Invoke( "oneLoopIsFnished", 1.00 );
// NOTE use the CORRECT time for each animation
// you may want to tweak them in each case
// for the feel you want, jerky, smooth whatever
facing = FACING.up;
weNeedAnIdle = true;
}
function doRight .. similar
function doDown .. similar
function doLeft .. similar
function oneLoopIsFinished()
{
playingOneAnimationLoop = false;
}
function changeToIdle()
{
if ( facing == FACING.up ) anim.Play("Up_Idle");
if ( facing == FACING.right ) anim.Play("Right_Idle");
.. etc ..
weNeedAnIdle = false;
}
Here is the switch-case from my comment, tested and working with an example web player build at the bottom. I also included the change from Input.GetKey to Input.GetAxis :
#pragma strict
private var speed : float = 0.5;
private var moveDir : int = 0;
private var lastDir : int = 0;
function Update()
{
if ( Input.GetAxis("Vertical") > 0 ) // Input.GetKey(KeyCode.UpArrow)
{
moveDir = 0;
lastDir = 0;
}
else if ( Input.GetAxis("Horizontal") < 0 ) // Input.GetKey(KeyCode.LeftArrow)
{
moveDir = 1;
lastDir = 1;
}
else if ( Input.GetAxis("Vertical") < 0 ) // Input.GetKey(KeyCode.DownArrow)
{
moveDir = 2;
lastDir = 2;
}
else if ( Input.GetAxis("Horizontal") > 0 ) // Input.GetKey(KeyCode.RightArrow)
{
moveDir = 3;
lastDir = 3;
}
else
{
moveDir = -1;
}
switch( moveDir )
{
case 0 :
// move up
transform.Translate( 0, 0, speed * Time.deltaTime, Space.World );
animation.CrossFade("TPC_Dude Running");
break;
case 1 :
// move left
transform.Translate( -speed * Time.deltaTime, 0, 0, Space.World );
animation.CrossFade("TPC_Dude Strafing");
break;
case 2 :
// move down
transform.Translate( 0, 0, -speed * Time.deltaTime, Space.World );
animation.CrossFade("TPC_Dude Walking Backward");
break;
case 3 :
// move right
transform.Translate( speed * Time.deltaTime, 0, 0, Space.World );
animation.CrossFade("TPC_Dude Strafing");
break;
default : // case -1 :
// play correct idle animation
switch( lastDir )
{
case 0 :
// idle up
animation.CrossFade("TPC_Dude Idle");
break;
case 1 :
// idle left
animation.CrossFade("TPC_Dude Idle");
break;
case 2 :
// idle down
animation.CrossFade("TPC_Dude Idle");
break;
case 3 :
// idle right
animation.CrossFade("TPC_Dude Idle");
break;
}
break;
}
//Debug.Log( " moveDir " + moveDir + " : lastDir " + lastDir );
}
This is a direct copy of the script in my build, so you’ll have to change the animation names (and they’re old animations! but all I had on hand right now, enough for the example)