现在我们要学的是unity 脚步轨迹。游戏用到的Motion Trail原理其实很简单,就是利用一个Queue,将两参考点于每个Frame的位置记录下来,这记录通常是有条件的,也许是两参考点与上一个Frame的纪录比较距离,若高过某一threadhould就push in,此外在每个Frame里也检查已经在Queue中的其它点,生命周期是不是已经到了,如果是就将这次的纪录pop out。
unity 脚步轨迹
Pseudo Code如下所示:
接下来的问题就是,将这Queue里的“点”加上建构三角面的Index及计算出贴图UV,进行Rendering,即可得到两点间的移动轨迹,加上贴图就如同上图所示了。Pseudo Code如下所示:
  1. Update() {
  2. float now = Time.time;
  3. Vector3 P1 = m_CurPointA;
  4. Vector3 P2 = m_CurPointB;
  5. Vector3 preP1 = m_Queue[0].PointA;
  6. Vector3 preP2 = m_Queue[0].PointB;
  7. if( (P1 - preP1).length > 0.5f ||
  8. (P2 - preP2).length > 0.5f ) {
  9. m_Queue.push( p1, p2, now );
  10. }
  11. while( m_Queue.count > 0 &&
  12. now - m_Queue[end].time > 1.0f ) {
  13. m_Queue.pop( end );
  14. }
  15. //Generate triangles indices:
  16. trailMesh.triangles = new int[(m_Queue.count-1)*2*3];
  17. for( int i=0; i trailMesh.triangles[i * 6 + 0] = i * 2; i++ ) {
  18. trailMesh.triangles[i * 6 + 0] = i * 2;
  19. trailMesh.triangles[i * 6 + 1] = i * 2 + 1;
  20. trailMesh.triangles[i * 6 + 2] = i * 2 + 2;
  21. trailMesh.triangles[i * 6 + 3] = i * 2 + 2;
  22. trailMesh.triangles[i * 6 + 4] = i * 2 + 1;
  23. trailMesh.triangles[i * 6 + 5] = i * 2 + 3;
  24. }
  25. }
进阶修饰:
如果只单纯的这样产生Motion Trail,你因该会发现,画出来的弧线会菱菱角角的不是很好看。至于要怎麽加强这个部分呢?很简单,就拿曲线演算来使用吧!在这里使用的是Catmull-Rom Spline,它有几个特点:
1. Catmull-Rom保证,曲线一定通过控制点
2. Spline C1 contunuous,这表示在tangent的方向与长度上,不会有区别。
3. 计算简单
数学表示式如下:
q(t) = 0.5 *( (2 * P1) + (-P0 + P2) * t + (2*P0 – 5*P1 + 4*P2 – P3) * t2 + (-P0 + 3*P1- 3*P2 + P3) * t3)
Pseudo Code如下所示:
  1. public static TrailSection Catmull_Rom(
  2. TrailSection p0, TrailSection p1,
  3. TrailSection p2, TrailSection p3,
  4. float t )
  5. {
  6. TrailSection section = new TrailSection();
  7. float t2 = t * t;
  8. float t3 = t2 * t;
  9. float a0 = -t3 + 2*t2 - t;
  10. float a1 = 3*t3 - 5*t2 + 2;
  11. float a2 = -3*t3 + 4*t2 + t;
  12. float a3 = t3 - t2;
  13. section.pointS = (a0*p0.pointS + a1*p1.pointS + a2*p2.pointS + a3*p3.pointS) * 0.5f;
  14. section.pointE = (a0*p0.pointE + a1*p1.pointE + a2*p2.pointE + a3*p3.pointE) * 0.5f;
  15. section.time = (a0*p0.time + a1*p1.time + a2*p2.time + a3*p3.time) * 0.5f;
  16. return section;
  17. }