如何检测墙体与网格运动的碰撞?

我有这个小游戏,我的玩家正在使用一个基于网格的移动脚本(见下面的代码)在一个简单的水平上移动。 我的问题是,我试图实现一个二维射线,它必须检测下一个“瓷砖”是否是一个可移动的瓷砖(而不是墙)。 但是,我在互联网上find的所有例子都不是我能做的事情。 所以请帮助我如何在他移动之前检测玩家是否被允许移动。

我正在使用Unity 5。

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; } } 

如果你使用网格,你不应该使用Unity的物理学来进行碰撞检测 – 使用网格。 让你的位置在网格上,然后做这样的事情:

 public bool GridCast (Coordinate Position, Coordinate Direction, int Length) { for (int i = 0; i < Length; i++) { Coordinate Check = Position + Direction * Length; if (GridNodes[Check.x,Check.y].Occupied) { //Collision return true; } } return false; } 

要检查是否可以向前走4个瓷砖,请执行以下操作:

 if (GridPhysics.GridCast(MyCoordinate, new Coordinate (0,1), 4)) { //Something's in the way } else{ //Nothing's in the way; proceed with walking } 

如果你想知道有多less瓦片可以前进,如果有什么问题,可以添加一个名为Point的out参数来表示碰撞点。

 Coordinate Check = Position + Direction * Length; if (GridNodes[Check.x,Check.y].Occupied) { //Collision *Point = Check* return true; } 

然后,直到这一点。

 Move (Point - MyCoordinate); 

要回答标题问题,您可以通过访问GridNodes数组并标记墙所占的节点并检测与GridCast方法的冲突来创建墙。

 For (int i = Wall.MyCoordinate.x; i < Wall.Width + Wall.MyCoordinate.x; i++) { for (int j = Wall.MyCoordinate.y; j < Wall.Height + Wall.MyCoordinate.y; j++) { GridNodes[i,j].Occupied = true; } } 

请注意,此GridCast实现将不能准确地对角线工作,但它将超级快,特别是如果您将GridNodes数组展平。


以下是网格地图可以做的其他示例: https : //www.youtube.com/watch?v=MEd6XV2Pecw 。 在这个概述中,我把它称为影响图,但是概念保持不变 – 将你的位置映射到网格平面上的2D点,然后根据需要用点和存储在网格中的信息来做任何事情。

寻路,战争迷雾(对于网格游戏来说真的很酷),AI Bots都可以通过影响图来实现。 我99.99%肯定MineCraft使用平坦的3D数组来存储其块状信息。 星际争霸使用网格进行寻路,构建和攻击search(我认为)。 无论如何,你明白了。 网格是便宜,有效的信息存储和交互方式。

使用二维平铺arrays为您的世界/水平的一代和代表将肯定会简化的事情。 举个例子,你可以用瓦片的网格在内部表示你的世界,

 using System; using System.Collections.Generic; using System.Text; namespace Tiles { public class Vector2 { public int x; public int y; public Vector2(int x, int y) { this.x = x; this.y = y; } } public enum TileType { None, Grass, Dirt, Stone, Water, Air, } public class Tile { public Vector2 position; public TileType tileType; public Tile(int x, int y, TileType tileType) { this.position = new Vector2(x, y); this.tileType = tileType; } } public class World { public Tile[,] tiles; public int sizeX; public int sizeY; public World(int sizeX, int sizeY) { this.sizeX = sizeX; this.sizeY = sizeY; int tileCount; // build the world tiles = new Tile[sizeX, sizeY]; Random rnd = new Random(); tileCount = Enum.GetValues(typeof(TileType)).Length; // construct grid of tiles for (int x = 0; x < sizeX; x++) { for (int y = 0; y < sizeX; y++) { tiles[x, y] = new Tile(x, y, (TileType)rnd.Next(tileCount)); } } } } class Program { static void Main(string[] args) { World world = new World(20, 20); for (int y = 0; y < world.sizeY; y++) { for (int x = 0; x < world.sizeX; x++) { Console.Write((int)world.tiles[x, y].tileType + " "); } Console.WriteLine(); } } } } 

一旦设置好了,你就可以在你的移动path上询问一个瓷砖,看它是否根据地形types走路,或者是否被儿童障碍物阻挡等等。