12 第1页 | 共2 页下一页
返回列表 发新帖
查看: 5599|回复: 12
打印 上一主题 下一主题

Trail Arc Renderer刀光拖尾脚本

[复制链接]

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

跳转到指定楼层
楼主
发表于 2011-9-13 08:51:47 |只看该作者 |倒序浏览
Trail Arc Renderer刀光拖尾脚本

Trail Arc Renderer

From Unify Community Wiki

Jump to: navigation, search

author: Nick Gronow (Stick)



Contents [hide]

1 Description

1.1 Features

1.2 One-Time Use

1.3 Image

2 C# - TrailArc.cs





[edit] Description

Alright, this is my last trail renderer I will post (wink). This trail renderer is designed specifically with melee trails in mind. It will track the path of its parent object and create a fluid arc between its saved points. You can set the distance between saved points, which gives you control over the accuracy of the interpolation. Increasing distance will produce more smoothed out arcs, where reducing distance will increase accuracy to the actual path.



[edit] Features

Set the fade out time (lifetime) when the trail is done emitting

Control when its done by simply turning off the "emit" property

Set any number of colors

Set any number of widths

Autodestructs when faded out

Set the interpolation distance

Set whether it always faces the camera

Set the number of segments to place between each interpolation distance

[edit] One-Time Use

This trail renderer is designed to be a one-time use component. There are several reasons for this, based on the way it is designed for optimization. When emitting is set to false, the trail renderer will stop adding new segments and fade out. The fade out time is set to the lifetime.



[edit] Image





[edit] C# - TrailArc.cs







using UnityEngine;



using System.Collections;



public class TrailArc : MonoBehaviour

{

   

    int savedIndex;

    int pointIndex;

   

    // Material - Particle Shader with "Tint Color" property

    public Material material;

   

    // Emit

    public bool emit

    {

        get { return Emit; }

        set { Emit = value; }

    }

    bool Emit = true;

    bool emittingDone = false;

   

    //Minimum velocity (script terminates)

    public float minVel = 10;

   

    // Facing

    public bool faceCamera = true;

   

    // Lifetime of each segment

    public float lifetime = 1;

    float lifeTimeRatio = 1;

    float fadeOutRatio;



    // Colors

    public Color[] colors;



    // Widths

    public float[] widths;

   

    // Optimization

    public float pointDistance = 0.5f;

    float pointSqrDistance = 0;

    public int segmentsPerPoint = 4;

    float tRatio;



    // Print Output

    public bool printResults = false;

    public bool printSavedPoints = false;

    public bool printSegmentPoints = false;

   

    // Objects

    GameObject trail = null;

    Mesh mesh = null;

    Material trailMaterial = null;

   

    // Points

    Vector3[] saved;

    Vector3[] savedUp;

    int savedCnt = 0;

    Vector3[] points;

    Vector3[] pointsUp;

    int pointCnt = 0;

   

    // Segment Appearance Normalization

    int displayCnt = 0;

    float lastPointCreationTime = 0;

    float averageCreationTime = 0;

    float averageInsertionTime = 0;

    float elapsedInsertionTime = 0;



    // Initialization

    bool initialized = false;

   

    void Start ()

    {

    if(gameObject.rigidbody.velocity.magnitude < minVel)

            Destroy(this);

        

        // Data Inititialization

        saved = new Vector3[60];

        savedUp = new Vector3[saved.Length];

        points = new Vector3[saved.Length * segmentsPerPoint];

        pointsUp = new Vector3[points.Length];

        tRatio = 1f / (segmentsPerPoint);

        pointSqrDistance = pointDistance * pointDistance;

      

        // Create the mesh object

        trail = new GameObject("Trail");

        trail.transform.position = Vector3.zero;

        trail.transform.rotation = Quaternion.identity;

        trail.transform.localScale = Vector3.one;

        MeshFilter meshFilter = (MeshFilter) trail.AddComponent(typeof(MeshFilter));

        mesh = meshFilter.mesh;

        trail.AddComponent(typeof(MeshRenderer));

        trailMaterial = new Material(material);

        fadeOutRatio = trailMaterial.GetColor("_TintColor").a;

        trail.renderer.material = trailMaterial;

    }

   

    void printPoints()

    {

        if(savedCnt == 0)

            return;

        string s = "Saved Points at time " + Time.time + ":
";

        for(int i = 0; i < savedCnt; i++)

            s += "Index: " + i + "        Pos: " + saved + "
";

        print(s);

    }



    void printAllPoints()

    {

        if(pointCnt == 0)

            return;

        string s = "oints at time " + Time.time + ":
";

        for(int i = 0; i < pointCnt; i++)

            s += "Index: " + i + "        Pos: " + points + "
";

        print(s);

    }



    void findCoordinates(int index)

