Effect(一)—— fyRibbonTrail

来源:互联网 发布:linux提权 编辑:程序博客网 时间:2024/06/08 12:30

目录为:Assets/Scripts/Effect/fyParticleSystem/目录下
fyRibbonTrail.cs

这个类是所有丝带特效的基类,
在这里面用代码生成丝带mesh,并控制颜色.
代码如下:

using UnityEngine;using System.Collections.Generic;[System.Serializable]public class ColorKey{    public Color color;    public float time;    //构造函数    public ColorKey()    {        time = 1.0f;        color = new Color (1.0f, 1.0f, 1.0f, 1.0f);    }    //构造函数    public ColorKey (Color color, float time)    {        this.color = color;        this.time = time;    }}//继承Monopublic class fyRibbonTrail: MonoBehaviour{    //最大Ribbon段数    public int maxElement = 10;    //Ribbon每段的宽度    public float segWidth = 2.0f;    //Ribbon每段的长度    public float segLength = 1.0f;    //对象Transform    public Transform source = null;    //对象    public GameObject renderObj = null;    //UV重复长度    public float mUVLength = 1.0f;    //Mesh    protected Mesh mMesh = null;    //MeshRederer    protected MeshRenderer mMeshRender = null;    //纹理旋转矩阵    protected Matrix4x4 mMatrix = Matrix4x4.identity;    //偏移位置    public Vector2 mOffset = new Vector2 (0, 0);    //旋转位置    public float mOffRot = 0;    //平移    public Vector2 mTranslate = new Vector2 (0, 0);    //缩放    public Vector2 mScale = new Vector2 (1, 1);    //旋转    public float mRotate = 0.0f;    //设置周期时间    public float mColorPeriodTime = 0.0f;    public float mColorCurTime = 0;    //颜色渐变    //这颜色估计要自己指定    public ColorKey[] colorKey = new ColorKey[5];    //保存对应的shader    public Shader mShader = null;    //保存对应的Texture2D    public Texture2D mTexture = null;    //朝向类型    public enum OrientType    {        World_Type,        BillBoard_Type    }    //纹理寻址类型    public enum MaterialAddressType    {        Common_Type,        //普通纹理寻址        Sequence_Type,      //序列帧寻址        Repeat_Type,        //重复寻址    }    //Blend类型    public enum BlendType    {        Replace_Type,        Alpha_Type,        Additive_Type,        Distort_Additive,    }    //朝向    public OrientType mOrientType = OrientType.World_Type;    //纹理寻址类型    public MaterialAddressType mMaterialType = MaterialAddressType.Common_Type;    //blend type    public BlendType mBlendType = BlendType.Additive_Type;    public Vector3 mNormal = new Vector3 (0, 1, 0);    //Ribbon Segment列表    protected Vector3[] elemPosPool;    protected Vector2[] elemUVPool;    protected Color[] elemColorPool;    //是否创建完成    protected bool bCreated = false;    void Start()    {        //从这里看来这个脚本要挂到Object上去        renderObj = this.gameObject;        source = renderObj.transform;        //运行状态,已经有Mesh数据,不需要重新创建        ReCreate ();        //初始变换矩阵        InitMatrix ();    }    //Matrix初始化    public void InitMatrix()    {        //初始偏移        //单位矩阵        Matrix4x4 xlate = Matrix4x4.identity;        if (mOffset.x != 0 || mOffset.y != 0)        {            //x            xlate.m03 = mOffset.x;            //y            xlate.m13 = mOffset.y;        }        //初始旋转        Matrix4x4 rotMatrix = Matrix4x4.identity;        if (mOffRot != 0)        {            //把度数转为弧度            float theta = mOffRot * Mathf.Deg2Rad;            float cosTheta = Mathf.Cos (theta);            float sinTheta = Mathf.Sin (theta);            //绕Z轴旋转---------------------------            //cos -sin 0  0            //sin cos  0  0            //0    0   1  0              //0    0   0  1            //填充旋转矩阵            rotMatrix.m00 = cosTheta;            rotMatrix.m01 = -sinTheta;            rotMatrix.m10 = sinTheta;            rotMatrix.m11 = cosTheta;            //-----------------------------------            // Offset center of rotation to center of texture            //x translate            rotMatrix.m03 = 0.5f + ((-0.5f * cosTheta) - (-0.5f * sinTheta));            //y translate            rotMatrix.m13 = 0.5f + ((-0.5f * sinTheta) + (-0.5f * cosTheta));        }        //旋转和平移联结起来        mMatrix = xlate * rotMatrix;        //设置旋转效果        if (mMeshRender != null)        {            //编辑模式            if (!Application.isPlaying)            {                //sharedMaterial:得到原始的material,任何改变都会影响到引用这个material的其他物体                if (mMeshRender.sharedMaterial != null)                {                    //设置旋转效果                    mMeshRender.sharedMaterial.SetMatrix ("_TransMatrix", mMatrix);                }            }            //运行模式            else            {                //material:得到一个副本,这个material改变,并不影响其他引用改变之前的material的物体                if (mMeshRender.material != null)                {                    //把transfom传到shader里面去                    mMeshRender.material.SetMatrix ("_TransMatrix", mMatrix);                }            }        }    }    //Update is called once per frame    void Update()    {        //更新颜色        UpdateColor (Time.deltaTime);        //更新Ribbon        //由子类实现        UpdateRibbon (Time.deltaTime);        //更新变换矩阵        UpdateMatrix ();    }    //创建Ribbon    virtual public void ReCreate()    {        //检测源物体        if (maxElement < 1)        {            Debug.LogError ("the ribbon max element must be more than 0!");            return;        }        renderObj.name = "fyRibbon";        //获取MeshFilter,准获取Mesh        MeshFilter mf = gameObject.GetComponent<MeshFilter> ();        //没有就创建        if (mf == null)        {            mf = renderObj.AddComponent<MeshFilter> ();            //在面板中不可编辑            mf.hideFlags = HideFlags.NotEditable;        }        //获取MeshRenderer        MeshRenderer mr = gameObject.GetComponent<MeshRenderer> ();        //没有就创建        if (mr == null)        {            mr = renderObj.AddComponent<MeshRenderer> ();            //关闭投影            mr.castShadows = false;            //关闭接收阴影            mr.receiveShadows = false;            //设置不可编辑状态            mr.hideFlags = HideFlags.NotEditable;        }        mMeshRender = mr;        //创建mesh        if (mf.sharedMesh == null)        {            mf.sharedMesh = new Mesh ();        }        mMesh = mf.sharedMesh;        //组件不可见        //mf.hideFlags = HideFlags.HideInInspector;        //创建RibbonMesh        CreateRibbonMesh (mf.sharedMesh);        //编辑状态        if (!Application.isPlaying)        {            //第一次创建            if (mMeshRender.sharedMaterial == null)            {                Texture2D defaultTex = Resources.Load ("effect/test/flare") as Texture2D;                //设置默认shader                if (mShader == null)                {                    //修改为默认材质以及贴图                    Shader shader = Shader.Find ("fyShader/Additive");                    mShader = shader;                    mMeshRender.sharedMaterial = new Material (shader);                }                //设置默认texture                if (mTexture == null)                {                    mTexture = defaultTex;                    mMeshRender.sharedMaterial.SetTexture ("_MainTex", defaultTex);                }            }            if (mShader != null)            {                mMeshRender.sharedMaterial = new Material (mShader);                if (mTexture != null)                {                    mMeshRender.sharedMaterial.SetTexture ("_MainTex", mTexture);                }            }        }        //运行状态        else        {            if (mShader != null)            {                mMeshRender.material = new Material (mShader);                if (mTexture != null)                {                    mMeshRender.material.SetTexture ("_MainTex", mTexture);                }            }        }        bCreated = true;    }    //改变贴图    public void ChangeTexture(Texture2D tex)    {        //保存贴图        mTexture = tex;        if (mMeshRender != null && mMeshRender.sharedMaterial != null)        {            mMeshRender.sharedMaterial.SetTexture ("_MainTex", tex);        }    }    //其实就是创建mesh    //创建RibbonMesh    void CreateRibbonMesh(Mesh mesh)    {        //局部坐标系 法线方向        //指向y轴正半轴        Vector3 normal = new Vector3 (0, 1, 0);        Vector3 sourcePos = new Vector3 (0, 0, 0);        Debug.Log ("source pos " + sourcePos.ToString ());        //初始RibbonElement Pool        elemPosPool = new Vector3[(maxElement + 1) * 2];        elemUVPool = new Vector2[(maxElement + 1) * 2];        elemColorPool = new Color[(maxElement + 1) * 2];        //初始方向        //指向z轴正半轴        Vector3 dir = new Vector3 (0, 0, 1);        //这里Normalize没什么意义        dir.Normalize ();        mesh.Clear ();        //默认初始长度,编辑时候需要处理        float length = 0.0001f;        //默认maxElement = 10        //segLength = 1        //length = 10        length = maxElement * segLength;        //这里很奇怪        //deltaLength = 1        float deltaLength = length / maxElement;        //默认结束位置        Vector3 endPos = sourcePos + dir * length;        //数据点        //i表示element段数        for (int i = 0; i < elemPosPool.Length / 2.0f; i++)        {            //距离起始点的距离 i * deltaLengh            float vLength = i * deltaLength;            //当前段的起始pos            Vector3 vPos = endPos - dir * vLength;            //垂直法向            //dir(0, 0, 1)            //normal(0, 1, 0)            //vDir = (-1, 0, 0);            Vector3 vDir = Vector3.Cross (dir, normal);            //当前段的中心点坐标            Vector3 p1 = vPos + vDir * segWidth / 2.0f;            //上一段的中心店坐标,不过上一段存不存在无所谓,只是算距离得出的            Vector3 p2 = vPos - vDir * segWidth / 2.0f;            //保存顶点数据            //存储当前段的中心点            elemPosPool [i * 2] = p1;            elemColorPool [i * 2] = new Color (1, 1, 1, 1);            //存储上一段的中心点            elemPosPool [i * 2 + 1] = p2;            elemColorPool [i * 2 + 1] = new Color (1, 1, 1, 1);            //对UV没那么了解,这里看着有点迷            //Repeat_Type            if (mMaterialType == MaterialAddressType.Repeat_Type)            {                //默认mUVLength = 1                //vLength几乎等于当前i                float uv = vLength / mUVLength;                elemUVPool [i * 2] = new Vector2 (-uv, 1.0f);                elemUVPool [i * 2 + 1] = new Vector2 (-uv, 0.0f);            }            else            {                //根据UV类型                //跟上面相比,少了1                elemUVPool [i * 2] = new Vector2 (1.0f - vLength / length, 1.0f);                elemUVPool [i * 2 + 1] = new Vector2 (1.0f - vLength / length, 0.0f);            }        }        //这里定义三角形index        int[] index = new int[maxElement * 2 * 3];        for (int i = 0; i < maxElement; i++)        {            int index0 = i * 2;            int index1 = i * 2 + 1;            //其实就是 i * 2 + 2            int index2 = (i + 1) * 2;            int index3 = (i + 1) * 2 + 1;            //三角形条带            //  0 ---- 1            //        /            //      2  ----- 3            index [i * 6 + 0] = index0;            index [i * 6 + 1] = index1;            index [i * 6 + 2] = index2;            index [i * 6 + 3] = index3;            index [i * 6 + 4] = index2;            index [i * 6 + 5] = index1;        }        //顶点        mesh.vertices = elemPosPool;        //UV        mesh.uv = elemUVPool;        //Color        mesh.colors = elemColorPool;        //三角形index        mesh.triangles = index;        //重新计算法线        mesh.RecalculateNormals ();        //重新计算边界体积        mesh.RecalculateBounds ();        //Mesh优化,运行时会变快,不过这函数只在自己代码生成mesh时用        mesh.Optimize ();    }    //更新变换矩阵    public virtual void UpdateMatrix()    {        if (mMeshRender != null)        {            bool updateMatrix = false;            //先缩放再平移再旋转            //缩放            if (mScale.x != 1 || mScale.y != 1)            {                //Offset to center of texture                //缩放                mMatrix.m00 /= mScale.x;                mMatrix.m11 /= mScale.y;                //Skip matrix concat since first matrix update                //x translate                mMatrix.m03 = (-0.5f * mMatrix.m00) + 0.5f;                //y translate                mMatrix.m13 = (-0.5f * mMatrix.m11) + 0.5f;                updateMatrix = true;            }            //平移            if (mTranslate.x != 0 || mTranslate.y != 0)            {                Matrix4x4 xlate = Matrix4x4.identity;                xlate.m03 = mTranslate.x;                xlate.m13 = mTranslate.y;                //联结                mMatrix = xlate * mMatrix;                updateMatrix = true;            }            //旋转            if (mRotate != 0)            {                Matrix4x4 rotMatrix = Matrix4x4.identity;                float theta = mRotate * Mathf.Deg2Rad;                float cosTheta = Mathf.Cos (theta);                float sinTheta = Mathf.Sin (theta);                rotMatrix.m00 = cosTheta;                rotMatrix.m01 = -sinTheta;                rotMatrix.m10 = sinTheta;                rotMatrix.m11 = cosTheta;                //Offset center of rotation to center of texture                rotMatrix.m03 = 0.5f + ((-0.5f * cosTheta) - (-0.5f * sinTheta));                rotMatrix.m13 = 0.5f + ((-0.5f * sinTheta) + (-0.5f * cosTheta));                mMatrix = rotMatrix * mMatrix;                updateMatrix = true;            }            //设置旋转效果            //只要改变了,updateMatrix这个标志就会为true            if (updateMatrix)            {                //编辑模式                if (!Application.isPlaying)                {                    if (mMeshRender.sharedMaterial != null)                    {                        //设置效果                        mMeshRender.sharedMaterial.SetMatrix ("_TransMatrix", mMatrix);                    }                }                //运行模式                else                {                    if (mMeshRender.material != null)                    {                        mMeshRender.material.SetMatrix ("_TransMatrix", mMatrix);                    }                }            }        }    }    //更新颜色    public virtual void UpdateColor(float deltaTime)    {        if (mColorPeriodTime == 0)        {            return;        }        //计算颜色值,颜色有效        Color gColor = new Color ();        mColorCurTime += deltaTime;        //计算当前颜色时间        if (mColorCurTime > mColorPeriodTime)        {            mColorCurTime = 0;        }        //计算颜色        gColor = GetGradientColor ();        //Debug.Log("color" + gColor.ToString());        //遍历修改数据点        //改变颜色        for (int i = 0; i < elemPosPool.Length / 2.0f; i++)        {            elemColorPool [i * 2] = gColor;            elemColorPool [i * 2 + 1] = gColor;        }        mMesh.colors = elemColorPool;    }    //根据当前时间计算颜色    public virtual Color GetGradientColor()    {        Color gcolor = new Color ();        //计算比例值        float factor = mColorCurTime / mColorPeriodTime;        //计算color值        //colorKey数组长度默认等于5        int colorLength = colorKey.Length;        for (int i = 0; i < colorLength - 1; i++)        {            //当前            ColorKey key1 = colorKey [i % colorLength];            //下一个            ColorKey key2 = colorKey [(i + 1) % colorLength];            //计算距离            float dist = key2.time - key1.time;            //其实这里就是在按线性插值来混合颜色            if (factor >= key1.time && factor <= key2.time)            {                float ff = (factor - key1.time) / dist;                // key1 --------------------------key2                //          factor                gcolor = key1.color * (1 - ff) + key2.color * ff;                break;            }        }        return gcolor;    }    //更新Ribbon    //由子类继承    public virtual void UpdateRibbon(float deltaTime)    {    }    //重置    public virtual void Reset()    {        if (mMesh == null)        {            return;        }        //重置位置        Vector3 sourcePos = source.position;        //初始RibbonElement Pool        elemPosPool = new Vector3[(maxElement + 1) * 2];        elemUVPool = new Vector2[(maxElement + 1) * 2];        //初始方向        Vector3 dir = new Vector3 (0, 0, 1);        //仍然的无意义        dir.Normalize ();        //默认初始长度        float length = maxElement * segLength;        float deltaLength = length / maxElement;        //默认结束位置        Vector3 endPos = sourcePos + dir * length;        float totalElemLength = maxElement * segLength;        //真实最大长度        float realLength = totalElemLength > length ? length : totalElemLength;        //遍历修改数据点        for (int i = 0; i < elemPosPool.Length / 2.0f; i++)        {            float vLength;            if (i * segLength > length)            {                vLength = length;            }            else            {                vLength = i * segLength;            }            Vector3 vPos = endPos - dir * vLength;            //垂直法向            Vector3 vDir = Vector3.Cross (dir, mNormal);            Vector3 p1 = vPos + vDir * segWidth / 2.0f;            Vector3 p2 = vPos - vDir * segWidth / 2.0f;            //转为局部坐标            p1 -= sourcePos;            p2 -= sourcePos;            //重置顶点数据            elemPosPool [i * 2] = p1;            elemUVPool [i * 2] = new Vector2 (1.0f - vLength / realLength, 1.0f);            elemColorPool [i * 2] = new Color (1, 1, 1, 1);            elemPosPool [i * 2 + 1] = p2;            elemUVPool [i * 2 + 1] = new Vector2 (1.0f - vLength / realLength, 0.0f);            elemColorPool [i * 2 + 1] = new Color (1, 1, 1, 1);        }        mMesh.vertices = elemPosPool;        mMesh.uv = elemUVPool;        mMesh.RecalculateNormals ();        mMesh.RecalculateBounds ();        mMesh.Optimize ();        //刷新矩阵数据        mMatrix = Matrix4x4.identity;        InitMatrix ();        mColorCurTime = 0;        Debug.Log ("reset");    }}
原创粉丝点击