Help with Top-Down Controls using 2D Toolkit

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");
    		}
    	}
    }

Never, EVER use “else if”.

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 );
}

Here is a web build to demonstrate : http://www.alucardj.net16.net/unityanswers/CrossAnim.html

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)

=]

Couldn’t you just use a SWITCH/CASE clause directly from Input.GetAxis? ELSE IF statements make my skin crawl. :slight_smile: