Home Unity

lasersword trail how to?

greentooth
Offline / Send Message
Goeddy greentooth
so im working on a fighting-game in unity and i want to achieve an effect like this for our weapons.4515d1184941747-tales-of-symphonia-knight-ratatosk-dawn-new-world-tos2.jpg
we have laser-swords that look like this, and it would be totaly epic if we could achieve a trail effect like the one shown above.
actualy it has to look somewhat like that, not exactly.
BUT it has to work on mobile.
i dont know if i could achive this with a shader mady by scrumpy´s editor, but that would be perfect cause i know that defently works on mobile.

so what it needs to do is keep a part of the last 5 or so frames rendered, blendet over the current frame.
that would be nearly perfect.

if there is no way to do that via shader i gues i´ll have to animate something like this by hand, but this is what i am trying to avoid.

also the sword i would you looks like this:
scrn96.jpg
it has transparency and self-illumination.

Replies

  • Maph
  • Goeddy
    Offline / Send Message
    Goeddy greentooth
    yeshhh exactly, thank you very much :]
  • cupsster
    Offline / Send Message
    cupsster polycounter lvl 11
    TrailArc.cs
    author: Nick Gronow (Stick)
    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 + ":\n";
            for(int i = 0; i < savedCnt; i++)
                s += "Index: " + i + "\tPos: " + saved[i] + "\n";
            print(s);
        }
    
        void printAllPoints()
        {
            if(pointCnt == 0)
                return;
            string s = "Points at time " + Time.time + ":\n";
            for(int i = 0; i < pointCnt; i++)
                s += "Index: " + i + "\tPos: " + points[i] + "\n";
            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[i];
                    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[i] * width * 0.5f;
                        vertices[i * 2 + 1] = point - pointsUp[i] * 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);
            }
        }
    }
    
  • Elyaradine
    Offline / Send Message
    Elyaradine polycounter lvl 11
    If you get the look you want, please post screenshots! :D

    I've always struggled with trails. <_<
  • Goeddy
    Offline / Send Message
    Goeddy greentooth
    well i got it to work, but only with a dummy effect.
    need to wait till the attack animations are done so i can tweak it the way i want it to look like.
    will post screens and maby vids when i get it to shine^^
  • warby
    Offline / Send Message
    warby polycounter lvl 18
    that script there is a huge troll face its not working at all

    /edit never mind i am just a noob it works great but the default color should not be black with 0 alpha ! default should not be something thats invisible !
  • Goeddy
    Offline / Send Message
    Goeddy greentooth
    so i got the effect i wanted.
    dont know yet how it will look like with proper animation, but should turn out realy cool.
    here is a small test i made.
    sry for the quality, youtube smashed it.
    [ame="http://www.youtube.com/watch?v=dbhEoqt1htM&quot;]trailtest.avi - YouTube[/ame]
    i gues this will eat up way too much performance for phones so i´ll give cupsster´s script a chance when we go for optimizing to the max.
    right now we are spitting out beauty as much as we can, for we are creating the first trailer at the moment.
  • justifun
    Offline / Send Message
    justifun polycounter lvl 4
    There are 2 other free motion trail packages in the asset store. One is called pocket Rpg and the other is just called motion trails i think.

    worth a look
Sign In or Register to comment.