Working on methods for grid movement

Hi guys! Continuing with my roguelike, I stumbled upon grid movement for the player, using a bit of code from Robertbu, mixed in with some of my own code, which works perfectly. I duplicated the code for the AI, with some minor changes. However, the AI doesn’t move the way I need it to. Rather than moving precise grid units, the AI sometimes stops off centre. I looked through my code and I can’t find an exact reason as to why this isn’t working.

This is the code for the spawner of the monsters.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class basicmob : MonoBehaviour {
	public List<GameObject> moblist = new List<GameObject>();
	public GameObject mob;	
	public static int monsters;
	public GameObject newspawn;
	public static bool cleared;
	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		

		if(ControllerScript.counter>=5   monsters<10  !ControllerScript.moving){
			GameObject[] mobPosition;
			mobPosition= GameObject.FindGameObjectsWithTag("room");
			var mobPlace=Random.Range(0,mobPosition.Length);
			Transform target= mobPosition[mobPlace].transform;
		    newspawn=(GameObject)Instantiate(mob, target.position+(Vector3.up/2), target.rotation);
			moblist.Add(newspawn);
			ControllerScript.counter=0;
			monsters++;
		}
		if(overseer.nextfloor){
			moblist.Clear ();
		}
			if(ControllerScript.nextturn  moblist.Count>0){
				foreach(GameObject monster in moblist){
					var script=monster.GetComponent<Mobhelper>();
					script.turnProcedure();
				}
	}
}
}

and the code for the monsters themselves

sing UnityEngine;
using System.Collections;


public class Mobhelper : MonoBehaviour {
	private float speed=1.0f;
	public GameObject player;
	private Vector3 mobEnd;
	private bool mobMove;
	void Start(){
	}
	
	void Update(){
	}
	
	public void turnProcedure(){
		patrol();
	}
	void patrol(){
		 bool hittingForward=false;
       if(Physics.Raycast(transform.position, Vector3.forward, 1)){
         hittingForward=true;
       }
         bool hittingRight=false;
       if(Physics.Raycast(transform.position, Vector3.right, 1)){
         hittingRight=true;
       }
         bool hittingLeft=false;
       if(Physics.Raycast(transform.position, Vector3.left, 1)){
         hittingLeft=true;
       }
         bool hittingBackwards=false;
       if(Physics.Raycast(transform.position, -Vector3.forward, 1)){
         hittingBackwards=true;
       }
		
 		var chance=Random.Range (0,5);

       if (mobMove  (transform.position == mobEnd)){
         mobMove = false;
			ControllerScript.nextturn=false;
         }
       if(!mobMove  chance==1  hittingForward==false){
        mobMove = true;


         mobEnd = transform.position + Vector3.forward;
       }
       if(!mobMove  chance==2  hittingRight==false){
         mobMove = true;


         mobEnd = transform.position + Vector3.right;
       }
       if(!mobMove  chance==3  hittingLeft==false){
         mobMove = true;

         mobEnd = transform.position + Vector3.left;
       }
       if(!mobMove  chance==4  hittingBackwards==false){
         mobMove = true;

         mobEnd = transform.position - Vector3.forward;
       }
       transform.position = Vector3.MoveTowards(transform.position, mobEnd, Time.deltaTime * speed);
		}
	}

the weirdest thing about the result is that the AI moves slower than the player, despite that the speed variables are the same.

Is there a reason as to why the above things I mentioned are happening, or is there a better way to go about this.

I wasn’t sure whether or not to put this in unity answers, since it’s technically more than one question.

I’m working in c#

Thanks.

I wouldn’t use things like Physics.Raycast in a grid-based Roguelike game. It’s both too complex, and probably less precise than you need. Just make a 2D array that keeps track of what’s in each square of the world, and use that for your collision detection. Update this map whenever an agent (whether player, monster, or whatever) starts to move — that way, other things can immediately move into the square they’re vacating, and conversely, nothing else will move into the same square they’re moving into.

HTH,

  • Joe

That’s pretty interesting. I had seen similar posts on answers about it, but i’m not sure how you would use an array to represent the world. Is it like making a grid, and filling it with objects, where the array is the grid? If so, how do you make a grid out of a 2d array?

Hmm, I’m not sure I understand your question. You just need a data structure that represents what is where in the world. If it’s a 2D world, then you need a 2D data structure… that’s an array. For example:

  const int kWorldSize = 128;
  static int[,] worldMap = new int[kWorldSize, kWorldSize];

There’s your array representing the world as a bunch of integers. You could define 0 to mean “empty”, 1 to mean “wall”, 2 to mean “treasure chest”, and so on, including a unique value for each type of monster and another value for the player.

Even better would be to use an enum rather than an integer, but either way is fine.

Now, a position in the world is represented by two numbers; let’s call 'em x and y. What’s in the world at that position is worldMap[x,y]. If you want to change what’s in the world at that position, you assign a new value to worldMap[x,y].

All this is the “model” of your game, i.e., the abstract representation of it, entirely separate from the “view” which is the actual scene graph displayed on screen. Now that I think about it, I bet your confusion stems from being led down the dark side by Unity’s scene-oriented approach. In most cases, for beginners, I think the Dark Side is fine, but for a roguelike game, it is quickly going to end up being a LOT more work than cleanly separating the model and view from the get-go.

So, assuming you buy into this whole model/view separation, what’s needed is a “controller” with that keeps them in sync. This isn’t too hard. It should have methods to:

  1. Generate game objects for all the objects in the map. You just zip through worldMap with a couple of nested for-loops, and instantiate and position the appropriate prefab for each entry therein.

  2. Move an object in both the scene graph and the world map. As noted previously, it should update the world map array with the destination right away, but fire off some MonoBehaviour to animate the movement in the scene graph over 0.5 seconds or whatever.

  3. Add an object to both the scene graph and the world map. Easy peasy.

  4. Remove an object from both the scene graph and the world map. Again pretty easy.

The only challenging part here is that the controller must always be able to find the GameObject that corresponds to a given world position, and vice versa. I might suggest another 2D array of GameObject, which does the former, and a Dictionary<GameObject, Vector2> which does the latter.

While none of this is terribly complicated, it may seem so if you’re new to programming in general… I have no idea what your background is, and whether I’m belaboring simple points or setting you up for a challenge. I’m confident you can do it, though, if you stick to it. And learning this model/view/controller separation is likely to serve you well in the future. However, if it all seems complex and you start to despair, just ignore me and embrace the Dark Side. It will lead to its own challenges, and you’ll spend a lot more time on play-testing in the long run, but it too can be made to work.

I think I can understand that. I wish I knew a bit more about this before I started, but what’s done is done I guess. Thanks for being patient with me, since I don’t have much of a coding background at all. Thanks for your help and happy 2014!

Hi JoeStrout,

Apologies for rooting this old post up, I’ve recently been researching the best approach for grid movement, and your suggestion does resonate as the proper solution I’ve been thinking about as well. You’re suggesting using 3 data structures to represent the MVC pattern. However, something that I’m confused on, is why do you need ‘two’ data structures to represent the model and the scene graph? Couldn’t you just do away with the 2D array for the model, and use the 2D array that you are using to represent your scene graph? Since it is essentially a 2D array listing each object in its appropriate location? Why the need for an INT representation of the same information? e.g. (1=enemy, 2=block, etc)

I’m just asking because I’m trying to think through the process myself and was wondering if the ‘model’ array is even needed.

I’ve recently completed the “2D roguelike” tutorial on this website, and and found that while it is an invaluable resource for a beginner/intermediate trying to learn Unity, I didn’t like the raycasting approach for grid movement either, and found it limiting when I attempted to expand on the project.

Thanks for any response you can give to this (old) post!

I don’t think there were ever 3 data structures. The idea was the model (data) would be one structure that was simply an array of ints stating what was where. The view would be some other data structure of objects to display that data (maybe ascii characters, maybe 3d models)… but in our case most likely an array of gameObjects that have spriteRenders and maybe Animations attached to them.

The 3rd Component the Controller would just be a set of methods and fields that run the model data, retrieve it and send it to the view data. Now you could easily just incorporate the model and view together but then you’d be ruining the point of MVC. What if down the road you wanted to change from a topdown 2D sprite world , to some 3rd person 3D view. It would be a pain to rework it all. If you kept the model separate, your game would run exactly as it always did you would just add a new set of graphics objects that the controller talks to.

1 Like

No… it’s “one” data structure for the model, and another (possibly Unity’s scene graph) for the view.

As @takatok , said, that’s mixing the model and view together. Yes, it could work, but it tends to lead to pain. Particularly since Unity’s scene graph is not a 2D array.

But as always, you should do what makes the most sense to you in your situation. If it leads to pain, go back and refactor it (or if it’s hopeless, throw it out and start again, older and wiser than before).

Best,

  • Joe

thanks for both your responses. This is helpful. I agree and think this is the best approach, but having not tried it yet, i couldn’t help think “why not just use the array of GameObjects as your model”, and its good to know the pitfalls before diving down that path! I’ll give it a try with a proper MVC pattern.