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.

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.

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!!