塔防游戏中的网格制作
在大部分塔防游戏中当我们在建造单位的时候都会在可以建造的地方出现网格,我们在选择某个单位创建的时候鼠标移动到某个网格的时候这个网格就会处于选择状态,然后我们就可以在这个格子里创建一个单位,今天研究了一个塔防插件,把里面的网格部分分离出来做个小教程,分享给大家。
在开始之前把用到unity中的一些知识列出来:
1、在unity中Plane的单位大小是Cube的十倍
2、在plane上贴上带透明通道的图片,然后通过设置纹理的偏移量和缩放量来画出网格
3、通过射线的方式来判断当前所处的网格
Ray ray = Camera.main.ScreenPointToRay (mousePos);
RaycastHit hit;
好了,接下来就开始在unity中制作了:
1、新建一个plane和一个cube,给plane贴上图片grid.psd;我要做一个6×6的网格,如知识的2中,设置缩放量和偏移量分别为(0.5,0.5),(6.0,6.0)。
2、Plane和cube的位置都设置成(0,0,0);
3、我们以1.5倍的cube单位长度为一个网格的长,所以plane的大小是 1.5×6/10 即以0.9为单位长度的正方形。
4、把摄像机调节到合适的位置
5、开始写代码(下边以注释的方式讲解代码)
6、把脚本拖到相机上,吧plane托给Ground,cube托给indicator2,运行,要的效果就出来了
[table=1,#ffffff,#dddddd,0,0,initial][tr][td=1,1,0]
using UnityEngine;
using System.Collections;
public class GridTest : MonoBehaviour
{
public GameObject indicator2;//cube 作为被选中网格的标识
public GameObject ground; //plane
private float _gridSize = 1.5f;//网格的大小,以cube的单位长度为标准
void Start ()
{
}
void Update ()
{
SetIndicator (Input.mousePosition);
}
void SetIndicator (Vector3 mousePos)
{
//从鼠标位置发射一条射线
Ray ray = Camera.main.ScreenPointToRay (mousePos);
RaycastHit hit;
if (Physics.Raycast (ray, out hit, Mathf.Infinity)) {
Transform basePlane = ground.transform;
//通过大小来判断行数和列数是奇数还是偶数
float remainderX = GetWorldScale (basePlane).x * 10 / _gridSize % 2;
float remainderZ = GetWorldScale (basePlane).z * 10 / _gridSize % 2;
//获取射线碰撞点到ground的一个旋转量
Quaternion rot = Quaternion.LookRotation (hit.point - basePlane.position);
//get the x and z distance from the centre of the plane in the baseplane orientation
//from this point on all x and z will be in reference to the basePlane orientation
//碰撞点到ground的距离
float dist = Vector3.Distance (hit.point, basePlane.position);
Debug.Log ("dist:" + dist);
//以ground为坐标原点为坐标系,通过三角函数计算出碰撞点在坐标系中的坐标
float distX = Mathf.Sin ((rot.eulerAngles.y - basePlane.rotation.eulerAngles.y) * Mathf.Deg2Rad) * dist;
Debug.Log ("distX:" + distX);
float distZ = Mathf.Cos ((rot.eulerAngles.y - basePlane.rotation.eulerAngles.y) * Mathf.Deg2Rad) * dist;
Debug.Log ("distZ:" + distZ);
//判断碰撞点在ground为原点的坐标系中的哪一象限
float signX = distX / Mathf.Abs (distX);
Debug.Log ("signX:" + signX);
float signZ = distZ / Mathf.Abs (distZ);
//获取在ground为原点的坐标系中的单位坐标
float numX = Mathf.Round ((distX + (remainderX - 1) * (signX * _gridSize / 2)) / _gridSize);
float numZ = Mathf.Round ((distZ + (remainderZ - 1) * (signZ * _gridSize / 2)) / _gridSize);
//计算出在坐标轴中的偏移量
float offsetX = -(remainderX - 1) * signX * _gridSize / 2;
float offsetZ = -(remainderZ - 1) * signZ * _gridSize / 2;
//调整坐标系,
Vector3 p = basePlane.TransformDirection (new Vector3 (numX, 0, numZ) * _gridSize);
Debug.Log ("p :" + p);
p += basePlane.TransformDirection (new Vector3 (offsetX, 0, offsetZ));
Debug.Log ("p1 :" + p);
//set the position;
Vector3 pos = p + basePlane.position;
indicator2.transform.position = pos;
indicator2.transform.rotation = basePlane.rotation;
}
}
public Vector3 GetWorldScale (Transform transform)
{
Vector3 worldScale = transform.localScale;
Transform parent = transform.parent;
while (parent != null) {
worldScale = Vector3.Scale (worldScale, parent.localScale);
parent = parent.parent;
}
return worldScale;
}
}