- Home /
Enemy keeps moving in one direction. Help pls!
Hey, i created a script for an enemy ai and it works... A little bit... It makes the enemy moving in random directions and change them after a short time. The problem is that it does this once and then keeps the direction. What have i done wrong?
MY SCRIPT
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PrototypeBoss1 : MonoBehaviour {
public float moveSpeed;
private Rigidbody2D myRigidbody;
private bool moving;
public float timeBetweenMove;
private float timeBetweenMoveCounter;
public float timeToMove;
private float timeToMoveCounter;
private Vector3 moveDirection;
// Use this for initialization
void Start () {
myRigidbody = GetComponent();
timeBetweenMoveCounter = timeBetweenMove;
timeToMoveCounter = timeToMove;
}
// Update is called once per frame
void Update () {
if (moving)
{
timeBetweenMoveCounter -= Time.deltaTime;
myRigidbody.velocity = moveDirection;
if(timeToMoveCounter < 0f)
{
moving = false;
timeBetweenMoveCounter = timeBetweenMove;
}
}
else
{
timeBetweenMoveCounter -= Time.deltaTime;
myRigidbody.velocity = Vector2.zero;
if(timeBetweenMoveCounter < 0f)
{
moving = true;
timeToMoveCounter = timeToMove;
moveDirection = new Vector3(Random.Range(-1f, 1f) moveSpeed, Random.Range(-1f, 1f) moveSpeed, 0f); }
}
}
}
Add some debug logs on your moveDirection and see if they are actually changing. I suspect it might not be.
P.S. Try to use the code sample next time, your code is horrible to follow without formatting.
Answer by AdityaViaxor · Jul 21, 2018 at 12:22 PM
i think i got the solution in the else section you assign " timeToMoveCounter = timeToMove;" but you neither decreasing timeToMove nor decreasing timeToMoveCounter so in first if case the compiler doen't enter to
if(timeToMoveCounter < 0f)
{
moving = false;
timeBetweenMoveCounter = timeBetweenMove;
}
so it never goes to else condition ever again and it move in one direction.
plz accept answer it helps you
thank you
i removed the "timeBetween$$anonymous$$oveCiunter = timeBetween$$anonymous$$ove;" nothing changed
Answer by kalen_08 · Jul 19, 2018 at 09:57 PM
So here's the deal. you reduce the same counter for both sections even though you're only testing the value of 1, meaning that the other one will not change. here's your fixed code:
void Update ()
{
if (moving)
{
//you had : timeBetweenMoveCounter -= Time.deltaTime;
timeToMoveCounter -= Time.deltaTime;
myRigidbody.velocity = moveDirection;
if (timeToMoveCounter < 0)
{
moving = false;
timeToMoveCounter = timeToMove;
}
}
else
{
timeBetweenMoveCounter -= Time.deltaTime;
myRigidbody.velocity = moveDirection;
if (timeToMoveCounter < 0)
{
moving = false;
timeBetweenMoveCounter = timeBetweenMove;
moveDirection = new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized;
}
}
}
My Solution (which i think is a little cleaner and less likely to make the same mistake as yours.
public class PrototypeBoss1 : MonoBehaviour
{
// public variables/references
public float moveSpeed;
public float moveForSeconds;
public float waitForSeconds;
// private variables
float timeSince = 0f;
bool moving;
// private components
Rigidbody2D myRigidbody;
// MESSAGES
void Start ()
{
myRigidbody = GetComponent<Rigidbody2D>();
}
void Update ()
{
// my way of doing it (remove the comments and its a lot less
// update the time since direction changed || stopped moving
timeSince += Time.deltaTime;
if (moving)
{
// if moving, then if we've been moving for moveForSeconds
// or longer then stop moving, reset the timeSince and
// set rigidbody velocity to 0
if(timeSince >= moveForSeconds)
{
moving = false;
timeSince = 0;
myRigidbody.velocity = Vector2.zero;
}
}
else
{
// if we are stopped and have been stopped for waitForSeconds
// or longer then reset timeSince, and set a velocity in a new direction.
if(timeSince >= waitForSeconds)
{
moving = true;
timeSince = 0;
var newDirection = new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized;
myRigidbody.velocity = newDirection * moveSpeed;
}
}
}
}
I still think that if you're going to be expanding the logic then CoRoutines are the best way to go. (i've used them for this exact purpose and they're not very difficult in fact maybe more simple.) Here is how i would still do it :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMovement : MonoBehaviour {
[SerializeField] float moveTime = 1;
[SerializeField] float waitTime = 1;
[SerializeField] float moveSpeed = 1;
Rigidbody2D myRigidbody;
void Start () {
myRigidbody = GetComponent<Rigidbody2D> ();
StartCoroutine(Movement());
}
IEnumerator Movement ()
{
while (true)
{
print("moving");
//move
var direction = new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f)).normalized;
myRigidbody.velocity = direction * moveSpeed;
yield return new WaitForSeconds(moveTime);
//wait
myRigidbody.velocity = Vector2.zero;
print("stopped");
yield return new WaitForSeconds(waitTime);
}
}
}
Nope it absolutly doesn't work.
I need a skript that makes my enemie to move random and if he sees me he attacks me.
Your answer
Follow this Question
Related Questions
Looping Between Waypoints 1 Answer
How do I implement A* pathfinding to my 2d game, without tiles? 4 Answers
2D AI, Aim at player - even when jumping? 1 Answer
Enemy AI problems 2 Answers
EnemyAI C# Error 1 Answer