您的位置:首页 > 移动开发 > Unity3D

Unity人工智能学习—确定性AI算法之追踪算法五

2015-10-09 11:47 1456 查看
前面的追踪都能很好的解决大部分的问题,但是人工智能的宗旨是模拟实现更为真实更为智能的智能体。同样,一个简单的追踪算法它也是有很多优化为更智能的需求。这一篇是追踪算法里面的拦截追踪,效果图如图所示:



这个就不在是前面简单生硬的尾随而至的追踪了,导弹是根据飞机的飞行速度来提前拦截飞机,这里有一个追踪的目标点我隐藏掉了,它的真是写照如图所示



飞机前面的目标点就是导弹追踪的目标,目标点始终都是在飞机的飞行正前方且随着速度越大目标点的距离越远。
核心算法代码如下:
/// <summary>
/// 拦截追逐算法,可以预测追逐目标的移动位置进行追踪
/// </summary>
/// <returns></returns>
Vector2 AI_PredictionPursuit()
{
//首先计算两者的距离
Vector2 ToPursuit = m_pursuitTarget.Position - m_pursuiter.Position;
//局部坐标的前进方向向量的点积
float RelativeHeading = DotProduct(m_pursuiter.vHeading, m_pursuitTarget.vHeading);
//如果两者的距离在追逐者的局部向量前进方向的投影大于零,那么追逐者应该直接向被追踪对象移动,这里的20是被追踪对象的反方向和追踪者的朝向在18度(cos(18)=0.95)就被认为是面对着的
if(DotProduct(ToPursuit,m_pursuiter.vHeading)>0&&RelativeHeading<-0.95f)
{
//            Debug.Log("relativeHeading:" + RelativeHeading);
return AI_Seek(m_pursuitTarget.Position);
}
//预测被追踪者的位置,预测的时间正比于被追踪者与追踪者的距离,反比与追踪者的速度和当前靠近被追踪者的被预测位置(好绕口啊,慢慢理解吧!)
float toPursuitLenght=Mathf.Sqrt(ToPursuit.x*ToPursuit.x+ToPursuit.y*ToPursuit.y);
float LookAheadTime = toPursuitLenght / (m_pursuiter.MaxSpeed + m_pursuitTarget.Speed);
//预测的位置,其实这个位置会一直在被追踪对象的局部坐标前方
Vector2 predictionPos=m_pursuitTarget.Position+m_pursuitTarget.Velocity*LookAheadTime;
Debug.Log("preditionx:" + predictionPos.x + "preditiony:" + predictionPos.y);
AimPredictionPos.transform.position = new Vector3(predictionPos.x, predictionPos.y, 0);
return AI_Seek(predictionPos);
}
完整实现代码如下:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class AIPredictionPursuit : MonoBehaviour {
public PlayObject m_pursuiter;
public PlayObject m_pursuitTarget;
public Image AimPredictionPos;
// Use this for initialization
void Start () {
}

// Update is called once per frame
void Update()
{
//  Vector2 moveVec = AI_Seek(m_pursuitTarget.Position);
Vector2 moveVec = AI_PredictionPursuit();
m_pursuiter.moveVx += moveVec.x;
m_pursuiter.moveVy += moveVec.y;
m_pursuiter.Move(1, true);
}
/// <summary>
/// 拦截追逐算法,可以预测追逐目标的移动位置进行追踪
/// </summary>
/// <returns></returns>
Vector2 AI_PredictionPursuit()
{
//首先计算两者的距离
Vector2 ToPursuit = m_pursuitTarget.Position - m_pursuiter.Position;
//局部坐标的前进方向向量的点积
float RelativeHeading = DotProduct(m_pursuiter.vHeading, m_pursuitTarget.vHeading);
//如果两者的距离在追逐者的局部向量前进方向的投影大于零,那么追逐者应该直接向被追踪对象移动,这里的20是被追踪对象的反方向和追踪者的朝向在18度(cos(18)=0.95)就被认为是面对着的
if(DotProduct(ToPursuit,m_pursuiter.vHeading)>0&&RelativeHeading<-0.95f)
{
//            Debug.Log("relativeHeading:" + RelativeHeading);
return AI_Seek(m_pursuitTarget.Position);
}
//预测被追踪者的位置,预测的时间正比于被追踪者与追踪者的距离,反比与追踪者的速度和当前靠近被追踪者的被预测位置(好绕口啊,慢慢理解吧!)
float toPursuitLenght=Mathf.Sqrt(ToPursuit.x*ToPursuit.x+ToPursuit.y*ToPursuit.y);
float LookAheadTime = toPursuitLenght / (m_pursuiter.MaxSpeed + m_pursuitTarget.Speed);
//预测的位置,其实这个位置会一直在被追踪对象的局部坐标前方
Vector2 predictionPos=m_pursuitTarget.Position+m_pursuitTarget.Velocity*LookAheadTime;
Debug.Log("preditionx:" + predictionPos.x + "preditiony:" + predictionPos.y);
AimPredictionPos.transform.position = new Vector3(predictionPos.x, predictionPos.y, 0);
return AI_Seek(predictionPos);
}
/// <summary>
/// 到达指定位置
/// </summary>
/// <param name="TargetPos">指定位置向量</param>
/// <returns></returns>
Vector2 AI_Seek(Vector2 TargetPos)
{
//计算目标位置与追踪对象位置的向量并且将其归一化
Vector2 DesiredVelocity = (TargetPos - m_pursuiter.Position).normalized*m_pursuiter.MaxSpeed;
//直接相减就可以得到一个中间的过渡向量,避免直接生硬的改变
DesiredVelocity = DesiredVelocity - m_pursuiter.Velocity;
return DesiredVelocity;
}
/// <summary>
/// 计算矩阵A与矩阵B的点积
/// </summary>
/// <param name="A"></param>
/// <param name="B"></param>
/// <returns></returns>
float DotProduct(Vector2 A, Vector2 B)
{
return A.x * B.x + A.y * B.y;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: