博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
山寨小小军团开发笔记 之 Arrow Projectile
阅读量:6160 次
发布时间:2019-06-21

本文共 4329 字,大约阅读时间需要 14 分钟。

    好久没怎么更新博客了,今天抽空来一篇,讨论一下弓箭的轨迹生成。

一、原理

      弓箭的轨迹本质就是一个数学问题,使用一个 bezier 曲线公式就可以插值生成。得到轨迹后,做一个lookAt就可以了。

二、Bezier 曲线原理

     2015-5-15 :相关原理介绍,我就不重复了

  http://zh.wikipedia.org/wiki/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A

  http://devres.zoomquiet.io/data/20110728232822/index.html

 

 

     我这里贴一下应用代码

     

public class Bezier    {        public Vector3 p0 = Vector3.zero;        public Vector3 p1 = Vector3.zero;        public Vector3 p2 = Vector3.zero;        public Bezier(Vector3 v0, Vector3 v1, Vector3 v2)        {            this.p0 = v0;            this.p1 = v1;            this.p2 = v2;        }        public void UpdateTargetPos(Vector3 v2)        {            p2 = v2;        }        public Vector3 GetPointAtTime(float t)        {            float x = (1 - t) * (1 - t) * p0.x + 2 * t * (1 - t) * p1.x + t * t * p2.x;            float y = (1 - t) * (1 - t) * p0.y + 2 * t * (1 - t) * p1.y + t * t * p2.y;            float z = (1 - t) * (1 - t) * p0.z + 2 * t * (1 - t) * p1.z + t * t * p2.z;            return new Vector3(x, y, z);        }    }

三、例子分析

     搭建一个测试场景,从中心点发射弓箭诡异

  

 

      Center上挂载一个脚本  

      BezierTest.cs

public GameObject arrowPrefab;    public Transform left;    public Transform right;    void Test(bool fireRight)    {        Transform end = fireRight ? right : left;        ///在中心点生成弓箭        GameObject curArrow = arrowPool.Spawn(transform.position, Quaternion.Euler(Vector3.zero));        ///计算LookTarget的点 与 贝塞尔曲线的第三个控制点        Vector3[] points = Re_LookTarget_MiddlePerpendicularPoint(curArrow.transform, end);        ///初始化发射        ArrowControl arrowControl = curArrow.GetComponent
(); arrowControl.Init( points[0], points[1], end.position, 3.0f, delegate() { arrowPool.Unspawn(curArrow); }); } Vector3[] Re_LookTarget_MiddlePerpendicularPoint(Transform self, Transform enemy) { Vector3 direction = (enemy.position - self.position).normalized; float segment = Vector2.Distance(enemy.position, self.position) / 2.0f; Vector3 lookTarget = (self.position + enemy.position) / 2.0f; Vector3 perpendicular_direction; if (direction.x > 0) { perpendicular_direction = new Vector3(-direction.y, direction.x, 0); } else { perpendicular_direction = new Vector3(direction.y, -direction.x, 0); } ///perpendicular line Vector3 middle_pendicular = lookTarget + perpendicular_direction * segment; return new Vector3[] { lookTarget, middle_pendicular }; } void OnGUI() { if (GUI.Button(new Rect(10, 10, 150, 100), "Fire Left")) Test(false); if (GUI.Button(new Rect(160, 10, 150, 100), "Fire Right")) Test(true); }

 

  预设上挂载的控制脚本

  ArrowControl.cs 

 

float alltimer;        Util.Bezier bezier = null;    float timer = 0f;    Callback recycleFunction;    Vector3 lookAtTarget;    //bool defaultRightNeedTurn = false;;    public void Init(Vector3 lookAtTarget, Vector3 middle, Vector3 end, float alltimer, Callback recycleFunction)    {        this.lookAtTarget = lookAtTarget;        this.bezier = new Util.Bezier(transform.position, middle, end);                this.alltimer = alltimer;        Flip(end.x, transform.position.x);        this.recycleFunction = recycleFunction;    }    void Flip(float end_X, float self_X)    {        Transform pic = transform.Find("pic");        if (end_X < self_X)  {            pic.localScale = new Vector3(-1.0f, 1.0f, 1.0f);        }        else {            pic.localScale = new Vector3( 1.0f, 1.0f, 1.0f);        }    }    public void Clear()    {        this.bezier = null;        timer = 0f;    }    void Update()    {        if (this.bezier != null)        {            timer += Time.deltaTime;            float t = timer / alltimer;            //Debug.Log("timer" + timer + " t " + t);            if (t >= 1.0f) {                Clear();                if (recycleFunction != null) recycleFunction();            }            else {                transform.LookAt(lookAtTarget, Vector3.forward);                                transform.position = bezier.GetPointAtTime(t);            }        }    }

  

 这里注意,对于LookAt这个行为,我没有很好的数学方法,所以用了U3D的API。

 但是这个API 只能保证Z轴始终指向target, 所以图片的旋转预先是这样。

 

 

四、结果

 

转载于:https://www.cnblogs.com/chongxin/p/4340108.html

你可能感兴趣的文章
在OSCHINA上的第一篇博文,以后好好学习吧
查看>>
Spring常用注解
查看>>
linux:yum和apt-get的区别
查看>>
Sentinel 1.5.0 正式发布,引入 Reactive 支持
查看>>
数据库之MySQL
查看>>
2019/1/15 批量删除数据库相关数据
查看>>
数据类型的一些方法
查看>>
Webpack 2 中一些常见的优化措施
查看>>
移动端响应式
查看>>
js中var、let、const的区别
查看>>
简洁优雅地实现夜间模式
查看>>
react学习总结
查看>>
在soapui上踩过的坑
查看>>
MySQL的字符集和字符编码笔记
查看>>
ntpd同步时间
查看>>
Maven编译时跳过Test
查看>>
Spring Boot 整合Spring Security 和Swagger2 遇到的问题小结
查看>>
Apache通过mod_php5支持PHP
查看>>
java学习:jdbc连接示例
查看>>
Silverlight 如何手动打包xap
查看>>