Godot Version
Godot 4.6 (.NET)
Question
Hi!
I’ve been trying to create a grid-based turn-based movement system on a TileMapLayer using a NavigationAgent2D node on my enemy scene.
As of now they correctly move on all 8 sides looking for the player, and when they reach it they use their turn to attack.
Everything’s great up until I decide to create another instance of the aforementioned enemy. They both work properly, but there are situations where they overlap each other.
Specifics:
- I’m using the Navigation Layers property of the TileMapLayer to ensure the enemy won’t walk on water or terrain, this works just fine as of now.
- If there’s anything else I need to add to the info, feel free to ask!
- I’ve started coding less than a month ago, so feel free to point any newbie mistake.
Here’s the code I’m using for the enemy:
using Godot;
using System;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
public partial class BlueBlob : CharacterBody2D
{
// Area used to check wether the player is in range for attack
public Area2D attackArea;
// X-axis value to which the enemy is going to move
public double valueToLerpX;
// Y-axis value to which the enemy is going to move
public double valueToLerpY;
// Future check on wether this lil thing can walk on water or walls (as of now, not used, I am aware)
public bool canThisMonsterWalkThroughWater = false;
public bool canThisMonsterWalkThroughWalls = false;
// Movement animation
public Tween tween;
// Point to reach (attached to the enemy)
public NavigationAgent2D navigator;
public void EnemyMovement()
{
// Check wether the enemy wants to move diagonally and sets the right path
if (Position.X < navigator.GetNextPathPosition().X)
{
valueToLerpX = Position.X + NewPlayer.tileSize;
}
else if (Position.X == navigator.GetNextPathPosition().X)
{
valueToLerpX = Position.X;
}
else {valueToLerpX = Position.X - NewPlayer.tileSize;}
if (Position.Y < navigator.GetNextPathPosition().Y)
{
valueToLerpY = Position.Y + NewPlayer.tileSize;
}
else if (Position.Y == navigator.GetNextPathPosition().Y)
{
valueToLerpY = Position.Y;
}
else { valueToLerpY = Position.Y - NewPlayer.tileSize;}
//
if (!attackArea.OverlapsArea(NewPlayer.playerArea))
{
// Movement animation
tween = CreateTween();
tween.TweenProperty(this, "position", new Godot.Vector2((float)valueToLerpX, (float)valueToLerpY), 0.4f);
}
else
{
tween = CreateTween();
tween.TweenProperty(this, "position", Position, 0.4f);
NewPlayer.HP = NewPlayer.HP - 5;
}
}
public override void _Ready()
{
navigator = GetNode<NavigationAgent2D>("NavigationAgent2D");
attackArea = GetNode<Area2D>("AttackCheckArea");
tween = CreateTween();
tween.TweenProperty(this, "position", Position, 0.4f);
valueToLerpX = Position.X;
valueToLerpY = Position.Y;
EventManager.enemiesInLevel++;
}
public override void _PhysicsProcess(double delta)
{
// Sets target (the player)
navigator.TargetPosition = NewPlayer.playerTarget;
// Enemy movement if it's their turn and not all enemies have played yet
if (NewPlayer.isPlayerTurn == false && EventManager.enemiesTurns < EventManager.enemiesInLevel)
{
EnemyMovement();
EventManager.enemiesTurns++;
}
// if all enemies have reached their position, stops their turn
if (tween.IsRunning() == false)
{
NewPlayer.isPlayerTurn = true;
}
}
}
}
And here’s the situation for the Enemy scene and the NavigationAgent2D:
My Questions:
- Is there a way to avoid these enemies overlapping each other on the same cell? I’d like to avoid doing this through code alone directly on the Character since it’s bug-prone, I’d rather code on the NavigationAgent (or the NavigationObstacles? I’d think they are supposed to be used this way, but I couldn’t manage to make them work).
- Am I supposed to use the avoidance system on the NavigationAgent? Again, I’ve tried messing with it for a couple hours but to no avail.
- Looking for ways to solve this problem I’ve read about the AStarGrid2D system, am I correct assuming this is the same as AStar Edgebased system? Is it something else entirely?

