Author : polygoo


Reply
Reply
 
Thread Tools Display Modes
Goeddy's Avatar
Old (#1)
so im working on a fighting-game in unity and i want to achieve an effect like this for our weapons.
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:

it has transparency and self-illumination.
Offline , triangle, 371 Posts, Join Date Jun 2011, Location germany  
   Reply With Quote

Maph's Avatar
Old (#2)
What you're looking for is called TrailRenderer
http://unity3d.com/support/documenta...lRenderer.html
Offline , polycounter, 952 Posts, Join Date Mar 2011, Location Nottingham, United Kingdom  
   Reply With Quote

Goeddy's Avatar
Old (#3)
yeshhh exactly, thank you very much :]
Offline , triangle, 371 Posts, Join Date Jun 2011, Location germany  
   Reply With Quote

cupsster's Avatar
Old (#4)
TrailArc.cs
author: Nick Gronow (Stick)

Code:
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);
        }
    }
}
Offline , triangle, 349 Posts, Join Date Jan 2010, Location Slovakia Send a message via Skype™ to cupsster  
   Reply With Quote

Elyaradine's Avatar
Old (#5)
If you get the look you want, please post screenshots!

I've always struggled with trails. <_<
Generalist and TA at Luma Arcade
Houdini/Mixamo entry
Offline , triangle, 287 Posts, Join Date Apr 2009, Location South Africa  
   Reply With Quote

Goeddy's Avatar
Old (#6)
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^^
Offline , triangle, 371 Posts, Join Date Jun 2011, Location germany  
   Reply With Quote

warby's Avatar
Old (#7)
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 !

Last edited by warby; 02-29-2012 at 04:42 AM..
Offline , polycounter, 836 Posts, Join Date Dec 2004, Location boston hamburg copenhagen  
   Reply With Quote

Goeddy's Avatar
Old (#8)
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.
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.

Last edited by Goeddy; 03-08-2012 at 03:16 AM..
Offline , triangle, 371 Posts, Join Date Jun 2011, Location germany  
   Reply With Quote

justifun's Avatar
Old (#9)
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
Offline , null, 18 Posts, Join Date Jan 2012,  
   Reply With Quote

Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Copyright 1998-2012 A. Risch