Unity实现角色受击身体边缘发光特效
程序员文章站
2022-06-03 15:17:21
游戏中经常需要制作角色受击打的身体边缘光效果,本文使用的方法是,给renderer叠加一个制作好的边缘光材质球,并通过脚本动态控制边缘光的渐变效果,表现出受击后的边缘光效果工程结构如下1 创建一个材质...
游戏中经常需要制作角色受击打的身体边缘光效果,本文使用的方法是,给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); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。