[Unity3D]-螺旋线
来源:互联网 发布:贵金属网络销售好做吗 编辑:程序博客网 时间:2024/04/29 05:07
之前,在做人物技能设计的时候,遇见一个做螺旋运动的技能,特效师,K帧K个半死,最终还是没有完美的弄出一个螺旋运动.这个时候,纯手工制作就没有用工程学的方法制作那般完美了.
在一个平面上做螺旋运动,螺纹由外向内,只需要两个步骤就可以完成.
1. 先在平面中做圆周运动
2. 然后逐渐缩短半径
如果在螺纹平面的垂直方向上再加一个运动量,则可形成3D螺旋运动.想想都觉得简单..哈哈!
上图为2D螺旋线运动轨迹和3D螺旋线运动轨迹示意图.
接下来本文将讲解如何制作一个2D螺线运动轨迹.
圆周运动
在3D空间中使一个物体在绕指定轴做圆周运动,例如Y轴,那么物体就在XZ平面上运动.
中心点A可已看成是从世界坐标远点到A点的向量,在此表示为OA,图中交点B也可用同样的方式去理解,在此表示为OB,那么红线所代表向量则可表示为AB.
已知A点和向量AB时,向量OB=OA+AB;
以此类推,物体做圆周运动时,轨迹上的点X(向量OX),可以由向量OA加上中心到圆周交点的X的向量AX求得,即OX=OA+AX;向量AX就是需要我们去实时计算的量.
如何计算向量 AX?
由图中的向量AB绕Y轴(或者说是中心点A)旋转一圈就可以求得所有的向量AX.向量AB=半径长度*单位向量.这里的单位向量可用XZ平面的任何一个单位向量表示.
如何旋转向量 AB?
我们可以使用四元数对向量AB做旋转变换,得出所有的向量AX.
物体圆周运动的求解思路大致如此,下面我给出一段示例代码.
public class MROTATE : MonoBehaviour{ public float _distance = 5f; public float _angle = 10f; bool _isStart = false; Transform _center; Transform _surround; void Awake() { _center = transform; _surround = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; _center.name = "_center"; _surround.name = "_surround"; _surround.position = Vector3.Normalize(Vector3.forward) * _distance + _center.position; StartCoroutine(InitEnd()); } IEnumerator InitEnd() { yield return new WaitForSeconds(1); _isStart = true; } void Update() { if (!_isStart) return; //绕Y轴旋转_angle度 Quaternion rotate = Quaternion.AngleAxis(_angle, Vector3.up); //由中心指向圆周的方向向量 Vector3 dir = Vector3.Normalize(_surround.position - _center.position); //向量OX = 向量OA + 向量AX _surround.position = _center.position + rotate * dir * _distance; } }
关于四元数的类容.
可以参考链接http://blog.csdn.net/candycat1992/article/details/41254799
或者参考书籍<3D数学基础:图形与游戏开发>
逐渐缩短半径
逐渐缩短半径就比较容易了,没有圆周运动那么复杂的计算.如果理解Lerp线性插值运算,那么逐渐缩短半径对你来说就是小菜一碟.
Lerp运算,有三个参数,第一个参数是起始值start,第二个参数是终点值end;第三个参数t范围在[0,1].
当第三个参数为0时,返回值start;
当第三个参数为1时,返回值end;
当第三个参数为0.5时,返回start与end中间的值,即(start+end)/2;
在Update方法中,做插值计算便可做到半径逐渐减小的效果.
其他好像没什么好说的了,下面是最终代码!
public class MROTATE : MonoBehaviour{ public float _distance = 10f; public float _speed = 10; public float _angle = 2f; bool _isStart = false; Transform _center; Transform _surround; float _value = 1; void Awake() { _center = transform; _surround = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform; _center.name = "_center"; _surround.name = "_surround"; _surround.position = Vector3.Normalize(Vector3.forward) * _distance + _center.position; //这一步协程是为了避免螺纹线初始位置绘制错误 StartCoroutine(InitEnd()); } IEnumerator InitEnd() { yield return new WaitForSeconds(1); _isStart = true; } void Update() { if (!_isStart) return; //半径逐渐减小 _value -= _speed * Time.deltaTime * 0.01f; float distance = Mathf.Lerp(0, _distance, _value); //圆周运动 Quaternion rotate = Quaternion.AngleAxis(_angle, Vector3.up); Vector3 dir = Vector3.Normalize(_surround.position - _center.position); _surround.position = rotate * dir * distance + _center.position; _pos.Add(_surround.position); } List<Vector3> _pos = new List<Vector3>(); void OnDrawGizmos() { Gizmos.color = Color.red; //在Scene视图中绘制螺纹线 for (int i = 0; i < _pos.Count - 1; i++) { Vector3 from = _pos[i]; Vector3 to = _pos[i + 1]; Gizmos.DrawLine(from, to); } }}
最终在Scene视图下的效果图如下.
- [Unity3D]-螺旋线
- 螺旋线
- 螺旋线
- 螺旋线
- 阿基米德螺旋线
- Matlab绘制螺旋线
- 技能的螺旋线
- python绘制螺旋线
- 螺旋线插补
- 在canvas中画个螺旋线
- OpenGL 绘制螺旋线
- l螺旋线方程
- 螺线与螺旋线
- MATLAB画阿基米德螺旋线
- 用opengl生成螺旋线算法
- python画五角星和螺旋线
- 阿基米德螺旋线-画无线扩大圆
- 绘制螺旋线导入到PCB中
- SIP测试环境搭建与SIP-ALG分析
- spark上使用scala及python编程练习
- android初识属性动画---alpha、scale、translate、rotate、set的xml属性及用法
- JS中的call、apply、bind方法
- MQTT---HiveMQ源码详解(二十一)完结篇
- [Unity3D]-螺旋线
- SSH整合———action报错
- hdu 2042不容易系列之二(老汉过收费站)
- 【Hadoop】基于Hadoop/Hbase/Hive的小型离线服务器日志分析应用
- HTTPS 初体验
- 三天打渔,两天晒网c++程序源码
- Cinatra:高性能现代C++ Web框架
- JavaMail、Spring JavaMail案例
- 显著性检测之