- Home /
The question is answered, right answer was accepted
How to detect collision of a wall with grid movement?
Hi everybody
I have this little game, where my player is moving around a simple level, using a grid based movement script (See code below). My problem is that I have tried to implement a 2D raycast, which has to detect if the next 'tile' is a movable tile (not a wall). However all the examples I have found on the internet hasn't been something I could make work. So please help me with how I can detect if the player is allowed to move, before he moves.
using System.Collections;
using UnityEngine;
public class GridMove : MonoBehaviour {
public float moveSpeed = 2f;
private float gridSize = 1f;
private enum Orientation {
Horizontal,
Vertical
};
private Orientation gridOrientation = Orientation.Vertical;
private bool allowDiagonals = false;
private bool correctDiagonalSpeed = true;
private Vector2 input;
private bool isMoving = false;
private Vector3 startPosition;
private Vector3 endPosition;
private float t;
private float factor;
private Animator animator;
// Use this for initialization
void Start () {
animator = 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));
animator.SetBool("isWalking", true);
}
else {
animator.SetBool("isWalking", false);
}
}
}
public IEnumerator Move(Transform transform) {
isMoving = true;
startPosition = transform.position;
t = 0;
animator.SetFloat("x", input.x);
animator.SetFloat("y", input.y);
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;
transform.position = Vector3.Lerp(startPosition, endPosition, t);
yield return null;
}
isMoving = false;
yield return 0;
}
}
Well, you don't have much of raycast related code here. But... Do you have colliders attached to your wall objects?
Probably you have checked the unity documentation about this:
http://docs.unity3d.com/ScriptReference/Physics2D.Raycast.html
But. If I were developing grid-based game, I would take totally different approach and forget about the hassle with raycasts etc. See, you could create an 2d array of ints for example, where different numbers represents different items in world. Wall could be number 1, player character number 2 etc. Idea would be that character movement is handled with that array coordinates and then just projected to 2d world of yours. Then checking if next tile is movable would be simply checking the type of tile from that array before movement.
Answer by rageingnonsense · Apr 28, 2015 at 02:45 PM
If you're using a grid, you don't even need to use the physics engine for this. In fact, you can get a huge performance boost by not doing this.
Let's say we represent your grid's movable areas with a 2d boolean array, where false values mean you cannot move. The array is arranged as x, y. Consider the following:
XXXXX
X00PX
X000X
X000X
XXXXX
X is a wall, 0 is movable space, and P is the player. Let's represent this in a a boolean array where tiles[0,0] is the top left, and tiles[4,4] is the bottom right.
Now all you need is a method like this:
bool TileIsPassable(int x, int y) {
return tiles[x, y];
}
Then all you need to do is transform your coordinates into the x, y coordinates of the grid. If your grid squares are unit squares (1 meter each), then you can use the direct values from a Vector2 (or even a Vector3):
bool canPass = TileIsPassable(Vector2.x, Vector2.y);
I had a problem with the 2D array. I have created a list, with objects of a new class called GridCell, which I am using to store information as the game object, and the vector position. I am therefore marking your answer as accepted, since It has helped me recoding my solution.
Follow this Question
Related Questions
Collision with grid based movement 0 Answers
2D Tile Map Question 0 Answers
How to find sprite at grid location? 1 Answer