- Home /
Moving with coroutines
Hi!!
I'm trying to develop a 2D game using the 2DToolkit, at the very beginning is easy, using the keyboard to move and other things. I'm using the TP_Controller from 3DBuzz, may be you may heard about it, and using the keyboard to move the character and animate it was fine, using the mouse is when the problem start.
Im using the mouse to move the character, but the animation get froze still the movement ends, and this is a big problem. Im trying to use Coroutines but still I have no get it work. I dont know what it best, if make the manage of the movement like coroutine or if the playing animation have to be the coroutine, and also where to trigger.
Of course, the code is divided in three classes, TPController, TPMotor and TPAnimator, for the moment I'm letting some code of animation in TPController but I have to re-factorize it
TP_Controller
public class TP_Controller : MonoBehaviour
{
public static CharacterController CharacterController;
public static TP_Controller Instance;
private Vector3 targetPosition;
private Vector2 targetPoint;
public Vector2 targetDirection;
private bool isAnimated = false;
void Awake ()
{
CharacterController = GetComponent("CharacterController") as CharacterController;
Instance = this;
targetDirection = Vector2.zero;
}//Awake()
void Update ()
{
if(Camera.mainCamera == null)
return;
GetLocomotionInput();
if(!isAnimated)
StartCoroutine(HandleActionInput());
TP_Motor.Instance.UpdateMotor();
}//Update()
void GetLocomotionInput()
{
TP_Motor.Instance.VerticalVelocity = TP_Motor.Instance.MoveVector.y;
// Reset the MoveVector
TP_Motor.Instance.MoveVector = Vector2.zero;
// Getting the targetPosition from the clic
if(Input.GetKeyDown(KeyCode.Mouse0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var playerPlane = new Plane(Vector3.forward,CharacterController.transform.position);
float hitdist = 0.0f;
// Detecting the place of hit
if(playerPlane.Raycast(ray,out hitdist))
{
// Position in 3D where the clic was made
targetPosition = ray.GetPoint(hitdist);
targetPoint = (Vector2) (targetPosition - CharacterController.transform.position);
}
}
//CharacterController.transform.position = Vector2.Lerp(CharacterController.transform.position,targetPosition, Time.deltaTime * 5f);
// Stopping our player when reach the target at 0.2 near
if(Vector2.Distance(new Vector2(targetPosition.x,0),new Vector2(CharacterController.transform.position.x,0)) < 0.2f )
{
targetDirection = Vector2.zero;
}
else
{
if(targetPoint.x > 0)
targetDirection = Vector2.right;
else
targetDirection = Vector2.right * -1;
TP_Motor.Instance.TargetPoint = targetPoint;
}
TP_Motor.Instance.MoveVector += new Vector2(targetDirection.x,0);
//TP_Animator.Instance.DetermineCurrentDirection();
}//GetLocomotionInput()
public IEnumerator HandleActionInput()
{
TP_Animator.Instance.anim.Play("walking_side_right");
yield return 0;
}//HandleActionInput()
}
TPMotor
public class TPMotor : MonoBehaviour {
public static TP_Motor Instance;
public float MoveSpeed = 5f;
public float JumpSpeed = 3f;
public float Gravity = 21f*0.5f;
public float TerminalVelocity = 20f;
public Vector2 MoveVector { get; set; }
public Vector2 TargetPoint { get; set; }
public float VerticalVelocity { get; set; }
void Awake()
{
Instance = this;
}//Awake()
public void UpdateMotor()
{
//SwapAlignCharacterWithCamera();
ProcessMotion();
}//UpdateMotor()
void ProcessMotion()
{
// Applying the velocity of moving
MoveVector *= MoveSpeed;
// adding the last position in Y
MoveVector = new Vector2(MoveVector.x,VerticalVelocity);
// Applying Gravity
ApplyGravity();
TP_Controller.CharacterController.Move(MoveVector * Time.deltaTime);
//StartCoroutine("Move");
}//ProcessMotion()
void ApplyGravity()
{
if(MoveVector.y > -TerminalVelocity)
MoveVector = new Vector2(MoveVector.x,MoveVector.y - Gravity * Time.deltaTime);
if(TP_Controller.CharacterController.isGrounded && MoveVector.y < -1)
MoveVector = new Vector2(MoveVector.x, -1);
}//ApplyGravity()
TP_Animator
public class TPAnimator : MonoBehaviour { public static TPAnimator Instance; public tk2dAnimatedSprite anim;
public enum CharacterState
{
WalkingLeft, WalkingRight, Running, Idle, Falling, Jumping, Dead, Hitting
}
public enum Direction
{
Stationary, Left, Right
}
public CharacterState State;
public Direction MoveDirection;
void Awake()
{
Instance = this;
}//Awake()
void Start()
{
anim = GetComponent<tk2dAnimatedSprite>();
}//Start()
void Update()
{
DetermineCurrentDirection();
DetermineCurrentState();
ProcessCurrentState();
//HandleActionInput();
Debug.Log("Current MoveDirection is " + MoveDirection.ToString());
}//Update()
public void ProcessCurrentState()
{
switch (State) {
case CharacterState.Idle:
anim.Play("idle");
//anim.animationCompleteDelegate = WalkCompleteDelegate;
break;
case CharacterState.WalkingRight:
anim.Play("walking_side_right");
break;
case CharacterState.WalkingLeft:
anim.Play("walking_side_left");
break;
case CharacterState.Jumping:
break;
case CharacterState.Falling:
break;
case CharacterState.Hitting:
break;
}
}//ProcessCurrentState()
#region Actions Method
void WalkCompleteDelegate(tk2dAnimatedSprite sprite, int clipId)
{
if(State == CharacterState.WalkingRight)
anim.Play("walk_side_right");
else if(State == CharacterState.WalkingLeft)
anim.Play("walk_side_left");
else
anim.Play("idle");
}
Thanks for your answers.
Perhaps you could post a code example of your movement routine?
I've edited your question and posted the code there - don't use Answers to post something that isn't a solution (there's a Add New Comment link hidden on the right) and you can edit your question. Don't worry everyone does it the first time :)
@Wolfram - it's the total confusion I had when I had a tick an answer when it wasn't my question that surprised me :-) I think it's a bit odd though - you can delete someone's answer but you can't convert it to a comment... Oh well - it'll be a while before I get 10k...
Answer by whydoidoit · Jun 15, 2012 at 09:06 PM
So this code looks odd to me:
// Getting the targetPosition from the clic
if(Input.GetKeyDown(KeyCode.Mouse0))
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var playerPlane = new Plane(Vector3.forward,CharacterController.transform.position);
float hitdist = 0.0f;
// Detecting the place of hit
if(playerPlane.Raycast(ray,out hitdist))
{
// Position in 3D where the clic was made
targetPosition = ray.GetPoint(hitdist);
targetPoint = (Vector2) (targetPosition - CharacterController.transform.position);
}
}
Why not:
if(Input.GetMouseDown(0))
{
targetPosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, CharacterController.transform.position.z));
targetPoint = (Vector2)(targetPosition - CharacterController.transform.position);
}
Not sure that's your problem - because I'm not totally on top of what you are doing here.
Alright, I've changed to Input.Get$$anonymous$$ouseButtonDown(0), and works like always. The problem with all this, is not if the object is moving, because it can, the problem is that when it moves the animation does not start, my character rise a foot and until he came to the target point the walking animation get played, so for that reason i thought that with a coroutine this could be fixed
By other hand I'm thinking what could happen if i try to use iTween to execute at the same time the movement and the animation
Are you sure it isn't a problem in Deter$$anonymous$$eCurrentState() which I don't believe is in the code you posted.
Answer by alfchee · Jun 19, 2012 at 10:40 AM
Hi! and thanks for all the answers. Making changes here and there, at beginning I thought that if I perform the animation before than the movement, it will work, but that wasn't the solution, so here I post the changes:
TP_Controller
// Stopping our player when reach the target at 0.2 near
if(Vector2.Distance(new Vector2(targetPosition.x,0),new Vector2(CharacterController.transform.position.x,0)) < 0.2f )
{
targetDirection = Vector2.zero;
TP_Animator.Instance.ProcessCurrentState();
}
TP_Animator
void Update()
{
DetermineCurrentDirectionAndState();
HandleActionInput();
}//Update()
void HandleActionInput()
{
if(Input.GetMouseButtonDown(0))
{
TP_Animator.Instance.ProcessCurrentState();
}
}//HandleActionInput()
So in this way the animation gets executed once, and at the same time if the character reaches 0.2 near the destination, the new state of the character is processed. But still I'm not so sure if is right to call the ProcessCurrentState method in the TP_Controller in the way I'm doing, what do you think??
Thanks for all!!
Your answer
![](https://koobas.hobune.stream/wayback/20220613072828im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Animation not working correctly on moving object 1 Answer
Player direction/idle animation 2 Answers
Animation Playback Problem 1 Answer
character animation and movement 1 Answer