0
\$\begingroup\$

Trying to create a 2d Top down random movement. I have the blendtree setup so that it faces the sprite in the right direction. However, I can't get it move right. It just flips back and forth between directions never moving. Unless I use the RidgidBody2d apply force then it just slowly convulses to 0,0.

I guess I wanted it walk in one direction base cardinal direction (no angles) for 3 seconds then change direction.

What Am I doing wrong?

public float moveSpeed = 0.75f;
 public Animator anim;
 public Rigidbody2D body;

 private Vector2 enemyMovement;


 void Start () {
     anim = GetComponent<Animator> ();
 }


 void Update () {
     Invoke("randomDirection", 1);
     transform.position = new Vector3(enemyMovement.x,enemyMovement.y,0) * moveSpeed * Time.deltaTime;

     //TRIED THIS TOO
     //body.AddForce (enemyMovement);
 }

 void randomDirection() {
     switch(Random.Range (0,3)){
         case 0:
             Debug.Log ("Moving enemy Up");
              enemyMovement = new Vector2 (0,1);
             break;
         case 1:
             Debug.Log ("Moving enemy Right");
              enemyMovement = new Vector2 (1,0);
             break;
         case 2: 
             Debug.Log ("Moving enemy Down");
              enemyMovement = new Vector2 (0,-1);
             break;
         case 3:
             Debug.Log ("Moving enemy Left");
              enemyMovement = new Vector2 (-1,0);
             break;
         default:
              enemyMovement = new Vector2 (0,0);
             break;
     }

 }
\$\endgroup\$
1
  • \$\begingroup\$ You are using enemyMovement as a postion, not a velocity. You add a velocity to current position for the position to change. \$\endgroup\$
    – Almo
    Commented Feb 19, 2016 at 15:23

2 Answers 2

0
\$\begingroup\$

Although you did mark it as answer, but now this code will work 100% correct.

Couple of things are here.

First of all you are calling Invoke in Update. Which means Invoke is executing 60 times per second. That is weird. Instead of that make a Coroutine that will executes every second.

Try the below code,

 public float moveSpeed = 0.75f;
 public Animator anim;
 public Rigidbody2D body;

 private Vector2 enemyMovement;


 void Start () {
     anim = GetComponent<Animator> ();
     StartCoroutine("ChangeDirection");
 }


 void Update () {
     //Invoke("randomDirection", 1);


     transform.position += new Vector3(enemyMovement.x,enemyMovement.y,0) * moveSpeed * Time.deltaTime;

     //TRIED THIS TOO
     //body.AddForce (enemyMovement);
 }

 IEnumerator ChangeDirection()
 {
     while(true){
         yield return new WaitForSeconds(1.0f);
         RandomDirection();
     }
 }

 void RandomDirection() {
     // HAMZA's: Now I'm sure it will work :)
     switch(Random.Range (0,4)){
         case 0:
             Debug.Log ("Moving enemy Up");
              enemyMovement = new Vector2 (0,1);
             break;
         case 1:
             Debug.Log ("Moving enemy Right");
              enemyMovement = new Vector2 (1,0);
             break;
         case 2: 
             Debug.Log ("Moving enemy Down");
              enemyMovement = new Vector2 (0,-1);
             break;
         case 3:
             Debug.Log ("Moving enemy Left");
              enemyMovement = new Vector2 (-1,0);
             break;
         default:
              enemyMovement = new Vector2 (0,0);
             break;
     }

 }
\$\endgroup\$
8
  • \$\begingroup\$ Do you mean 'StartCoroutine("ChangeDirection");' \$\endgroup\$
    – user-44651
    Commented Feb 19, 2016 at 15:29
  • 1
    \$\begingroup\$ it is ok to call randomDirection. If you call every frame changeDirection without waiting the enemy to reach final position the system goes through an umpredictable loop \$\endgroup\$
    – Leggy7
    Commented Feb 19, 2016 at 15:33
  • \$\begingroup\$ This slowed him down. But he never actually moves. He just jumps to 0,0 and faces the direction every second. So that's a step in the right direction! @hamza-hasan \$\endgroup\$
    – user-44651
    Commented Feb 19, 2016 at 15:33
  • \$\begingroup\$ change the update to transform.position += new Vector3(enemyMovement.x,enemyMovement.y,0) * moveSpeed * Time.deltaTime; \$\endgroup\$
    – Leggy7
    Commented Feb 19, 2016 at 15:51
  • \$\begingroup\$ Instead of putting IEnumerator in an infinite loop, i think one can simply put InvokeRepeating in the Start() method to do the job. It looks more elegant and you can stop the invoking instantly with CancelInvoke instead of waiting for the next yield instruction. \$\endgroup\$ Commented Feb 19, 2016 at 15:51
0
\$\begingroup\$

Well, you change the movement vector every frame. Invoke just adds one second delay to the call, but you still call it every frame. You could do

 if(!IsInvoking("randomDirection"){
    Invoke("randomDirection",1);
 }

This way you only schedule a new change if the last one is done. But in my opinion you should not be using Invoke, it leads to very unreadable code. Make a timer yourself like this:

float remainingTime=0;
void Update(){
    remainingTime -= Time.deltaTime;
    if(remainingTime <0f){
       remainingTime=1f;
       randomDirection();
    }
    //Move code as you did.
}
\$\endgroup\$
1
  • \$\begingroup\$ Why are you putting this burden in Update? while you have invoke and coroutine? any reason for this extra calculations? \$\endgroup\$ Commented Feb 19, 2016 at 20:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .