adding collision detection to GridMove script

Hi - I’ve been trying to build scene that resembles a very simplistic version of the old top down gameboy games like pokemon; and am using the GridMove script (http://www.unifycommunity.com/wiki/index.php?title=GridMove) for movement

My character moves around correctly, but goes straight through walls and other objects, if I attach a script like the standard FirstPerson Controller it is fine, but doesen’t move how I would like

Would someone be able to help me with scripting this? Something which means the character stops when colliding with an object.

Any help would be greatly appreciated☆

I’m new to Unity, so I can only generally tell you what you would need to do. Don’t know if it will help or not. Assuming you don’t allow corners. You need to do a horizontal raycast and a vertical raycast in the GetAxis function if there is a horizontal or vertical movement call from input, so this is one more condition for the if statement in that function. In pseudo code:
if(input.x > 0 raycast test in x direction is true) input.x = 0;
if(input.x < 0 raycast test in -x direction is true) input.x = 0;
if(input.y > 0 raycast test in y direction is true) input.y = 0;
if(input.y < 0 raycast test in -y direction is true) input.y = 0;
if (Mathf.Abs(input.x) > Mathf.Abs(input.y))
input.y = 0.0;
else
input.x = 0.0;

So you would need to work out the true raycast test in javascript and replace that pseudocode with it.

The other alternative would be to use a grid map. This is a 2 dimensional array with 1’s or 0’s. If it’s marked with a 1, then that means it’s not walkable. So you would do that test according to the object position on the map before moving.

Thanks a lot for your reply - a grid map system would actually be exactly what I was after!

Do you have any idea how to go about it?
I had a look at the 2D Shooter tutorial, but I would like something I could edit directly in the UI〜

Any help is again, extremely appreciated☆

Instead of raycasting, you can convert the GridMove.js to use the character.controller.move function.
(I apologize for raising a necro topic, but this is exactly what I am doing and I hope it helps people in the future.)

private var moveDirection : Vector3 = Vector3.zero;

function Start () 
{
	//needed to move character controller so we collide with colliders in scene
	var controller : CharacterController = GetComponent(CharacterController) as CharacterController;

    var myTransform = transform;

    var startPosition : Vector3;
    var endPosition : Vector3;
    var t : float;
    var tx : float;
    var moveSpeed = walkSpeed;
    
    while (true) {
        while (input == Vector2.zero) {
            GetAxes();
            tx = 0.0;
            yield;
        }
        
        startPosition = myTransform.position;
        endPosition = gridOrientation == Orientation2.Horizontal?
            Vector3(Mathf.Round(myTransform.position.x), 0.4, Mathf.Round(myTransform.position.z)) +
            Vector3(System.Math.Sign(input.x)*gridSize, 0.4, System.Math.Sign(input.y)*gridSize)
            :
            Vector3(Mathf.Round(myTransform.position.x), Mathf.Round(myTransform.position.y), 0.0) +
            Vector3(System.Math.Sign(input.x)*gridSize, System.Math.Sign(input.y)*gridSize, 0.0);
        t = tx;
        while (t < 1.0) {
            moveSpeed = Input.GetButton("Run")? runSpeed : walkSpeed;
            t += Time.deltaTime * (moveSpeed/gridSize) * (correctDiagonalSpeed  input.x != 0.0  input.y != 0.0? .7071 : 1.0);
            //myTransform.position = Vector3.Lerp(startPosition, endPosition, t);
			//Above line uses translation to move object, below uses character controller
			// based on input vector2 directions.

			if ( input == (Vector2(1.0, 0.0))) //right
			{
				moveDirection = (Vector3(1.0, 0.0, 0.0));
			}
			if ( input == (Vector2(-1.0, 0.0))) //left
			{
				moveDirection = (Vector3(-1.0, 0.0, 0.0));
			}
			if ( input == (Vector2(0.0, 1.0))) //up
			{
				moveDirection = (Vector3(0.0, 0.0, 1.0));
			}
			if ( input == (Vector2(0.0, -1.0))) //down
			{
				moveDirection = (Vector3(0.0, 0.0, -1.0));
			}
			controller.Move (moveDirection);
            yield;
        }
        tx = t - 1.0;
        GetAxes();
    }
}

So you just comment out the “myTransform.position = Vector3.Lerp(startPosition, endPosition, t);” line,
and put cases for dependency on which input comes in. This way all of your methods for the player’s input
can simply tell GetAxes(); to handle input based on the vector2.

Meaning you can have both input from the defined input inside the project settings, AND GUI buttons that
handle the input changes as well.

input = Vector2(1.0, 0.0); changing the two vectors depending on which direction the player enters, this one is ‘right’ for example, is all you need to do by sending it to GetAxes. I’ve tested this out as I am editing GridMove.js myself.

The changes in the above Start function allow for the character to collide. You will have to play with the math a bit
to get the distance you want.

Eric’s GridMove.js is a very nice addition to the community.

I’d highly recommend using a 2D array to store the state of the world and base movement off that, rather than raycasting etc. Much more simple, consistent, and effective.

–Eric

Indeed. I have a slightly unique problem in how my world is, being that there is the person who designs the level first, then the player alters
things in the world that have collision later.

Also the objects in my world are of varying size and shape, so I cant rely on them sticking to the grid-size, as the characters all have the capsule controller which slides along stuff because its round, and
well I kinda like that for how the world operates.

This is step one in my process for fixing all the collision I need. I am writing an array that checks
within an area for objects and stores the positions of new ones once they are placed. The issue I have is I need it to not be static and very versitle.

Hi Argenex,
I was forcet to use C# version of gridmove script. Have anyone collision script in C#
Thanks a lot.

Here is a rough C# workaround that I have working for the GridMove.cs script.
It currently does not have the full desired effect as I have set the grid-size to 1 to allow for moveSpeed to be applied.

using System.Collections;
using UnityEngine;
 
class TopDown_PlayerController : MonoBehaviour {

	private GameObject _AUDIO;
	private CharacterController CC;
	
    public float moveSpeed = 8f;
    public float gridSize = 1f;
    private enum Orientation {
        Horizontal,
        Vertical
    };
    private Orientation gridOrientation = Orientation.Vertical;
    public bool allowDiagonals = false;
    public bool correctDiagonalSpeed = true;
    private Vector2 input;
    public bool isMoving = false;
    private Vector3 startPosition;
    private Vector3 endPosition;
	private Vector3 moveDirection;
    private float t;
    private float factor;
	
	public void Awake () {
		CC = this.gameObject.GetComponent <CharacterController> () as CharacterController;
		_AUDIO = GameObject.Find ("_AUDIO");		
	}
	
    public void Update() {
					
        if (!isMoving) {	
            input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
            if (!allowDiagonals) {
                if (Mathf.Abs(input.x) > Mathf.Abs(input.y)) {
                    input.y = 0;
                } else {
                    input.x = 0;
                }
            }
            if (input != Vector2.zero) {
                StartCoroutine(move(transform));
            }
        }
    }
	
    public IEnumerator move(Transform transform) {
		
    isMoving = true;
    startPosition = transform.position;
    t = 0;

    if(gridOrientation == Orientation.Horizontal) {
    	endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
    	startPosition.y, startPosition.z + System.Math.Sign(input.y) * gridSize);
    }else{
        endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
        startPosition.y + System.Math.Sign(input.y) * gridSize, startPosition.z);
    }
 
    if(allowDiagonals  correctDiagonalSpeed  input.x != 0  input.y != 0) {
        factor = 0.7071f;
    }else{
        factor = 1f;
    }
 
    while (t < 1f) {
        t += Time.deltaTime * (moveSpeed/gridSize) * factor;
	
	// Right            
		if(input == new Vector2(1f, 0)){
			moveDirection = new Vector3 (1f * moveSpeed, 0, 0);
		}	

	// Left            
		if(input == new Vector2(-1f, 0)){
			moveDirection = new Vector3 (-1f * moveSpeed, 0, 0);
		}
			
	// Up            
		if(input == new Vector2(0, 1f)){
			moveDirection = new Vector3 (0, 1f * moveSpeed, 0);
		}
			
	// Down            
		if(input == new Vector2(0, -1f)){
			moveDirection = new Vector3 (0, -1f * moveSpeed, 0);
		}			
			
		CC.Move (moveDirection);
  		yield return null;
    }
 
    isMoving = false;
    yield return 0;
    }
}

