Enhancements in Unit Movement and Pathfinding in RTS Game
Last modified: May 18 2024 18:40:44
This blog post details the recent enhancements made to the unit movement and pathfinding mechanisms in our RTS game, focusing on improvements in navigation and gameplay experience.
Introduction
In this update, we introduce significant improvements to the unit movement and pathfinding mechanisms in our RTS game. These changes aim to make unit navigation more efficient and robust, ensuring a smoother gameplay experience. Let's delve into the modifications and their implications.
ActionSelectionListener Enhancements
In the ActionSelectionListener
class, we made several updates to improve how units handle movement actions:
import github.ac15cr.rts.units.UnitPathFind;
import java.util.List;
private final UnitPathFind unitPathFind;
public ActionSelectionListener(Logger logger, NamespacedKey blockKey, PlayerManager playerManager, GameManager gameManager) {
...
this.unitPathFind = new UnitPathFind();
...
}
We introduced a new UnitPathFind
class to handle pathfinding. This class computes the optimal path for units to reach their destinations while avoiding obstacles.
Furthermore, we modified the block assignment loop and the logic for handling unit movement:
for (int i = 3; i < 6; i++) {
player.getInventory().setItem(i, cancelBlock);
}
...
Location targetLocation = event.getClickedBlock().getLocation().add(0, 1, 0);
...
List<Location> blockPathToGoal = unitPathFind.findPath(selectedUnit.getEntity().getLocation(), targetLocation, selectedUnit.getAttributes().getMoveDistance());
...
if (selectedUnit.getGoal().moveTo(blockPathToGoal)) {
for (int i = 3; i < 6; i++) {
player.getInventory().setItem(i, ItemStack.empty());
}
playerData.setStatus(PlayerStatusEnum.READY);
}
These changes ensure that the cancel block is properly assigned to inventory slots and that units can find and move along valid paths to their destinations.
CustomUnit Class Updates
We made important modifications to the CustomUnit
class to support the new pathfinding logic:
private final UnitGoal goal;
public CustomUnit(Location location, Player owner, UnitType unitType, UnitAttributes attributes, EntityType entityType) {
...
this.goal = new UnitGoal(this);
...
}
...
public UnitGoal getGoal() {
return goal;
}
A new UnitGoal
instance is associated with each unit to manage movement goals and paths.
Introducing UnitGoal Class
The UnitGoal
class is designed to handle the movement goals for units. It integrates with the pathfinder to calculate and execute paths:
import com.destroystokyo.paper.entity.Pathfinder;
import java.util.*;
public class UnitGoal implements Goal<Mob> {
...
private final CustomUnit unit;
private final Pathfinder pathfinder;
private final Queue<Pathfinder.PathResult> paths;
public UnitGoal(CustomUnit unit) {
this.paths = new ArrayDeque<>();
this.unit = unit;
this.pathfinder = ((Mob) this.unit.getEntity()).getPathfinder();
}
public boolean moveTo(List<Location> targets) {
for (Location target : targets) {
Pathfinder.PathResult path = pathfinder.findPath(target);
if (path == null || path.getFinalPoint() != target) {
unit.getOwner().sendMessage(Component.text("Cannot reach that location!"));
paths.clear();
return false;
}
paths.add(path);
}
return true;
}
@Override
public void tick() {
if (pathfinder.hasPath()) return;
if (paths.isEmpty()) return;
pathfinder.moveTo(paths.poll());
}
...
}
This class queues paths for units and ensures they follow the calculated paths, providing a more seamless movement experience.
UnitManager Updates
Finally, we updated the UnitManager
class to integrate the new goal system:
if (Bukkit.getScoreboardManager().getMainScoreboard().getTeam("RTS-Units") != null) {
team = Bukkit.getScoreboardManager().getMainScoreboard().getTeam("RTS-Units");
} else {
team = Bukkit.getScoreboardManager().getMainScoreboard().registerNewTeam("RTS-Units");
}
Objects.requireNonNull(team).setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
...
Bukkit.getMobGoals().addGoal((Mob)customUnit.getEntity(), 0, customUnit.getGoal());
This ensures that units are assigned their respective goals and that collision rules are correctly configured.
Conclusion
These enhancements bring a more reliable and efficient pathfinding system to our RTS game, improving unit movement and overall gameplay experience. Stay tuned for more updates as we continue to refine and expand the game's features.