I have purchased and am using the unity 2D Toolkit and have run into an error with a script that I am using for movement. At the moment, said script allows for character movement in a top-down environment, updating the displayed animation based on input. The issue I am currently having is that the animations will only display the initial frame and be locked until an idle state (no buttons being pressed) is reached. I was able to remedy the problem by using a boolean “playingOneAnimationLoop = true” during each of the movement calls (commented out in the bellow code under doUp(), etc.). This allows the animations to play, but the character only translates at a few pixels per press. I’d like to know what I need to change in order for both the animations to play and the character to translate properly (comments left in the code for explanation of steps):
var playingOneAnimationLoop : boolean;
var weNeedAnIdle : boolean;
var alreadyBusy : boolean;
enum FACING {up, right, down, left }
var facing : FACING;
var speed : float = 0.25f;
var anim : tk2dAnimatedSprite;
anim = GetComponent(tk2dAnimatedSprite);
function Start ()
{
}
function 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, or, we're just doing nothing
// if we have JUST finished an animation, it's possible
// the user wants ANOTHER animation, if a key is down
if (Input.GetAxis("Vertical") > 0)
{
doUp();
return;
}
if (Input.GetAxis("Horizontal") < 0)
{
doRight();
return;
}
if (Input.GetAxis("Vertical") < 0)
{
doDown();
return;
}
if (Input.GetAxis("Horizontal") > 0)
{
doLeft();
return;
}
// if you get to here, you have JUST finished the play loop
// this split-second AND nobody is pressing any 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 );
facing = FACING.up;
weNeedAnIdle = true;
//playingOneAnimationLoop = true;
transform.Translate(0,0,speed * Time.deltaTime,Space.World);
}
function doRight()
{
alreadyBusy = true;
anim.Play("Walk_Right");
Invoke( "oneLoopIsFinished", 1.00);
facing = FACING.right;
weNeedAnIdle = true;
//playingOneAnimationLoop = true;
transform.Translate(speed * Time.deltaTime,0,0,Space.World);
}
function doDown()
{
alreadyBusy = true;
anim.Play("Walk_Forward");
Invoke( "oneLoopIsFinished", 1.00);
facing = FACING.down;
weNeedAnIdle = true;
//playingOneAnimationLoop = true;
transform.Translate(0,0,-speed * Time.deltaTime,Space.World);
}
function doLeft()
{
alreadyBusy = true;
anim.Play("Walk_Left");
Invoke( "oneLoopIsFinished", 1.00);
facing = FACING.left;
weNeedAnIdle = true;
//playingOneAnimationLoop = true;
transform.Translate(-speed * Time.deltaTime,0,0,Space.World);
}
function oneLoopIsFinished()
{
playingOneAnimationLoop = false;
}
function changeToIdle()
{
if ( facing == FACING.up )
{
anim.Play("Up_Idle");
}
if ( facing == FACING.right )
{
anim.Play("Right_Idle");
}
if ( facing == FACING.left )
{
anim.Play("Left_Idle");
}
if ( facing == FACING.down )
{
anim.Play("Forward_Idle");
}
weNeedAnIdle = false;
}
Hey Asy1umrat, I have re-written the script with a slightly different implementation which should help you manage your facing transitions a little better. The only problem is that I don’t know enough Javascript to give the code in Javascript (it’s written in C#). However, you should be able to pull the logic straight out of this script and put it in the correct Javascript syntax. I didn’t quite get to testing the script (I’ll do that once I get a chance), but this should give you an idea of the direction you may want to head in. I hope this helps you.
using UnityEngine;
using System.Collections;
public class CharController : MonoBehaviour
{
private float m_speed = .25f;
private Facing m_facing = Facing.Down;
private bool m_idle = true;
private tk2dAnimatedSprite m_anim;
private void Awake()
{
m_anim = GetComponent<tk2dAnimatedSprite>();
}
// Use this for initialization
private void Start ()
{
}
// Update is called once per frame
private void Update ()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
float horizontalAbs = Mathf.Abs(horizontal);
float verticalAbs = Mathf.Abs(vertical);
// Instead of updating both directions on a single frame, we limit it to movement on a single axis by updating x or z.
if (horizontalAbs > verticalAbs)
{
transform.Translate(new Vector3(horizontal * m_speed * Time.deltaTime, 0.0f, 0.0f), Space.World);
}
else
{
transform.Translate(new Vector3(0.0f, 0.0f, vertical * m_speed * Time.deltaTime), Space.World);
}
if (horizontal < 0.0f && m_facing != Facing.Left) //Only update to left facing if we are not already facing left.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Left;
UpdateFacing();
}
else if (horizontal > 0.0f && m_facing != Facing.Right)//Only update to Right facing if we are not already facing Right.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Right;
UpdateFacing();
}
else if (vertical > 0.0f && m_facing != Facing.Up)//Only update to Up facing if we are not already facing Up.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Up;
UpdateFacing();
}
else if (vertical < 0.0f && m_facing != Facing.Down)//Only update to Down facing if we are not already facing Down.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Down;
UpdateFacing();
}
if (m_idle == false && horizontal == 0.0f && vertical == 0.0f) //This is an edge case. This will happen when horizontal and vertical are equal (which is basically when we stop moving since both axis will return 0.0f).
{
m_idle = true;
PlayIdleAnimation();
//***Key to starting the correctly-facing walking animation again.
m_facing = Facing.Idle;
}
}
/// <summary>
/// Plays the correct walking animation depending on the current facing.
/// </summary>
private void UpdateFacing()
{
switch (m_facing)
{
case Facing.Down:
m_anim.Play("Walk_Down");
break;
case Facing.Left:
m_anim.Play("Walk_Left");
break;
case Facing.Right:
m_anim.Play("Walk_Right");
break;
case Facing.Up:
m_anim.Play("Walk_Up");
break;
}
}
/// <summary>
/// Plays the correct idle animation depending on the current facing.
/// </summary>
private void PlayIdleAnimation()
{
switch (m_facing)
{
case Facing.Down:
m_anim.Play("Down_Idle");
break;
case Facing.Left:
m_anim.Play("Left_Idle");
break;
case Facing.Right:
m_anim.Play("Right_Idle");
break;
case Facing.Up:
m_anim.Play("Up_Idle");
break;
}
}
enum Facing
{
Up,
Right,
Down,
Left,
Idle//***New variable used when we go into Idle so that we can update our facing correctly once we start moving again.
}
}
Edit: The idle-walking behavior you saw was caused by the current facing already being set. For example, if you walked right, then your current facing would be Facing.Right, therefore the check under m_facing != Facing.Right
would fail if you tried walking right again. The fix for that is to make a just make a new variable for Facing that we can set the current facing to once we have gone idle.
hello i was looking for something like this. but i still have a problem. i cant make it jump. when i push the jump button my character start to fly i try to use gravity but it doesnt work. here is the script.
public class AnimController: MonoBehaviour
{
private float m_speed = 6f;
private float m_speedjump = 10f;
private Facing m_facing = Facing.Right;
private bool m_idle = true;
float gravedad = 80;
bool airControl = true;
Vector3 moveDirection = Vector3.zero;
private tk2dAnimatedSprite m_anim;
private void Awake()
{
m_anim = GetComponent<tk2dAnimatedSprite>();
}
// Use this for initialization
private void Start ()
{
}
private void Jump()
{
CharacterController controller = GetComponent<CharacterController>();
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, 0);//extra
float inputX = Input.GetAxis("Horizontal");//extra
if(Input.GetButton("Jump"))
{
moveDirection.y = m_speedjump; //extra
airControl = true;
}
if (airControl == true)//extra
{
moveDirection.x = inputX * m_speed; //extra
}
moveDirection.y -= gravedad * Time.deltaTime;//extra
controller.Move(moveDirection * Time.deltaTime);//extra
}
// Update is called once per frame
private void Update ()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
float horizontalAbs = Mathf.Abs(horizontal);
float verticalAbs = Mathf.Abs(vertical);
// Instead of updating both directions on a single frame, we limit it to movement on a single axis by updating x or z.
if (horizontalAbs > verticalAbs)
{
transform.Translate(new Vector3(horizontal * m_speed * Time.deltaTime, 0.0f, 0.0f), Space.World);
}
// else
{
//transform.Translate(new Vector3(0.0f, vertical * m_speed * Time.deltaTime,0.0f), Space.World);
}
//Jump();
if (horizontal < 0.0f && m_facing != Facing.Left) //Only update to left facing if we are not already facing left.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Left;
UpdateFacing();
}
else if (horizontal > 0.0f && m_facing != Facing.Right)//Only update to Right facing if we are not already facing Right.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Right;
UpdateFacing();
}
/*
else if (vertical > 0.0f && m_facing != Facing.Up)//Only update to Up facing if we are not already facing Up.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Up;
UpdateFacing();
}
else if (vertical < 0.0f && m_facing != Facing.Down)//Only update to Down facing if we are not already facing Down.
{
m_idle = false;
//Set the new facing.
m_facing = Facing.Down;
UpdateFacing();
}*/
if (m_idle == false && horizontal == 0.0f && vertical == 0.0f) //This is an edge case. This will happen when horizontal and vertical are equal (which is basically when we stop moving since both axis will return 0.0f).
{
m_idle = true;
PlayIdleAnimation();
//***Key to starting the correctly-facing walking animation again.
m_facing = Facing.Idle;
}
}