草庐IT

Unity武器拖尾插件:X-WeaponTrail

忆中异 2023-03-28 原文

X-WeaponTrail是一个很古老的程序化刀光插件,很早以前买了一直放在仓库没用上。最近不知道特效同学抽什么疯,突然不肯自己做刀光特效了,所以就把这个插件丢给他了。

image

用法

该插件的用法很简单,找到你的武器,把X-WeaponTrail预设拖到武器节点下,调整StartPointEndPoint,使其和武器对齐即可。

image
image
image

查看X Weapon Trail脚本,参数都比较直观,不过美术比较难理解的是Max FrameGranularity这2个参数,作者在他的主页给了如下说明:

image

MaxFrame可以理解为刀光拖尾的生命周期(长度),MaxFrame越大,拖尾越长。
Granularity可以理解为拖尾Mesh的顶点粒度,Granularity越大,顶点数越多,越平滑。


实现细节

趁着给美术介绍参数,我把这个刀光的实现代码看了一遍,有一些地方还是值得说一下。

首先,作者维护了一个队列mSnapshotList,用来保存刀光拖尾的位置信息。队列的index越小,则越接近当前武器的位置,index越大则越接近刀光的尾部,队列的长度由MaxFrame决定。

  void RecordCurElem() 
  {
    //TODO: use element pool to avoid gc alloc.
    //Element elem = new Element(PointStart.position, PointEnd.position);

    Element elem = mElemPool.Get();
    elem.PointStart = PointStart.position;
    elem.PointEnd = PointEnd.position;

    if (mSnapshotList.Count < MaxFrame) 
    {
      mSnapshotList.Insert(1, elem);
    }
    else 
    {
      mElemPool.Release(mSnapshotList[mSnapshotList.Count - 1]);
      mSnapshotList.RemoveAt(mSnapshotList.Count - 1);
      mSnapshotList.Insert(1, elem);
    }
  }

上面代码中的Element记录了一帧的位置信息,包括一开始我们设置的StartPointEndPoint,以及中间位置Pos

  public class Element 
  {
    public Vector3 PointStart;
    public Vector3 PointEnd;

    public Vector3 Pos 
    {
      get 
      {
        return (PointStart + PointEnd) / 2f;
      }
    }

    public Element(Vector3 start, Vector3 end) 
    {
      PointStart = start;
      PointEnd = end;
    }

    public Element() 
    {
    }
  }

有了MaxFrame帧的位置信息后,我们就可以生成Mesh了。假设我们没有做任何平滑处理,只是简单的根据每一帧的位置(StartPoint,Pos,EndPoint)补充顶点,已经可以生成刀光的Mesh了,但是会出现明显的折痕:

image

这个时候,插值平滑就非常必要了。作者采用的插值方式是CatmullRom,关于CatmullRom的说明,网上很多,这里直接贴代码:

        public static Vector3 CatmulRom(Vector3 T0, Vector3 P0, Vector3 P1, Vector3 T1, float f)
        {
            double DT1 = -0.5; 
            double DT2 = 1.5; 
            double DT3 = -1.5; 
            double DT4 = 0.5;

            double DE2 = -2.5; 
            double DE3 = 2; 
            double DE4 = -0.5;

            double DV1 = -0.5;
            double DV3 = 0.5;

            double FAX = DT1 * T0.x + DT2 * P0.x + DT3 * P1.x + DT4 * T1.x;
            double FBX = T0.x + DE2 * P0.x + DE3 * P1.x + DE4 * T1.x;
            double FCX = DV1 * T0.x + DV3 * P1.x;
            double FDX = P0.x;

            double FAY = DT1 * T0.y + DT2 * P0.y + DT3 * P1.y + DT4 * T1.y;
            double FBY = T0.y + DE2 * P0.y + DE3 * P1.y + DE4 * T1.y;
            double FCY = DV1 * T0.y + DV3 * P1.y;
            double FDY = P0.y;

            double FAZ = DT1 * T0.z + DT2 * P0.z + DT3 * P1.z + DT4 * T1.z;
            double FBZ = T0.z + DE2 * P0.z + DE3 * P1.z + DE4 * T1.z;
            double FCZ = DV1 * T0.z + DV3 * P1.z;
            double FDZ = P0.z;

            float FX = (float)(((FAX * f + FBX) * f + FCX) * f + FDX);
            float FY = (float)(((FAY * f + FBY) * f + FCY) * f + FDY);
            float FZ = (float)(((FAZ * f + FBZ) * f + FCZ) * f + FDZ);

            return new Vector3(FX, FY, FZ);
        }

调大Granularity后,之前的折痕平滑了很多。

