2d Roguelike - enemy chase after me

Hello !
So, I’m a beginner with c# and Unity engine. I’m working on a roguelike project without the procedural generation of dungeon, just a map with some spawnpoint. Everything work but I’m unable to make my prefab come after me in a range of 5 squares around them(320 pixels → 1 grid = 64px). The system is turn per turn, and the debug show that the mob move on their turn(in their dream maybe, because they stay at the same place during playmode), had their turn, etc. I added some damage possibility and they effectively damage me without even being near me and the debug confirmed it. So, how ? They don’'t attack when I’m near them on x or y axis but from their position as son as I start an action, which mean at my very first move after starting the playmode.
Here you can see my Enemy Behaviour logic, without the damage logic(I suppress it to put it in another script later):

Here you can see my Enemy Behaviour logic, without the damage logic(I suppress it to put it in another script later):

Here you can see my Enemy Behaviour logic, without the damage logic(I suppress it to put it in another script later):

<>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyBehavior : MonoBehaviour
{
public float detectionRange = 320f;
public float moveDistance = 64f;
public int health = 100;
public float speed = 2f;

private Transform player;

private void Start()
{
    player = GameObject.FindGameObjectWithTag("Player").transform;
}

public void TakeTurn()
{
    float distanceToPlayer = Vector2.Distance(transform.position, player.position);

    if (distanceToPlayer <= detectionRange)
    {
        MoveTowardsPlayer();
    }
}

private void MoveTowardsPlayer()
{
    Vector2 direction = (player.position - transform.position).normalized;

    direction = new Vector2(Mathf.Round(direction.x), Mathf.Round(direction.y)) * moveDistance;

    Vector2 targetPosition = (Vector2)transform.position + direction;

    Collider2D hitCollider = Physics2D.OverlapCircle(targetPosition, 0.1f);
    if (hitCollider == null || hitCollider.CompareTag("Player"))
    {
        transform.position = targetPosition;
    }
}

}

<>

And here you can also see the EnemyManager script :

<>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyManager : MonoBehaviour
{
public static EnemyManager Instance;

void Awake()
{
    if (Instance == null)
    {
        Instance = this;
    }
    else
    {
        Destroy(gameObject);
    }
}

public void TakeTurn()
{
    GameObject[] enemyObjects = GameObject.FindGameObjectsWithTag("enemy");

    foreach (GameObject enemyObject in enemyObjects)
    {
        EnemyBehavior enemy = enemyObject.GetComponent<EnemyBehavior>();
        if (enemy != null)
        {
            enemy.TakeTurn();
        }
    }
}

public void OnPlayerMoved()
{
    TakeTurn();
}

}

<>

I created a enemy tag on my prefabs and they are linked to the behaviour script. The EnemyManager group the list of the enemies and the spawn are working normally, they just don’t make any move… I Just want that when I enter in a 5 cases perimeter around them, they chase after me.

I know about the unity roguelike tutorial but I was trying to make it by myself without just remake another tutorial.

Hi @sainthorlogerie,

You’ve tagged this thread with the Behavior tag but that’s for the Behavior package which doesn’t seem like you’re using here. Perhaps replace the tag with Scripting or Getting Started instead as you might get more help there?

Hi, thank you ! I thought it was “behaviour” for “AI behaviour”, my bad, I’m sorry !

No worries :slight_smile: Good luck! You might find the Behavior package useful for this any way as it’s a behavior tree tool to make game AI :slight_smile:

Do NOT do this sort of thing in a grid game because you make it about 1000x harder on yourself:

Tile-based / grid-based 2D games: match3, tetris, chips challenge, rogue, etc:

For any tile-based game such as Match3 or Tetris or a grid-based Roguelike, do all the logical comparisons in your own data storage mechanism for the tiles, such as a 2D array of tiles.

Otherwise you needlessly bind your game logic into Unity objects and the Unity API, making it about 10x more complicated than it needs to be.

If you have no idea how to work with 2D arrays, hurry to some basic C# tutorials for the language portions of it, then look at any good tutorial that uses a 2D array

Here is my Match3 demo using this technique of storing data in a grid. Full source linked in game comments.

It stores all of its data in a 2D array:

PieceController[,] Board;

This allows for easy simple checking in code, not relying on anything like physics.

You should strive to use that pattern for all logic, then only use Unity to present what is happening in the game logic.

Sounds like you wrote a bug… and that means… time to start debugging!

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

ALSO: just a quick glance at your EnemyManager tells me it is a defective singleton.

Some super-simple Singleton examples to take and modify:

Simple Unity3D Singleton (no predefined data):

Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance

Alternately you could start one up with a [RuntimeInitializeOnLoad] attribute.

There is never a reason to drag a GameObject into a scene if it will be DontDestroyOnLoad.

If you do:

  • you may drag it into something else that isn’t DDOL. FAIL
  • you may drag something else into it that isn’t DDOL. FAIL

Just DO NOT drag anything into a scene that will be marked DontDestroyOnLoad. Just Don’t Do It!