Unity人工智能学习—确定性AI算法之追踪算法三
2015-09-10 09:42
731 查看
CSDN个人博客地址,凯尔八阿哥栏http://blog.csdn.net/zhangxiao13627093203,转载请注明出处
这样就可以很方便的操作我们的控制对象,作为使用例子我写了一个鼠标点击追踪算法,效果如图所示
它的核心代码如下:
它的原理是:首先计算预期的速度,这个速度是智能体在理想化情况下到达目标位置所需的速度,它是从智能体到目标的向量,大小为智能体的最大速度,该方法返回的操控力是所需要的力,当把它加到智能体当前速度向量上就得到预期的速度。所以,你可以简单的从预期速度中减去智能体的当前速度。但是你很快就会发现这个算法的一个问题,就是飞机在到达指定目标位置后并没有停止下来,而是反复的往返穿越目标点,如图所示:
针对这个问题,我会在下一篇进行讲解,接下来要讲的还是和这个算法直接相关的东西,我必须要先把它讲完。
有追踪算法,那么肯定也要有反追踪算法,其实它的原理在基于追踪的原理上就显得非常简单了
看看这个代码和上面的AI_Seek(vecter2 targetPos)有什么不一样。我在反追踪代码上面还加了一个距离的判断,也就是当目标和 飞机的距离小于预设的追踪距离的时候就开始追踪,它的效果图如图所示
接下来就是要进行更为精准更智能的追踪。因此,在接下来的代码演示Demo中我重新设计了几个类,一个是PlayObject,这个类其实也没有什么新的东西,都是之前已经介绍过的,无非就是速度向量、位置以及移动控制等它的代码设计如下:
</pre><span style="font-size:24px"></span><pre name="code" class="csharp">using UnityEngine; using System.Collections; public class PlayObject : MonoBehaviour { [HideInInspector] public float moveVx;//x方向的分速度 [HideInInspector] public float moveVy;//y方向的分速度 /// <summary> /// 2维坐标(x,y) /// </summary> public Vector2 Position { get { return new Vector2(this.transform.position.x, this.transform.position.y); } } private Vector2 _vHeading; /// <summary> /// //设置导弹的前进方向的归一化向量m_vHeading /// </summary> public Vector2 vHeading { get { float length = Mathf.Sqrt(moveVx * moveVx + moveVy * moveVy); if (length != 0) { _vHeading.x = moveVx / length; _vHeading.y = moveVy / length; } return _vHeading; } } private Vector2 _vSide; /// <summary> /// 前进方向的垂直向量 /// </summary> public Vector2 vSide { get { _vSide.x = -vHeading.y; _vSide.y = vHeading.x; return _vSide; } } /// <summary> /// 速度向量 /// </summary> public Vector2 Velocity { get { return new Vector2(moveVx, moveVy); } } /// <summary> /// 速度标量 /// </summary> public float Speed { get { return Mathf.Sqrt(moveVx * moveVx + moveVy * moveVy); } } public float MaxSpeedRate; // Use this for initialization void Start() { } // Update is called once per frame void Update() { } /// <summary> /// 移动物体 /// </summary> /// <param name="speedRate">移动的速度率,一般为1</param> /// <param name="isLookAtVelocityVector">是否要这是速度矢量与物体的朝向一致</param> public void Move(float speedRate, bool isLookAtVelocityVector) { this.transform.position += new Vector3(moveVx * Time.deltaTime, moveVy * Time.deltaTime, 0) * speedRate; // Debug.Log("x:" + m_postion.x + "y:" + m_postion.y); //调整导弹的朝向是的它和速度矢量合成方向一样 if (isLookAtVelocityVector) { LookAtVelocityVector(); } } /// <summary> /// 使得物体始终朝向矢量速度的方向 /// </summary> void LookAtVelocityVector() { float zAngles = Mathf.Atan(moveVx / moveVy) * (-180 / Mathf.PI); if (moveVy == 0) { zAngles = moveVx > 0 ? -90 : 90; //跟以往的计算角度不同的是,这里加了moveVx==0的独立判断,这样可以在不控制的时候保持原状态 if (moveVx == 0) { zAngles = this.transform.rotation.eulerAngles.z; } } if (moveVy < 0) { zAngles = zAngles - 180; } Vector3 tempAngles = new Vector3(0, 0, zAngles); Quaternion tempQua = this.transform.rotation; tempQua.eulerAngles = tempAngles; this.transform.rotation = tempQua; } }
这样就可以很方便的操作我们的控制对象,作为使用例子我写了一个鼠标点击追踪算法,效果如图所示
它的核心代码如下:
<span style="font-size:24px;">using UnityEngine; using System.Collections; using UnityEngine.UI; public class AISeek : MonoBehaviour { public PlayObject plane; public Image Aim; public float vecChangeRate;//这个数值越大在目标点的穿梭次数就会越多,一般为1 public float MaxSpeed; public float FleeDistance; Vector2 AimPos; // Use this for initialization void Start () { AimPos = new Vector2(Aim.transform.position.x, Aim.transform.position.y); } // Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0)) { Aim.transform.position = Input.mousePosition; AimPos = new Vector2(Aim.transform.position.x, Aim.transform.position.y); } Vector2 moveVec = AI_Seek(AimPos); float length = Mathf.Sqrt(moveVec.x * moveVec.x + moveVec.y * moveVec.y); if (length != 0) { // Debug.Log("x:" + moveVec.x + "y:" + moveVec.y); plane.moveVx += vecChangeRate * moveVec.x / length; plane.moveVy += vecChangeRate * moveVec.y / length; } plane.Move(1, true); } Vector2 AI_Seek(Vector2 targetPos) { Vector2 vSeekPos = targetPos - plane.Position; vSeekPos = vSeekPos.normalized*MaxSpeed - plane.Velocity; return vSeekPos; } } </span>
它的原理是:首先计算预期的速度,这个速度是智能体在理想化情况下到达目标位置所需的速度,它是从智能体到目标的向量,大小为智能体的最大速度,该方法返回的操控力是所需要的力,当把它加到智能体当前速度向量上就得到预期的速度。所以,你可以简单的从预期速度中减去智能体的当前速度。但是你很快就会发现这个算法的一个问题,就是飞机在到达指定目标位置后并没有停止下来,而是反复的往返穿越目标点,如图所示:
针对这个问题,我会在下一篇进行讲解,接下来要讲的还是和这个算法直接相关的东西,我必须要先把它讲完。
有追踪算法,那么肯定也要有反追踪算法,其实它的原理在基于追踪的原理上就显得非常简单了
<span style="font-size:24px;"> Vector2 AI_UNSeek(Vector2 targetPos) { Vector2 disPos = plane.Position - targetPos; float distance = Mathf.Sqrt(disPos.x * disPos.x + disPos.y * disPos.y); if(distance>FleeDistance) { return Vector2.zero; } disPos = disPos.normalized * MaxSpeed - plane.Velocity; return disPos; }</span>
看看这个代码和上面的AI_Seek(vecter2 targetPos)有什么不一样。我在反追踪代码上面还加了一个距离的判断,也就是当目标和 飞机的距离小于预设的追踪距离的时候就开始追踪,它的效果图如图所示
相关文章推荐
- Unity人工智能学习—确定性AI算法之反追踪算法
- 对Unity3d C#手动处理异常产生
- unity使用json的个人心得
- Unity中使用ulua的个人经验总结
- Unity3D制作高通AR(增强现实)图片识别应用
- uLua,一个Unity+Lua热更新解决方案!
- unity5在小米pad上闪退
- Unity调用原生(iOS, Android)方法
- Unity代码混淆方案
- unity实现简单的摄像机切换
- unity之Post,Get请求
- 在Unity3D中控制动画播放
- unity之协程
- unity之Json
- unity之XML
- Unity Attribute 总结
- 【Unity3D】夏日大作战Jumper~
- 【Unity3D】夏日大作战Jumper~
- Unity3D 学习笔记
- Unity3D开发之Unity跟IOS交互过程