    {

        if(index == 0 || index >= savedCnt-2)

            return;

        Vector3 P0 = saved[index-1];

        Vector3 P1 = saved[index];

        Vector3 P2 = saved[index+1];

        Vector3 P3 = saved[index+2];

        Vector3 T1 = 0.5f * (P2 - P0);

        Vector3 T2 = 0.5f * (P3 - P1);

        int pointIndex = index * segmentsPerPoint;

        for(int i = pointIndex; i < pointIndex+segmentsPerPoint; i++)

        {

            float t = (i-pointIndex) * tRatio;

            float t2 = t*t;

            float t3 = t2*t;

            float blend1 = 2*t3 - 3*t2 + 1;

            float blend2 = 3*t2 - 2*t3;

            float blend3 = t3 - 2*t2  + t;

            float blend4 = t3 - t2;

            int pntInd = i - segmentsPerPoint;

            points[pntInd] = blend1*P1 + blend2*P2 + blend3*T1 + blend4*T2;

            pointsUp[pntInd] = Vector3.Lerp(savedUp[index], savedUp[index+1], t);

        }

        pointCnt = pointIndex;

    }

   

    void Update ()

    {

        try

        {

            Vector3 position = transform.position;

            // Wait till the object is active (update called) and emitting

            if( ! initialized && Emit)

            {

                // Place the first point behind this as a starter projected point

                saved[savedCnt] = transform.TransformPoint(0,0,-pointDistance);

                savedUp[savedCnt] = transform.up;

                savedCnt++;

                // Place the second point at the current position

                saved[savedCnt] = position;

                savedUp[savedCnt] = transform.up;

                savedCnt++;

                // Begin tracking the saved point creation time

                lastPointCreationTime = Time.time;

                initialized = true;

            }

           

            if(printSavedPoints)

                printPoints();

            if(printSegmentPoints)

                printAllPoints();

           

            // Emitting - Designed for one-time use

            if( ! Emit )

            {

                if( ! emittingDone && pointCnt > 0 )

                {

                    // Save two final points projected from the ending point

                    saved[savedCnt] = transform.TransformPoint(0,0,pointDistance);

                    savedUp[savedCnt] = transform.up;

                    savedCnt++;

                    findCoordinates(savedCnt-3);

                    // This makes the trail fill the actual entire path

                    saved[savedCnt] = transform.TransformPoint(0,0,pointDistance*2);

                    savedUp[savedCnt] = transform.up;

                    savedCnt++;

                    findCoordinates(savedCnt-3);

                }

                emittingDone = true;

            }

            if(emittingDone)

                Emit = false;

           

            if(Emit)

            {

               

                // Do we save a new point?

                if( (saved[savedCnt-1] - position).sqrMagnitude > pointSqrDistance)

                {

                    saved[savedCnt] = position;

                    savedUp[savedCnt] = transform.up;

                    savedCnt++;



                    // Calc the average point display time

                    if(averageCreationTime == 0)

                        averageCreationTime = Time.time - lastPointCreationTime;

                    else

                    {

                        float elapsedTime = Time.time - lastPointCreationTime;

                        averageCreationTime = (averageCreationTime + elapsedTime) * 0.5f;

                    }

                    averageInsertionTime = averageCreationTime * tRatio;

                    lastPointCreationTime = Time.time;



                    // Calc the last saved segment coordinates

                    if(savedCnt > 3)

                        findCoordinates(savedCnt-3);

                }

            }



            // Do we fade it out?

            if( ! Emit && displayCnt == pointCnt)

            {

                Color color = trailMaterial.GetColor("_TintColor");

                color.a -= fadeOutRatio * lifeTimeRatio * Time.deltaTime;

                if(color.a > 0)

                    trailMaterial.SetColor("_TintColor", color);

                else

                {

                    if(printResults)

                        print("Trail effect ending with a segment count of: " + pointCnt);

                    Destroy(trail);

                    Destroy(gameObject);

                }

                return;

            }

   

            // Do we display any new points?

            if(displayCnt < pointCnt)

            {

                elapsedInsertionTime += Time.deltaTime;

                while(elapsedInsertionTime > averageInsertionTime)

                {

                    if(displayCnt < pointCnt)

                        displayCnt++;

                    elapsedInsertionTime -= averageInsertionTime;

                }

            }



            // Do we render this?

            if(displayCnt < 2)

            {

                trail.renderer.enabled = false;

                return;

            }

            trail.renderer.enabled = true;

                       

            // Common data

            lifeTimeRatio = 1f / lifetime;

            Color[] meshColors;

           

            // Rebuild the mesh

            Vector3[] vertices = new Vector3[displayCnt * 2];

            Vector2[] uvs = new Vector2[displayCnt * 2];

            int[] triangles = new int[(displayCnt-1) * 6];

            meshColors = new Color[displayCnt * 2];

      

            float pointRatio = 1f / (displayCnt-1);

            Vector3 cameraPos = Camera.main.transform.position;

            for(int i = 0; i < displayCnt; i++)

            {

                Vector3 point = points;

                float ratio = i * pointRatio;

               

                // Color

                Color color;

                if(colors.Length == 0)

                    color = Color.Lerp(Color.clear, Color.white, ratio);

                else if(colors.Length == 1)

                    color = Color.Lerp(Color.clear, colors[0], ratio);

                else if(colors.Length == 2)

                    color = Color.Lerp(colors[1], colors[0], ratio);

                else

                {

                    float colorRatio = colors.Length - 1 - ratio * (colors.Length-1);

                    if(colorRatio == colors.Length-1)

                        color = colors[colors.Length-1];

                    else

                    {

                        int min = (int) Mathf.Floor(colorRatio);

                        float lerp = colorRatio - min;

                        color = Color.Lerp(colors[min+0], colors[min+1], lerp);

                    }

                }

                meshColors[i * 2] = color;

                meshColors[(i * 2) + 1] = color;

               

                // Width

                float width;

                if(widths.Length == 0)

                    width = 1;

                else if(widths.Length == 1)

                    width = widths[0];

                else if(widths.Length == 2)

                    width = Mathf.Lerp(widths[1], widths[0], ratio);

                else

                {

                    float widthRatio = widths.Length - 1 - ratio * (widths.Length-1);

                    if(widthRatio == widths.Length-1)

                        width = widths[widths.Length-1];

                    else

                    {

                        int min = (int) Mathf.Floor(widthRatio);

                        float lerp = widthRatio - min;

                        width = Mathf.Lerp(widths[min+0], widths[min+1], lerp);

                    }

                }



                // Vertices

                if(faceCamera)

                {

                    Vector3 from = i == displayCnt-1 ?  points[i-1]   : point;

                    Vector3 to = i == displayCnt-1 ?    point    : points[i+1];

                    Vector3 pointDir = to - from;

                    Vector3 vectorToCamera = cameraPos - point;

                    Vector3 perpendicular = Vector3.Cross(pointDir, vectorToCamera).normalized;

                    vertices[i * 2 + 0] = point + perpendicular * width * 0.5f;

                    vertices[i * 2 + 1] = point - perpendicular * width * 0.5f;

                }

                else

                {

                    vertices[i * 2 + 0] = point + pointsUp * width * 0.5f;

                    vertices[i * 2 + 1] = point - pointsUp * width * 0.5f;

                }

               

                // UVs

                uvs[i * 2 + 0] = new Vector2(ratio , 0);

                uvs[i * 2 + 1] = new Vector2(ratio, 1);

               

                if(i > 0)

                {

                    // Triangles

                    int triIndex = (i - 1) * 6;

                    int vertIndex = i * 2;

                    triangles[triIndex+0] = vertIndex - 2;

                    triangles[triIndex+1] = vertIndex - 1;

                    triangles[triIndex+2] = vertIndex - 0;

                  

                    triangles[triIndex+3] = vertIndex + 0;

                    triangles[triIndex+4] = vertIndex - 1;

                    triangles[triIndex+5] = vertIndex + 1;

                }

            }

            trail.transform.position = Vector3.zero;

            trail.transform.rotation = Quaternion.identity;

            mesh.Clear();

            mesh.vertices = vertices;

            mesh.colors = meshColors;

            mesh.uv = uvs;

            mesh.triangles = triangles;

        }

        catch(System.Exception e)

        {

            print(e);

        }

    }

}
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

Asen    

867

主题

0

听众

1万

积分

外协人员

Rank: 7Rank: 7Rank: 7

纳金币
17488
精华
1
沙发
发表于 2011-9-14 08:43:48 |只看该作者
回复

使用道具 举报

5969

主题

1

听众

39万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

板凳
发表于 2012-1-21 23:28:55 |只看该作者
时间穿越一年四季,牵挂紧紧攥在手里;平凡忙碌又到年底,无形中把自己当成了工具;松一松疲惫的身体,梳一梳心灵的沉积。挣钱重要,更要保重自己!
回复

使用道具 举报

tc    

5089

主题

1

听众

33万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2012-2-22 23:30:40 |只看该作者
呵呵,很好,方便罗。
回复

使用道具 举报

tc    

5089

主题

1

听众

33万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

5#
发表于 2012-4-1 23:28:45 |只看该作者
先顶上去,偶要高亮加精鸟!
回复

使用道具 举报

462

主题

1

听众

31万

积分

首席设计师

Rank: 8Rank: 8

纳金币
2
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

6#
发表于 2012-4-11 23:26:01 |只看该作者
谢谢楼主,真是太实用了
回复

使用道具 举报

markq    

511

主题

1

听众

1万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
15839
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

7#
发表于 2012-4-12 22:48:30 |只看该作者
不错 非常经典 实用
回复

使用道具 举报

tc    

5089

主题

1

听众

33万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

8#
发表于 2012-4-25 23:19:15 |只看该作者
楼主收集的可真全哦
回复

使用道具 举报

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

9#
发表于 2012-7-25 23:27:42 |只看该作者
不错哦,顶一下......
回复

使用道具 举报

5969

主题

1

听众

39万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

10#
发表于 2012-9-23 23:44:23 |只看该作者
很经典,很实用,学习了!
回复

使用道具 举报

12 第1页 | 共2 页下一页
返回列表 发新帖
您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-29 16:27 , Processed in 0.109554 second(s), 29 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部