1》人(任何移动物体)平常行走的每个路点都有两个方向(即:人可以从两个方向到此路点),人通过此路点到下个路点时人的朝向不变,故看起来什么都不需要做,只需要朝前走;
当面对各种路口(类似'L'形状路口有4种,类似'T'形状路口4种,类似'十'形状路口1种)时需要将人转向:
思路1(交给人脚本来做)人判断是什么样的路口,通过自己的当前朝向再确定自己转向角度(有多个转向角度可以选择时需要选择其中一个)。特点:大量代码放到人这一个脚本。
思路2.(交给路口脚本做)人只需要一直朝前走,路过路口时将自身引用传给路口脚本的函数,路口脚本(每种路口一个脚本)根据自身是什么样的路口和人当前朝向将人的朝向改变;特点:人一个脚本,每种路口各一个脚本共9+1 = 10个脚本。
显然思路2比较好,原因:路口相对于其他普通的路点来说,不同的地方就是可以起到一个转向器的作用;
2》当路点为‘L’型拐角路口时,人到达此路口需要转向为向下一个路点行走做准备,通过此时人的朝向确定旋转的角度。经过此路点的人的朝向只可能有两种,而这两种朝向对应两个转向角度;
3》实现:工具:Unity
此处以'L'形状的路口点为例,'T‘形和'十'形路口介绍主要代码;//下面的代码修改角度可以走斜路
思路:人只要通过射线检测到自己前方有cube就向自己的前方走一步,到达路口时,由路口脚本使人转向
人用红色cube代替,普通路点为白色,‘L’形路口点为蓝色,人行走6步停止,行走前状态如图:
运行时注意设置人的朝向:(人朝向Rotation的y值分别为:下:180或-180 上:0或360 左:270或-90 右:90)
Inspector面板中Rotation的y值设为:180或-180 即朝向下
路过路口后如图:(红色Cube的已经转向,别被看到的箭头迷惑,咱这是Mac版的Unity)
人行走的主要代码:
Player.cs:
public void MoveTo()
{
m_stepNum--; //对行走步数的控制
if (m_stepNum < 0)
{
m_stepNum = 0;
return;
}
RaycastHit hit;
Physics.Raycast(m_transform.position, m_transform.forward, out hit, 1.2f);//射线检测
TweenPosition twPos = TweenPosition.Begin(m_transform.gameObject, 0.1f, hit.transform.position);//此方法来自NGUI插件,功能是将m_transform.gameObject在0.1s时间内移动到位置hit.transform.position
if (hit.transform.GetComponent<WayPointLeftDownCorner>() != null)//WayPointLeftDownCorner.cs是挂在‘L’形路口点上的脚本
{
WayPointLeftDownCorner.RotatePlayer(this);//将人本身作为参数,此类方法用来改变人的朝向
}
else if (hit.transform.GetComponent<WayPointT2Corner>() != null)//WayPointT2Corner.cs是挂在‘T’形路口点上的脚本
{
WayPointT2Corner.RotatePlayer(this);//将人本身作为参数,此类方法用来改变人的朝向
}
else if (hit.transform.GetComponent<WayPointCross>() != null)//WayPointCross.cs是挂在'十'形路口点上的脚本
{
WayPointCross.RotatePlayer(this);//将人本身作为参数,此类方法用来改变人的朝向
}
EventDelegate.Add(twPos.onFinished, MoveTo);//当人移动到下个路点完成后,调用MoveTo(即自身)
}
WayPointLeftDownCorner.cs://挂在'L‘形路口点上的脚本,其他3种类似
public static void RotatePlayer(Player player)
{
if (player.transform.eulerAngles.y < 0)//人朝向下时,player.transform.eulerAngles.y的值180或-180;人朝向左时,值为-90或270
{
if (Mathf.Abs(-180 - player.transform.eulerAngles.y) < 0.5f)
{
player.transform.eulerAngles += new Vector3(0, -90, 0);
}
else if (Mathf.Abs(-90 - player.transform.eulerAngles.y) < 0.5f)
{
player.transform.eulerAngles += new Vector3(0, 90, 0);
}
}
else//0~360
{
if (Mathf.Abs(180 - player.transform.eulerAngles.y) < 0.5f)
{
player.transform.eulerAngles += new Vector3(0, -90, 0);
}
else if (Mathf.Abs(270 - player.transform.eulerAngles.y) < 0.5f)
{
player.transform.eulerAngles += new Vector3(0, 90, 0);
}
}
}
WayPointT2Corner.cs//
挂在'T‘形路口点上的脚本,其他3种类似
public static void RotatePlayer(Player player)
{
if (((player.transform.eulerAngles.y >= 0) && (Mathf.Abs(0 - player.transform.eulerAngles.y) < 0.5f))
|| ((player.transform.eulerAngles.y < 0) && (Mathf.Abs(0 - player.transform.eulerAngles.y) < 0.5f))
|| ((player.transform.eulerAngles.y > 0) && (Mathf.Abs(360 - player.transform.eulerAngles.y) < 0.5f)))//人朝向上
{
switch (Random.Range(0,2))
{
case 0:
WayPointLeftUpCorner.RotatePlayer(player);//右转
break;
case 1:
WayPointRightUpCorner.RotatePlayer(player);//左转
break;
default:
break;
}
}
else
{
if (player.transform.eulerAngles.y < 0 && Mathf.Abs(-90 - player.transform.eulerAngles.y) < 0.5f)//人朝向左
{
if (Random.Range(0,2) == 0)
{
WayPointLeftUpCorner.RotatePlayer(player);
}
}
else if (player.transform.eulerAngles.y > 0 && Mathf.Abs(270 - player.transform.eulerAngles.y) < 0.5f)//人朝向左
{
if (Random.Range(0,2) == 0)
{
WayPointLeftUpCorner.RotatePlayer(player);
}
}
else if (player.transform.eulerAngles.y > 0 && Mathf.Abs(90 - player.transform.eulerAngles.y) < 0.5f)//人朝向右
{
if (Random.Range(0,2) == 0)
{
WayPointRightUpCorner.RotatePlayer(player);
}
}
}
}
WayPointCross.cs//
挂在'十‘形路口点上的脚本
public static void RotatePlayer(Player player)
{
if ((((player.transform.eulerAngles.y >= 0) && (Mathf.Abs(180 - player.transform.eulerAngles.y) < 0.5f))
|| ((player.transform.eulerAngles.y < 0) && (Mathf.Abs(-180 - player.transform.eulerAngles.y) < 0.5f))))//人朝向下
{
switch (Random.Range(0,3))
{
case 0:
WayPointRightDownCorner.RotatePlayer(player);//右转
break;
case 1:
WayPointLeftDownCorner.RotatePlayer(player);//左转
break;
case 2:
break;//直行
default:
break;
}
}
else if (((player.transform.eulerAngles.y >= 0) && (Mathf.Abs(270 - player.transform.eulerAngles.y) < 0.5f))
|| ((player.transform.eulerAngles.y < 0) && (Mathf.Abs(-90 - player.transform.eulerAngles.y) < 0.5f)))//人朝向左
{
switch (Random.Range(0,3))
{
case 0:
WayPointLeftUpCorner.RotatePlayer(player);
break;
case 1:
WayPointLeftDownCorner.RotatePlayer(player);
break;
case 2:
break;
default:
break;
}
}
else if (((player.transform.eulerAngles.y >= 0) && (Mathf.Abs(0 - player.transform.eulerAngles.y) < 0.5f))
|| ((player.transform.eulerAngles.y < 0) && (Mathf.Abs(0 - player.transform.eulerAngles.y) < 0.5f))
|| ((player.transform.eulerAngles.y > 0) && (Mathf.Abs(360 - player.transform.eulerAngles.y) < 0.5f)))//人朝向上
{
switch (Random.Range(0,3))
{
case 0:
WayPointLeftUpCorner.RotatePlayer(player);
break;
case 1:
WayPointRightUpCorner.RotatePlayer(player);
break;
case 2:
break;
default:
break;
}
}
else if ((player.transform.eulerAngles.y >= 0) && (Mathf.Abs(90 - player.transform.eulerAngles.y) < 0.5f))//人朝向右
{
switch (Random.Range(0,3))
{
case 0:
WayPointRightUpCorner.RotatePlayer(player);
break;
case 1:
WayPointRightDownCorner.RotatePlayer(player);
break;
case 2:
break;
default:
break;
}
}
}