image

关于顶点的UV映射

最后想再说一下顶点的UV映射问题。如果不考虑特效贴图,单纯的看顶点生成,效果如下:

image
image

注意上图的红色射线,射线的原点即StartPointEndPoint的中间点Pos,射线方向从StartPoint指向EndPoint

查看顶点更新的代码,我们发现顶点的UV设定如下:StartPoint的U是1,EndPoint的U是0,Pos的U是0.5。越接近刀光尾部的顶点,V越接近1。

                Vector3 pos = mSpline.InterpolateByLen(fadeT);
                Vector3 up = mSpline.InterpolateNormalByLen(fadeT);
                Vector3 pos0 = pos + (up.normalized * mTrailWidth * 0.5f);
                Vector3 pos1 = pos - (up.normalized * mTrailWidth * 0.5f);

                Debug.DrawRay(pos, up * 3, Color.red);

                // pos0
                pool.Vertices[baseIdx] = pos0;
                pool.Colors[baseIdx] = MyColor;
                uvCoord.x = 0f;
                uvCoord.y = uvSegment;
                pool.UVs[baseIdx] = uvCoord;

                //pos
                pool.Vertices[baseIdx + 1] = pos;
                pool.Colors[baseIdx + 1] = MyColor;
                uvCoord.x = 0.5f;
                uvCoord.y = uvSegment;
                pool.UVs[baseIdx + 1] = uvCoord;

                //pos1
                pool.Vertices[baseIdx + 2] = pos1;
                pool.Colors[baseIdx + 2] = MyColor;
                uvCoord.x = 1f;
                uvCoord.y = uvSegment;
                pool.UVs[baseIdx + 2] = uvCoord;

结合特效贴图

image

越接近刀光头部(武器)的顶点,其UV映射的区域越接近贴图的底部:

image

越接近刀光尾部的顶点,其UV映射的区域越接近贴图的上部:

image

结合实际效果查看刀光的强弱,就更清晰了:

image

有关Unity武器拖尾插件:X-WeaponTrail的更多相关文章

  1. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  2. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  3. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  4. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  5. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

  6. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  7. ruby-on-rails - 您希望看到哪些 Rails 插件? - 2

    您认为可以作为插件很好地存在于您的Rails应用程序中必须实现的哪些行为?您过去曾搜索过哪些插件功能但找不到?哪些现有的Rails插件可以改进或扩展,如何改进或扩展? 最佳答案 我希望在管理界面中看到一个引擎插件,它提供了应用程序中所有模型的仪表板摘要,以及可配置的事件图表。 关于ruby-on-rails-您希望看到哪些Rails插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questio

  8. ruby - vagrant 从 github 安装插件 - 2

    我们正在使用Vagrant进行部署,我们最终希望将此集群部署在Rackspace上。vagrant-rackspace插件是一个自然的选择,但它有一些错误,这些错误未包含在最新的0.1.1版本中(notablythatvagrantprovisiondoesn'twork)。我已经在我的personalfork中解决了这个问题通过合并其他人的工作来对存储库进行改造。是否可以从github安装vagrant插件?显而易见的事情没有奏效:[unix]$vagrantplugininstallvagrant-rackspace--plugin-sourcehttps://github.com

  9. Unity Shader 学习笔记(5)Shader变体、Shader属性定义技巧、自定义材质面板 - 2

    写在之前Shader变体、Shader属性定义技巧、自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用,方便后续回顾查看,如有以偏概全、不祥不尽之处,还望海涵。1、Shader变体先看一段代码......Properties{ [KeywordEnum(on,off)]USL_USE_COL("IsUseColorMixTex?",int)=0 [Toggle(IS_RED_ON)]_IsRed("IsRed?",int)=0}......//中间省略,后续会有完整代码 #pragmamulti_c

  10. 三分钟集成 TapTap 防沉迷 SDK(Unity 版) - 2

    三分钟集成Tap防沉迷SDK(Unity版)一、SDK介绍基于国家对上线所有游戏必须增加防沉迷功能的政策下,TapTap推出防沉迷SDK,供游戏开发者进行接入;允许未成年用户在周五、六、日以及法定节假日晚上8:00-9:00进行游戏,防沉谜时间段进入游戏会弹窗进行提示!开发环境要求:Unity2019.4或更高版本iOS10或更高版本Android5.0(APIlevel21)或更高版本🔗Unity集成Demo参考链接🔗UnityTapSDK功能体验APK下载链接二、集成前准备1.创建应用进入开发者后台,按照提示开始创建应用;2.开通服务在使用TDS实名认证和防沉迷服务之前,需要在上面创建的应

随机推荐