首页 >Unity3D频道 >【Unity3D研究院之游戏开发】 > Unity3D研究院之运行时修改粒子特效镜像以及缩放(八十)
2015
05-13

Unity3D研究院之运行时修改粒子特效镜像以及缩放(八十)

刚好这几天有朋友问我,我也刚好整理一下。

1.先说非运行时,AssetStore有一个叫Particle Scaler的插件,非常好用。但是很遗憾它运行时不能用。

2.再说运行时,就是让transform的scale可以控制粒子的缩放,如果设置-1就是粒子镜像。

首先,把unity的shader下载下来。http://unity3d.com/cn/get-unity/download/archive 找到所有Particle开头的shader,也就是粒子特效用的。

下面我随便改一个shader,其他的shader修改方法原理一样。 注:shader 中 ”//—Add—“ 就是我修改的内容

Shader "Particles/Additive" {
Properties {
	_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
	_MainTex ("Particle Texture", 2D) = "white" {}
	_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
	//----------------------add------------------------------
	_Position ("Position", Vector) = (0,0,0,0)
	_Scale ("Scale", Vector) = (1,1,1,1)
	//----------------------add------------------------------
	
}

Category {
	Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
	Blend SrcAlpha One
	AlphaTest Greater .01
	ColorMask RGB
	Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }
	
	SubShader {
		Pass {
		
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_particles

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			fixed4 _TintColor;
			
			struct appdata_t {
				float4 vertex : POSITION;
				fixed4 color : COLOR;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f {
				float4 vertex : SV_POSITION;
				fixed4 color : COLOR;
				float2 texcoord : TEXCOORD0;
				#ifdef SOFTPARTICLES_ON
				float4 projPos : TEXCOORD1;
				#endif
			};
			
			float4 _MainTex_ST;
			//----------------------add------------------------------
			float4 _Position;
			float4 _Scale;
			//----------------------add------------------------------
			v2f vert (appdata_t v)
			{
				v2f o;
				//----------------------add------------------------------
				float4 objV = mul(UNITY_MATRIX_MV, v.vertex);
				objV.xyz -= _Position;
				objV.xyz = float3(_Scale.x * objV.x, _Scale.y * objV.y, _Scale.z * objV.z);
				objV.xyz += _Position;
				o.vertex = mul(UNITY_MATRIX_P, objV);
				//----------------------add------------------------------
				//o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				
				#ifdef SOFTPARTICLES_ON
				o.projPos = ComputeScreenPos (o.vertex);
				COMPUTE_EYEDEPTH(o.projPos.z);
				#endif
				o.color = v.color;
				o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
				return o;
			}

			sampler2D_float _CameraDepthTexture;
			float _InvFade;

			fixed4 frag (v2f i) : SV_Target
			{
				#ifdef SOFTPARTICLES_ON
				float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
				float partZ = i.projPos.z;
				float fade = saturate (_InvFade * (sceneZ-partZ));
				i.color.a *= fade;
				#endif
				
				return 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);
			}
			ENDCG 
		}
	}	
}
}

接着给需要缩放或者镜像的粒子挂上这一条脚本。利用OnWillRenderObject方法,将粒子的缩放以及坐标传进shader中去。

using UnityEngine;
using System.Collections;

public class ParticleScaler : MonoBehaviour {
	void OnWillRenderObject(){
		renderer.material.SetVector("_Position",Camera.current.worldToCameraMatrix.MultiplyPoint(transform.root.position));
		renderer.material.SetVector("_Scale",transform.lossyScale);
	}
}

OK.这样粒子就完成了镜像。。 编辑器中快改一改transform的scale的值看看效果吧。

Snip20150513_1

工程代码:http://pan.baidu.com/s/1i34B7Dj

如果你还有更好的办法来做粒子镜像或者旋转,欢迎在下面留言。谢谢~祝大家学习愉快~

感谢楼下好友的补充。

如果特效层级多,旋转嵌套复杂,如果只用lossyScale是不正确的。
应该保持特效层级中的scale为1,1,1然后修改以上脚本:
GetComponent().material.SetVector(“_Scale”, new Vector3(transform.localScale.x * (transform.lossyScale.x < 0 ? -1.0f : 1.0f), transform.localScale.y * (transform.lossyScale.y < 0 ? -1.0f : 1.0f), transform.localScale.z * (transform.lossyScale.z < 0 ? -1.0f : 1.0f)));

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之运行时修改粒子特效镜像以及缩放(八十)》有 36 条评论

  1. jiacat说:

    5.3版本后粒子异步渲染,导致OnWillRenderObject函数修改*不一定*能反应到粒子上了,该方法已废

  2. 花大侠说:

    感谢你的分享。请问修改镜像的_InvFade应该怎么做呢? 试了一点效果都没有。_InvFade在镜子里面的值是最大值,并且完全不随调节而变化。

  3. Mercurial说:

    第十三行的Category{}是什么意思?为什么在子着色器的层级之外声明?

  4. 早点看到这方法就好了。。我之前都是直接改粒子效果的各种参数

  5. 1234说:

    请问刀光怎么镜像呢

  6. 哈无搞说:

    其实跟用Particle.startSize效果是一样的,可以GetComponentsInChildren()拿出来,修改startsize即可,不过unity4以上版本,模块数据并不开放,所以如果美术使用了模块数据的话,就无法修改了,不知道如何解决,看了下Particle Scaler就是用的unityeditor下的SerializedObject获取模块数据,但是这玩意只能在编辑器里玩玩。。。

  7. 杰恩、说:

    momo,你好,请问下skinnedmesh合并以后的模型为什么修改缩放没有效果? 如何才能修改缩放以后的模型?

  8. sunfound说:

    unity5.1 里,不能用啊

  9. 疯狂的兔子说:

    报错了Assets/resources/script/ParticleScaler.cs(8,17): error CS0411: The type arguments for method `UnityEngine.Component.GetComponent()’ cannot be inferred from the usage. Try specifying the type arguments explicitly

  10. 豆腐干说:

    如果是mobile下的粒子shader该怎么改?

  11. Chiuan说:

    如果特效层级多,旋转嵌套复杂,如果只用lossyScale是不正确的。应该保持特效层级中的scale为1,1,1然后修改以上脚本:GetComponent().material.SetVector(“_Scale”, new Vector3(transform.localScale.x * (transform.lossyScale.x < 0 ? -1.0f : 1.0f), transform.localScale.y * (transform.lossyScale.y < 0 ? -1.0f : 1.0f), transform.localScale.z * (transform.lossyScale.z < 0 ? -1.0f : 1.0f)));

  12. ma说:

    好像如果这个particle在某个particle下面,并且旋转不一样,lossyScale最终的就不对了

  13. lyle说:

    最近也在做粒子的缩放和镜像,也坑了很久,谢谢博主的分享。因为我的功能目前暂时只会在编辑器里使用,所以目前运行使还是使用Particle Scaler配合修改y旋转来实现,但是会有一些细节问题。之后试试博主提供的方式 Unity3D研究院之运行时修改粒子特效镜像以及缩放(八十) - 雨松MOMO程序研究院 - 1 多谢

  14. az说:

    雨松大神,我最近在研究unity的性能优化,http://matrix.unity3d.com/main.html,这个Unity新推出的功能不知道你有没有用过我想咨询下,你知道他这个是怎么实现的吗,我们可以自己实现类似的吗?

  15. 王蒙说:

    非常赞,大神说没有西安的粉丝,我就是啊,沙发一记

留下一个回复

你的email不会被公开。 必填项已用 * 标注。