关于游戏中拦截算法的实现
2015-11-08 23:49
225 查看
拦截,顾名思义,在追及目标的时候,预测目标在未来一段时间会到达的位置,并提前朝着这个位置前进。
在追及者速度大于被追及者(且称猎物)速度时,采用拦截算法能有效利用速度效率,并且能在某些情况下解决普通追及算法所出现的问题(例如追及者被甩尾会浪费速度效率)
拦截算法的关键是求出追及者速度的方向,需要猎物此刻相对追及者的位置、猎物的速度大小及其方向。
思路大致为:算出猎物相对于追及者的速度和位移,然后用相对位移除以相对速度得出预计拦截所需时间,再用猎物的速度乘拦截时间再加上猎物自身位移得出预计拦截点,
最后让追及者朝着拦截点运动进行拦截。(上述除时间其他变量均为向量,即带大小和方向)
简单的拦截算法在unity中实现,关键脚本如下:
该demo中,拦截算法每帧执行一次,故追及者每刻都会根据猎物的位置和速度来调整自身的拦截方向,所以即使猎物在进行变速运动,追及者都能完成拦截算法。
问:拦截算法的关键就是求出追及者速度的方向,然而在拦截算法的计算中却用到追及者的速度向量,是否相悖?
答:看上去确实有矛盾,但在该案例中,先把追及者速度初始化为零,此时拦截算法中的相对速度即为猎物速度,因此拦截算法能正常得出拦截点,再由CatchAt()函数将速度校准。
Ps:CatchAt函数是通过改变速度的分量大小来改变速度的方向,因此在校准速度时速度大小也会变化。
在追及者速度大于被追及者(且称猎物)速度时,采用拦截算法能有效利用速度效率,并且能在某些情况下解决普通追及算法所出现的问题(例如追及者被甩尾会浪费速度效率)
拦截算法的关键是求出追及者速度的方向,需要猎物此刻相对追及者的位置、猎物的速度大小及其方向。
思路大致为:算出猎物相对于追及者的速度和位移,然后用相对位移除以相对速度得出预计拦截所需时间,再用猎物的速度乘拦截时间再加上猎物自身位移得出预计拦截点,
最后让追及者朝着拦截点运动进行拦截。(上述除时间其他变量均为向量,即带大小和方向)
简单的拦截算法在unity中实现,关键脚本如下:
public class Enemy : MonoBehaviour { float cTime;//预计拦截时间 public int speedMag = 5;//速度级数 Vector3 speed = new Vector3();追及者速度 Vector3 target = new Vector3();//预测拦截点 Vector3 pPos = new Vector3();//相对位移 Vector3 pSpeedVec3 = new Vector3();//相对速度 Player player;//获得猎物的速度和位置 void Awake() { player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>(); } void Update() { transform.position += speed * Time.deltaTime;//实现运动 pSpeedVec3 = player.speed - speed;//该段为拦截算法 pPos = player.transform.position - transform.position; cTime = pPos.magnitude / pSpeedVec3.magnitude; target = player.transform.position + player.speed * cTime; CatchAt(target);//追及者朝着拦截点运动 } void CatchAt(Vector3 target) { Vector3 dir = (target - transform.position).normalized * speedMag; if (dir.x > 0) { speed.x = Mathf.Min(speed.x + 1, dir.x); } else if (dir.x < 0) { speed.x = Mathf.Max(speed.x - 1, dir.x); } if (dir.z > 0) { speed.z = Mathf.Min(speed.z + 1, dir.z); } else if (dir.z < 0) { speed.z = Mathf.Max(speed.z - 1, dir.z); } } }
该demo中,拦截算法每帧执行一次,故追及者每刻都会根据猎物的位置和速度来调整自身的拦截方向,所以即使猎物在进行变速运动,追及者都能完成拦截算法。
问:拦截算法的关键就是求出追及者速度的方向,然而在拦截算法的计算中却用到追及者的速度向量,是否相悖?
答:看上去确实有矛盾,但在该案例中,先把追及者速度初始化为零,此时拦截算法中的相对速度即为猎物速度,因此拦截算法能正常得出拦截点,再由CatchAt()函数将速度校准。
Ps:CatchAt函数是通过改变速度的分量大小来改变速度的方向,因此在校准速度时速度大小也会变化。
相关文章推荐
- Day 5(11.8):(0)主要知识点
- 重写jquery.confirm.js 摆脱传统alert confirm 插件供下载(三)
- 即将步入程序世界的小菜鸟
- 关于Python 的@操作符 Decorator 的用法
- Js 作用域链(是指AO链)
- 补充一下PES的包结构
- Day 5(11.8):分组查询练习1答案
- 滑动界面viewpager
- Codeforces Round #277 (Div. 2)C.Palindrome Transformation 贪心
- Wireshark网络分析就这么简单 -- 目录
- linux 常用基础命令 cat 详细介绍
- Day Two
- ISO/IEC 9899:2011 条款6.7.6——声明符
- Linux 技巧:让进程在后台可靠运行的几种方法
- 又看自己年少时的代码
- Day 5(11.8):(5)讲义
- jquery中attr和prop的区别分析
- ExtJS5获取当前光标位置插入文本内容
- redis并发问题
- ubuntu下服务自启与关闭