欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Unity实现角色受击身体边缘发光特效

程序员文章站 2022-06-03 15:17:21
游戏中经常需要制作角色受击打的身体边缘光效果,本文使用的方法是,给renderer叠加一个制作好的边缘光材质球,并通过脚本动态控制边缘光的渐变效果,表现出受击后的边缘光效果工程结构如下1 创建一个材质...

游戏中经常需要制作角色受击打的身体边缘光效果,本文使用的方法是,给renderer叠加一个制作好的边缘光材质球,并通过脚本动态控制边缘光的渐变效果,表现出受击后的边缘光效果

工程结构如下

1 创建一个材质球hittedmateffect.mat放在assets/resources/material目录中,使用transparentrim.shader
注意代码中用了resources.load,所以必须放在这个目录里,你可以改成别的方式
2 场景中创建一个sphere(球体),挂上runner脚本,运行,点击屏幕任意位置,球体就会表现出受击的边缘光效果了

Unity实现角色受击身体边缘发光特效

运行效果

Unity实现角色受击身体边缘发光特效

代码

transparentrim.shader

shader "effect/transparentrim" {
 properties{


 _rimcolor("rim color", color) = (0.5,0.5,0.5,0.5)
 _innercolor("inner color", color) = (0.5,0.5,0.5,0.5)
 _innercolorpower("inner color power", range(0.0,1.0)) = 0.5
 _rimpower("rim power", range(0.0,5.0)) = 2.5
 _alphapower("alpha rim power", range(0.0,8.0)) = 4.0
 _allpower("all power", range(0.0, 10.0)) = 1.0


 }
 subshader{
 tags { "queue" = "transparent" }

 cgprogram
 #pragma surface surf lambert alpha
 struct input {
 float3 viewdir;
 internal_data
 };
 float4 _rimcolor;
 float _rimpower;
 float _alphapower;
 float _alphamin;
 float _innercolorpower;
 float _allpower;
 float4 _innercolor;
 void surf(input in, inout surfaceoutput o) {
  half rim = 1.0 - saturate(dot(normalize(in.viewdir), o.normal));
  o.emission = _rimcolor.rgb * pow(rim, _rimpower)*_allpower + (_innercolor.rgb * 2 * _innercolorpower);
  o.alpha = (pow(rim, _alphapower))*_allpower;
 }
 endcg
 }
 fallback "vertexlit"
}

hittedmateffect.cs

// hittedmateffect.cs
using unityengine;
using system.collections;

public class hittedmateffect : monobehaviour
{
  bool mbactive = false;
  bool mbinit = false;
  material mmat = null;
  public float mlife;
  private static int s_innercolor = -1;
  private static int s_allpower = -1;
  private static int s_alphapower = -1;

  void awake()
  {
    s_innercolor = shader.propertytoid("_innercolor");
    s_allpower = shader.propertytoid("_allpower");
    s_alphapower = shader.propertytoid("_alphapower");
  }

  // use this for initialization
  /// <summary>
  /// 设置材质颜色
  /// </summary>
  /// <param name="color"></param>
  public void setcolor(color color)
  {
    mmat.setcolor(s_innercolor, color);

  }
  
  public void setlifetime(float time)
  {
    mlife = time;
  }
  
  public void active()
  {
    if (!mbinit)
      addeffect();
    mmat.setfloat(s_allpower, 0.9f);
    mbactive = true;
    mlife = 0.2f;

  }

  void update()
  {
    if (!mbactive)
      return;
    mlife -= time.deltatime;
    if (mlife < 0)
    {
      mbactive = false;
      mmat.setfloat(s_allpower, 0);
    }
    float v = mathf.sin((1 - mlife) * 8 * mathf.pi) + 2;
    mmat.setfloat(s_alphapower, v);
  }

  void addeffect()
  {
    object mat = resources.load("material/hittedmateffect");
    mmat = gameobject.instantiate(mat) as material;
    foreach (var curmeshrender in transform.getcomponentsinchildren<renderer>())
    {
      material[] newmaterialarray = new material[curmeshrender.materials.length + 1];
      for (int i = 0; i < curmeshrender.materials.length; i++)
      {
        if (curmeshrender.materials[i].name.contains("hittedmateffect"))
        {
          return;
        }
        else
        {
          newmaterialarray[i] = curmeshrender.materials[i];
        }
      }
      if (null != mmat)
        newmaterialarray[curmeshrender.materials.length] = mmat;
      curmeshrender.materials = newmaterialarray;
    }
    mbinit = true;
  }

  void removeeffect()
  {
    foreach (var curmeshrender in transform.getcomponentsinchildren<renderer>())
    {
      int newmaterialarraycount = 0;
      for (int i = 0; i < curmeshrender.materials.length; i++)
      {
        if (curmeshrender.materials[i].name.contains("hittedmateffect"))
        {
          newmaterialarraycount++;
        }
      }

      if (newmaterialarraycount > 0)
      {
        material[] newmaterialarray = new material[newmaterialarraycount];
        int curmaterialindex = 0;
        for (int i = 0; i < curmeshrender.materials.length; i++)
        {
          if (curmaterialindex >= newmaterialarraycount)
          {
            break;
          }
          if (!curmeshrender.materials[i].name.contains("hittedmateffect"))
          {
            newmaterialarray[curmaterialindex] = curmeshrender.materials[i];
            curmaterialindex++;
          }
        }
        curmeshrender.materials = newmaterialarray;
      }

    }
  }
}

runner.cs

using system.collections;
using system.collections.generic;
using unityengine;

public class runner : monobehaviour
{
  // use this for initialization
  void start()
  {

  }

  // update is called once per frame
  void update()
  {
    if (input.getmousebuttondown(0))
    {
      hittedmateffect sc = gameobject.getcomponent<hittedmateffect>();
      if (null == sc)
        sc = gameobject.addcomponent<hittedmateffect>();
      sc.active();
      sc.setcolor(color.red);
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。