- Home /
Pathfinding in a Grid-Based RPG... Theorycrafting and solution.
I am working on a Grid-Based title similar to Legend of Grimrock and/or Eye of the Beholder. In terms of pathfinding, I have gone through many issues as of lately.
My enemy has a wander AI which is very incomplete and only for testing purposes; I will implement a second-based AI later (this will be clear when you see the script below).
I tried using A*, but it merely causes the enemy to drag along, and not move in a grid. I had a script that rounded the current position to a whole number, which is the basic grid my game runs on. That worked to an extent; however, the enemy just dragged on without rotating at corners or going through his normal movement behavior.
Is there any way I can have the enemy move in a grid-based functionality, tracking down the player dynamically, and rotating at corners/rotating to face him?
Thanks in advance! :D
Enemy movement script (with wander AI(As you can see, the FoundPlayer method is empty as I have no clue what to do :P)):
using UnityEngine;
using System.Collections;
public class EnemyMovement : MonoBehaviour {
public static bool CanMoveForward;
public bool FoundPlayer;
//Translation:
float movSpeed = 4.0f;
Vector3 pos;
Transform tr;
public static bool moving = false;
//Rotation:
public static bool rotating = false;
public float rotSpeed = 360f;
float rotDegrees = 0f;
Quaternion rotToAngle ;
void Start () {
pos = transform.position;
tr = transform;
CanMoveForward = true;
FoundPlayer = false;
}
void MoveTowardsPlayer() {
return;
}
// Update is called once per frame
void Update () {
int randomValue = Random.Range (1, 100);
Debug.DrawRay(transform.position, transform.forward, Color.red);
if (!moving && !rotating && !FoundPlayer) {
if (randomValue == (1 | 2) && tr.position == pos && CanMoveForward) {
pos += transform.forward;
moving=true;
}
else if (randomValue == 5 && tr.position == pos) {
rotDegrees -= 90f;
rotToAngle = Quaternion.Euler(0, rotDegrees, 0);
rotating = true;
}
else if (randomValue == 6 && tr.position == pos) {
rotDegrees += 90f;
rotToAngle = Quaternion.Euler(0, rotDegrees, 0);
rotating = true;
}
} else if (FoundPlayer) {
MoveTowardsPlayer();
}
//Translation:
if (moving) {
if (Vector3.Distance(transform.position,pos) <0.05f){
transform.position = pos;
moving=false;
// print ("FINISHED MOVE");
} else {
transform.position = Vector3.MoveTowards(transform.position, pos, Time.deltaTime * movSpeed);
}
}
//Rotation:
if (rotating) {
if (Quaternion.Angle(transform.rotation,rotToAngle) <10f) {
transform.rotation = rotToAngle;
rotating=false;
// print ("FINISHED TURN");
} else {
transform.rotation = Quaternion.RotateTowards(transform.rotation, rotToAngle, rotSpeed * Time.deltaTime);
}
}
}
}
:D
Note we used the unity Built in navmesh. This is a short script from our project i isolated some of its code what we did was to add time delay on each move to simulate a grid move.. and just add a corner waypoint so when the player is on a 90 degree angle it will look for the corner gameobject with the AI raycast ins$$anonymous$$d of looking at the player directly.. note this isn't perfect but i do hope you get the idea well i did based on the game you mentioned.
private Nav$$anonymous$$eshAgent agent; public Transform Target;//the player public Nav$$anonymous$$esh nav$$anonymous$$esh; public Transform Corner;//private // no need to assign this it assigns it self private Color c = Color.white; // Use this for initialization void Start () { agent = GetComponent(); }
// Update is called once per frame
void Update () {
if(Corner!=null&&agent.remainingDistance>1){
agent.SetDestination(Corner.position);
}
else if(agent.remainingDistance<0.1F){
agent.SetDestination(Target.position);
StartCoroutine( DelayStep() );
}
else if(Corner==null){
agent.SetDestination(Target.position);
}
getPath();
}
private IEnumerator DelayStep()
{
// process pre-yield
//agent.angularSpeed =0;
yield return new WaitForSeconds( 1f );
agent.speed=0F;
yield return new WaitForSeconds( 1f );
// process post-yield
agent.speed =3.5F;
}
void getPath(){
DrawPath(agent.path);
}
void DrawPath(Nav$$anonymous$$eshPath path) {
if (path.corners.Length < 2)
return;
switch (path.status) {
case Nav$$anonymous$$eshPathStatus.PathComplete:
c = Color.white;
break;
case Nav$$anonymous$$eshPathStatus.PathInvalid:
c = Color.red;
break;
case Nav$$anonymous$$eshPathStatus.PathPartial:
c = Color.yellow;
break;
}
Vector3 previousCorner = path.corners[0];
int i = 1;
while (i < path.corners.Length) {
Vector3 currentCorner = path.corners[i];
Debug.DrawLine(previousCorner, currentCorner, c);
previousCorner = currentCorner;
i++;
}
RaycastHit hit;
if (Physics.Linecast ( path.corners[0], path.corners[1],out hit)) {
//print (hit.transform.name);
Corner= hit.transform;
}
}
Answer by Cherno · Jan 17, 2015 at 03:30 PM
I recommend Aron Granberg's Astar Pathfinding Project. It supports Grid Graphs and also runtime graph updating. It should be perfect for your needs.
The problem is rotating at corners... And I also mentioned, I used A* and it did not work out :/
You said you used A*, which is the underlying algorithm. The Astar Pathfinding Project is a specific asset that implements this algorithm. Did you use this asset? If yes, what exactly is the problem with rotating at corners? I can see no way why it wouldn't work with a Grid Graph. Every tile has one node and since movement is restricted to horizontal and vertical neighbors, turning before moving on is trivial.
It's a great asset, and he has his own dedicated forum. The free version would do what you want. You can find his forum here if you decide on using the asset.
(also +1 for the Aron reference)
How would I have the enemy move one block at a time, and pause to rotate 90 degrees at corners?
I think the AstarAI script is a good start, or AIFollow (I hope those two scripts are still included in the latest APP version). The main thing for a beginner is to try and follow the process of the pathfinding; How a path is called, what happens when the path is ready (OnPathComplete()), and what happens in OnPathComplete() -> $$anonymous$$oving from waypoint to waypoint until the last one is reached, and moving on to the next one everytime the nextWayPointDistance is reached
Your answer
![](https://koobas.hobune.stream/wayback/20220613180704im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
AI teleporting 1 Answer
Pathfinding unity 3 Answers
I need help to save my grid and show it in a different scene 2 Answers