武器拖尾的实现

转载说明:http://www.unitymanual.com/blog-2265-716.html


知识点 Mesh 

实现方式基本与技能冷却雷同
不同的是拖尾需要的不是定义固定数量的顶点去改变位置
而是动态的生成若干组顶点 每帧根据各顶点位置去描绘出需要的效果

定义一个效果顶点列表L
定义拖尾效果时间 T
定义一个拖尾光效的高度 H

在武器上附加一个空的gameObj 并修改其方向Y轴与武器平行 设其为点A

每帧记录当前点A的坐标 以及Y周方向偏移H的点坐标 并记录当前时间点 
将此帧记录信息存入L

遍历L列表 根据相邻两两个记录的4个顶点进行填充




在需要有拖尾效果的武器上附加一个空的GameObj 其位置最好在武器柄与刃交汇处 或者刃中心

Y轴与武器方向一致
并为其添加 MeshFilter、MeshRenderer组件 附加材质选择shader为Particles/Additive

创建拖尾脚本附加在GameObj上

原理篇有描述 就是在每帧记录当前帧的武器位置 朝向信息 并根据效果持续时间来记录消失时间点

如下图所示

图中为 武器挥出的三帧中 武器的位置状态  实体红线连接起来的区域为拖尾效果

绿色线条为设置的拖尾效果高度 1 2 3 4 5 6点为根据每帧拖尾组件所在的点 朝向 及高度计算的各个顶点位置

按照虚线绘制三角形 形成拖尾效果

当然了 拖尾效果 并不是时时刻刻都需要 所以我们需要在攻击动作的时候告知拖尾组件 需要绘制 这个时候才进行绘制


伪代码如下

其有内部成员变量

是否绘制状态 draw

信息记录列表 list

开始绘制{

draw=true

}

Update{

if(!draw)return;//当非描绘状态的时候直接跳出

记录当前位置 方向 持续时间信息 插入列表

根据列表算出顶点位置

设置Mesh顶点数组

设置Mesh各个顶点插值颜色

设置Mesh三角形数组

}

停止绘制{

draw=false;

清空Mesh信息

清空记录列表

}


注释比较清晰 就不做多的解释了


[code]csharpcode:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

//内部类 用于存储每帧光效点信息
class Wp
{
	public Vector3 point;
    public Vector3 upDir;
    public float time;
    public Wp() {

    }
    public Wp(Vector3 p, float t) {
        point = p;
        time = t;
    }
}

public class MyWeapon : MonoBehaviour {
	private List<Wp> sections = new List<Wp>();//光效点列表
	private Mesh mesh;
	public float time = 2.0f;
	public Color startColor = Color.white;
    public Color endColor = new Color(1, 1, 1, 0);
	private MeshRenderer meshRenderer;
    private Material trailMaterial;
	public float height = 2.0f;
    private bool isPlay = false;
	void Awake() {

        MeshFilter meshF = GetComponent(typeof(MeshFilter)) as MeshFilter;
        mesh = meshF.mesh;
        meshRenderer = GetComponent(typeof(MeshRenderer)) as MeshRenderer;
        trailMaterial = meshRenderer.material;
       

    }
	void Start () {
	
	}
	
	// 每帧进行显示更新
    void FixedUpdate()
    {
        if (isPlay)
        {
            Itterate(Time.time);
            UpdateTrail(Time.time);
        }
	}

    public void weStart() {
        isPlay = true;
    }

    public void weStop() {
        isPlay = false;
        ClearTrail();
    }
	
	public void Itterate(float itterateTime) { //记录拖尾点信息
   
        Vector3 position = transform.position;
        float now = itterateTime;

        // 将当前信息添加进列表
        if (sections.Count == 0 || (sections[0].point - position).sqrMagnitude > 0) {
            Wp section = new Wp();
            section.point = position;
            section.upDir = transform.TransformDirection(Vector3.up);//存入世界方向 
            section.time = now;
            sections.Insert(0, section);
            
        }
    }
    public void UpdateTrail(float currentTime) { // ** call once a frame **
    
        // 清空mesh显示
        mesh.Clear();
        //
        // 将超时点从列表移除
        while (sections.Count > 0 && currentTime > sections[sections.Count - 1].time + time) {
            sections.RemoveAt(sections.Count - 1);
        }
        // 两个点才能形成一个光效
        if (sections.Count < 2)
            return;
		//顶点 颜色 UV数组定义
        Vector3[] vertices = new Vector3[sections.Count * 2];
        Color[] colors = new Color[sections.Count * 2];
        Vector2[] uv = new Vector2[sections.Count * 2];
		//获取列表第一个点
        Wp currentSection = sections[0];
		//
        // 用矩阵代替transform 性能较高
        Matrix4x4 localSpaceTransform = transform.worldToLocalMatrix;
        // 设置 顶点 颜色 UV信息
        for (var i = 0; i < sections.Count; i++) {
            currentSection = sections[i];
            float u = 0.0f;
            if (i != 0)
                u = Mathf.Clamp01((currentTime - currentSection.time) / time);
			//
            // 获取朝向
            Vector3 upDir = currentSection.upDir;

            // 根据记录点 创建两个顶点
            vertices[i * 2 + 0] = localSpaceTransform.MultiplyPoint(currentSection.point);
            vertices[i * 2 + 1] = localSpaceTransform.MultiplyPoint(currentSection.point + upDir * height);

            uv[i * 2 + 0] = new Vector2(u, 0);
            uv[i * 2 + 1] = new Vector2(u, 1);

            // 计算插值颜色
            Color interpolatedColor = Color.Lerp(startColor, endColor, u);
            colors[i * 2 + 0] = interpolatedColor;
            colors[i * 2 + 1] = interpolatedColor;
        }

        // 创建三角形信息
        //      1---3---5
        //      |\  |\  |
        //      | \ | \ |
        //      |  \|  \|
        //      0---2---4
        int[] triangles = new int[(sections.Count - 1) * 2 * 3];
        for (int i = 0; i < triangles.Length / 6; i++) {
            triangles[i * 6 + 0] = i * 2;
            triangles[i * 6 + 1] = i * 2 + 1;
            triangles[i * 6 + 2] = i * 2 + 2;

            triangles[i * 6 + 3] = i * 2 + 2;
            triangles[i * 6 + 4] = i * 2 + 1;
            triangles[i * 6 + 5] = i * 2 + 3;
        }

        // 对mesh赋值
        mesh.vertices = vertices;
        mesh.colors = colors;
        mesh.uv = uv;
        mesh.triangles = triangles;
    }
    public void ClearTrail() {
		//清空显示对象
        if (mesh != null) {
            mesh.Clear();
            sections.Clear();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值