Hi all

I have one problen with bleakfacezzz implementation.
Is what i need but here is what happens:

The loop while (t<1) is not he same every time. It depeds on Time.deltaTime. So CC.Move(moveDirection) is not the same every time. It will executed for example 10 times if Time.deltaTime is similar to 0.1 or more than 10 times if Time.deltaTime is smaller. So i don’t have the same move every time.

Is there any way to have the same move every time?

Thank you.

I solved the problem by taking the original code in C# (http://wiki.unity3d.com/index.php/GridMove#C.23_-_GridMove.cs) and just changing

transform.position = Vector3.Lerp(startPosition, endPosition, t);

to

characterController.Move(endPosition - transform.position);

My final code:

using System.Collections;
using UnityEngine;

class CCGridMove : MonoBehaviour
{

    private CharacterController CC;

    public float moveSpeed = 6f;
    public float gridSize = 1f;
    private enum Orientation
    {
        Horizontal,
        Vertical
    };
    private Orientation gridOrientation = Orientation.Horizontal;
    public bool allowDiagonals = false;
    public bool correctDiagonalSpeed = true;
    private Vector2 input;
    public bool isMoving = false;
    private Vector3 startPosition;
    private Vector3 endPosition;
    private Vector3 moveDirection;
    private float t;
    private float factor;
    Animator anim;

    public void Start()
    {
        CC = GetComponent<CharacterController>();
        anim = GetComponent<Animator>();
    }

    public void Update()
    {

        if (!isMoving)
        {
            input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
            if (!allowDiagonals)
            {
                if (Mathf.Abs(input.x) > Mathf.Abs(input.y))
                {
                    input.y = 0;
                }
                else
                {
                    input.x = 0;
                }
            }
            if (input != Vector2.zero)
            {
                StartCoroutine(move(transform));
            }
        }
    }

    public IEnumerator move(Transform transform)
    {

        isMoving = true;
        startPosition = transform.position;
        t = 0;

        if (gridOrientation == Orientation.Horizontal)
        {
            endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
            startPosition.y, startPosition.z + System.Math.Sign(input.y) * gridSize);
        }
        else
        {
            endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
            startPosition.y + System.Math.Sign(input.y) * gridSize, startPosition.z);
        }

        if (allowDiagonals && correctDiagonalSpeed && input.x != 0 && input.y != 0)
        {
            factor = 0.7071f;
        }
        else
        {
            factor = 1f;
        }

        while (t < 1f)
        {
            t += Time.deltaTime * (moveSpeed / gridSize) * factor;

            Debug.Log("Start: " + startPosition + "Current: " + transform.position + "End: " + endPosition);
           
            CC.Move(endPosition - transform.position);
            yield return null;
        }

        isMoving = false;
        yield return 0;
    }
}

Hope this helps.