当前位置: 移动技术网 > IT编程>开发语言>c# > Unity实现角色受击身体边缘发光特效

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

2020年06月23日  | 移动技术网IT编程  | 我要评论

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

工程结构如下

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

运行效果

代码

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);
    }
  }
}

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网