2012年1月9日 星期一

UNITY Motion Trail Script!!



原理:
遊戲用到的Motion Trail原理其實很簡單,就是利用一個Queue,將兩參考點於每個Frame的位置記錄下來,這記錄通常是有條件的,也許是兩參考點與上一個Frame的紀錄比較距離,若高過某一threadhould就push in,此外在每個Frame裡也檢查已經在Queue中的其它點,生命周期是不是已經到了,如果是就將這次的紀錄pop out。
Pseudo Code如下所示:

接下來的問題就是,將這Queue裡的“點”加上建構三角面的Index及計算出貼圖UV,進行Rendering,即可得到兩點間的移動軌跡,加上貼圖就如同上圖所示了。Pseudo Code如下所示:
Update() {
    float now = Time.time;
    Vector3 P1 = m_CurPointA;
    Vector3 P2 = m_CurPointB;
    Vector3 preP1 = m_Queue[0].PointA;
    Vector3 preP2 = m_Queue[0].PointB;

    if( (P1 - preP1).length > 0.5f ||
         (P2 - preP2).length > 0.5f ) {
         m_Queue.push( p1, p2, now );
    }

    while( m_Queue.count > 0 &&
                now - m_Queue[end].time > 1.0f ) {
         m_Queue.pop( end );
    }

//Generate triangles indices:
trailMesh.triangles = new int[(m_Queue.count-1)*2*3];
for( int i=0; i trailMesh.triangles[i * 6 + 0] = i * 2; i++ ) {
    trailMesh.triangles[i * 6 + 0] = i * 2;
    trailMesh.triangles[i * 6 + 1] = i * 2 + 1;
    trailMesh.triangles[i * 6 + 2] = i * 2 + 2;

    trailMesh.triangles[i * 6 + 3] = i * 2 + 2;
    trailMesh.triangles[i * 6 + 4] = i * 2 + 1;
    trailMesh.triangles[i * 6 + 5] = i * 2 + 3;
}
}
進階修飾:
如果只單純的這樣產生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如下所示:
public static TrailSection Catmull_Rom(
TrailSection p0, TrailSection p1,
TrailSection p2, TrailSection p3,
float t )
{
     TrailSection section = new TrailSection();

     float t2 = t * t;
     float t3 = t2 * t;
     float a0 = -t3 + 2*t2 - t;
     float a1 = 3*t3 - 5*t2 + 2;
     float a2 = -3*t3 + 4*t2 + t;
     float a3 = t3 - t2;

     section.pointS = (a0*p0.pointS + a1*p1.pointS + a2*p2.pointS + a3*p3.pointS) * 0.5f;
     section.pointE = (a0*p0.pointE + a1*p1.pointE + a2*p2.pointE + a3*p3.pointE) * 0.5f;
     section.time = (a0*p0.time + a1*p1.time + a2*p2.time + a3*p3.time) * 0.5f;

     return section;
}


完整Script:
MotionTrail.cs


[小編 碎碎念] 
如果你覺得這篇文章寫的不錯,請給我們一個 "贊",加油打氣吧! ^__^



作者:Bric Lin, Email: ericlin09@gmail.com
曾任職台灣某遊戲公司研發Game Engine,為書籍“OGRE 入門指南”的譯者之一,專攻Rendering技術與遊戲開發,目前為獨立開發團隊CocosPlay主程式

沒有留言:

張貼留言