Unity3DAI行为------避开障碍物简单实现
2017-05-27 14:41
344 查看
public float speed = 20.0f;
public float mass = 5.0f;
public float force = 50.0f;
public float minimumDistToAvoid = 20.0f;
private float curSpeed;
private Vector3 targetPoint;
// Use this for initialization
void Start () {
targetPoint = Vector3.zero;
mass = 5.0f;
}
在Update方法中,我们基于AvoidObstacles方法返回的方向向量更新agent实体的位置并对其进行旋转。我们在update方法中所做的第一件事就是获取鼠标点击的位置,以移动我们的AI实体,我们向它正在观察的方向发出一条射线,然后获取这条射线
与地平面的交点,作为目标位置,一旦获取到了目标位置向量,就可以用目标位置向量减去当前位置的向量来计算出目标向量。最后调用AvoidObstacles方法,并将这个目标向量作为参数传入。
AvoidObstacles方法也非常简单,这里唯一需要注意的技巧就是光线投射会选择性的与障碍物所在的图层相互作用,这个图层已经在Unity3D的标签管理器中标记为User Layer8,Raycast方法接收一个图层掩码参数,
Unity3D使用一个32位的整数来代表这个图层掩码参数,例如,以下表示32位全是零:
0000 0000 0000 0000 0000 0000 0000 0000
默认情况下Unity使用前8层作为内置的图层。所以,当你不使用任何图层掩码参数的情况下调用光线投射方法时,它会对所有默认的这8层进行光线投射,可以用如下位掩码表示:
0000 0000 0000 0000 0000 0000 1111 1111
我们的障碍物所在的层被设置为第8层(下标为9),我们只希望对这个层进行光线投射,所以我们将位掩码设置为:
0000 0000 0000 0000 0000 0001 0000 0000
设置这个位掩码最简单的办法是使用位移操作,我们只需要将下标为9的位置设置为1,这意味着我们只需左移8位即可:
int layerMask = 1<<8;
一旦设置好了图层掩码,我们就可以调用Physics.Raycast方法,从当前实体的位置的方向投射一条射线。射线的长度使用变量minimumDistToAvoid,这样我们就可以只避开在这个距离内射线遇到的障碍。
然后我们获取到射线的法向量,用其乘以力的向量,再把它与当前实体方向的向量相加,得出合成方向向量,并将其从方法中返回。
接着在Update方法中,在避开障碍物之后,我们使用这个新的方向对AI实体进行旋转并根据速度值更新位置。
public void AvoidObstacles(ref Vector3 dir)
{
RaycastHit hit;
int layerMask = 1 << 8;
if (Physics.Raycast(transform.position,transform.forward,out hit, minimumDistToAvoid, layerMask))
{
Vector3 hitNormal = hit.normal;
hitNormal.y = 0;
dir = transform.forward + hitNormal * force;
}
}
public float mass = 5.0f;
public float force = 50.0f;
public float minimumDistToAvoid = 20.0f;
private float curSpeed;
private Vector3 targetPoint;
// Use this for initialization
void Start () {
targetPoint = Vector3.zero;
mass = 5.0f;
}
在Update方法中,我们基于AvoidObstacles方法返回的方向向量更新agent实体的位置并对其进行旋转。我们在update方法中所做的第一件事就是获取鼠标点击的位置,以移动我们的AI实体,我们向它正在观察的方向发出一条射线,然后获取这条射线
与地平面的交点,作为目标位置,一旦获取到了目标位置向量,就可以用目标位置向量减去当前位置的向量来计算出目标向量。最后调用AvoidObstacles方法,并将这个目标向量作为参数传入。
void Update () { RaycastHit hit; var ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Input.GetMouseButtonDown(0) && Physics.Raycast(ray,out hit,100.0f)) { targetPoint = hit.point; } Vector3 dir = targetPoint - transform.position; dir.Normalize(); AvoidObstacles(ref dir); if (Vector3.Distance(targetPoint,transform.position) <3.0f) { return; } curSpeed = speed * Time.deltaTime; var rot = Quaternion.LookRotation(dir); transform.rotation = Quaternion.Slerp(transform.rotation, rot, 5.0f * Time.deltaTime); transform.position += transform.forward * curSpeed; }
AvoidObstacles方法也非常简单,这里唯一需要注意的技巧就是光线投射会选择性的与障碍物所在的图层相互作用,这个图层已经在Unity3D的标签管理器中标记为User Layer8,Raycast方法接收一个图层掩码参数,
Unity3D使用一个32位的整数来代表这个图层掩码参数,例如,以下表示32位全是零:
0000 0000 0000 0000 0000 0000 0000 0000
默认情况下Unity使用前8层作为内置的图层。所以,当你不使用任何图层掩码参数的情况下调用光线投射方法时,它会对所有默认的这8层进行光线投射,可以用如下位掩码表示:
0000 0000 0000 0000 0000 0000 1111 1111
我们的障碍物所在的层被设置为第8层(下标为9),我们只希望对这个层进行光线投射,所以我们将位掩码设置为:
0000 0000 0000 0000 0000 0001 0000 0000
设置这个位掩码最简单的办法是使用位移操作,我们只需要将下标为9的位置设置为1,这意味着我们只需左移8位即可:
int layerMask = 1<<8;
一旦设置好了图层掩码,我们就可以调用Physics.Raycast方法,从当前实体的位置的方向投射一条射线。射线的长度使用变量minimumDistToAvoid,这样我们就可以只避开在这个距离内射线遇到的障碍。
然后我们获取到射线的法向量,用其乘以力的向量,再把它与当前实体方向的向量相加,得出合成方向向量,并将其从方法中返回。
接着在Update方法中,在避开障碍物之后,我们使用这个新的方向对AI实体进行旋转并根据速度值更新位置。
public void AvoidObstacles(ref Vector3 dir)
{
RaycastHit hit;
int layerMask = 1 << 8;
if (Physics.Raycast(transform.position,transform.forward,out hit, minimumDistToAvoid, layerMask))
{
Vector3 hitNormal = hit.normal;
hitNormal.y = 0;
dir = transform.forward + hitNormal * force;
}
}
相关文章推荐
- qt实现简单的五子棋(无AI)
- Unity3d 一个简单的玻璃效果实现!
- 使用状态机实现简单的AI
- 在Unity3D中实现简单的碰撞检测
- [游戏AI]实现掩蔽行为的策略
- 用unity3d实现简单chat对话
- unity3d简单的AI
- Unity3D里实现物体移动到目标点,并且摄像机跟着移动的简单方案
- [Unity3D插件]2dToolKit系列三 碰撞检测功能的实现以及障碍物的随机摆放 推荐
- 游戏AI简单实现
- AI中的漫游行为,简单模拟了下
- AI中的漫游行为,简单模拟了下
- Unity3D中利用NGUI实现简单的Tabview
- Unity3d 中行为类之间的简单交互
- 使用行为树(Behavior Tree)实现游戏AI
- Unity3D 加载fbx模型,实现简单的方向控制
- [Unity3D]使用碰撞体做触发器实现简单的自动开门
- unity3d 怪物的简单ai
- [Unity3D]Unity3D游戏开发之史上最简单的鼠标点击控制人物走动实现