在經過測試之後,得出兩種解決方式:
- Simulation Space - World
在Particle System的基本設定中,把Simulation Space設定為World。而必須使用Local Space的particle就可使用第二種方式。
- Sub Emitters
啟用Sub Emitters Module,在Birth新增一個sub emitter,這個sub emitter可以是deactive的。


MainTex為一張transparent texture,OffsetTex則是一張noise texture,Shader會以OffsetTex擾動MainTex,擾動的程度由Distortion控制,速度則由TurbulenceSpd控制。另外MainTex本身也會做流動,流動速度由ScrollSpd控制。
![]() |
| Inputs |
Properties
{
_MainTex("_MainTex", 2D) = "black" {}
_OffsetTex("_Offset", 2D) = "black" {}
_Distortion("_Distortion", Float ) = 0.1
_TurbulenceSpd("_TurbulenceSpd", Float) = -50
_ScrollSpd("_ScrollSpd", Float) = 30
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
}
Cull Off
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
fixed4 vertex : POSITION;
fixed2 texcoord : TEXCOORD0;
};
struct v2f {
fixed4 pos : SV_POSITION;
fixed2 uv : TEXCOORD0;
fixed2 uv2 : TEXCOORD1;
};
fixed4 _MainTex_ST;
fixed4 _OffsetTex_ST;
fixed _Distortion;
fixed _TurbulenceSpd;
fixed _ScrollSpd;
v2f vert (appdata_base v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
// Offset _MainTex uv
fixed mainTexOffset = _Time * _ScrollSpd;
//o.uv.x = v.texcoord.x * _MainTex_ST.x + _MainTex_ST.z;
//o.uv.y = v.texcoord.y * _MainTex_ST.y + _MainTex_ST.w + mainTexOffset;
o.uv.x = v.texcoord.x;
o.uv.y = v.texcoord.y + mainTexOffset;
// Offset _OffsetTex uv
fixed offsetTexOffset = _Time * _TurbulenceSpd;
//o.uv2.x = v.texcoord.x * _OffsetTex_ST.x + _OffsetTex_ST.z + offsetTexOffset;
//o.uv2.y = v.texcoord.y * _OffsetTex_ST.y + _OffsetTex_ST.w;
o.uv2.x = v.texcoord.x + offsetTexOffset;
o.uv2.y = v.texcoord.y;
return o;
}
sampler2D _MainTex;
sampler2D _OffsetTex;
fixed4 frag(v2f i) : COLOR {
// convert OffsetTex's color to luminance to distort MainTex's uv
fixed4 offsetTexColor = tex2D(_OffsetTex, i.uv2);
fixed lum = Luminance(offsetTexColor);
fixed2 texCord = ( lum, lum );
fixed4 mainTexColor = tex2D( _MainTex, i.uv + texCord * _Distortion );
return mainTexColor;
}
ENDCG
}
}
CGPROGRAM
#pragma surface surf NoLighting
#pragma target 2.0
sampler2D _MainTex;
sampler2D _OffsetTex;
float _Distortion;
float _Speed;
float _MoveSpeed;
struct EditorSurfaceOutput {
half3 Albedo;
half3 Normal;
half3 Emission;
half3 Gloss;
half Specular;
half Alpha;
};
fixed4 LightingNoLighting(EditorSurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed4 c;
c.rgb = s.Albedo;
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
float2 uv_OffsetTex;
};
void surf (Input IN, inout EditorSurfaceOutput o) {
// pan OffsetTex
fixed time = _Time * _Speed;
fixed2 UV_PanY = fixed2( IN.uv_OffsetTex.x + time, IN.uv_OffsetTex.y );
// pan MainTex
fixed moveTime = _Time * _MoveSpeed;
fixed2 UV_PanMove = fixed2( IN.uv_OffsetTex.x, IN.uv_OffsetTex.y + moveTime );
fixed2 OffsetTex2D = tex2D( _OffsetTex, UV_PanY.xy );
fixed2 distorted = OffsetTex2D * _Distortion;
fixed2 Add1 = UV_PanMove + distorted;
fixed4 MainTex2D = tex2D( _MainTex, Add1.xy );
o.Albedo = MainTex2D;
o.Alpha = MainTex2D.a;
}
ENDCG
Box Collider > Capsule Collider >> Sphere ColliderBox Collider稍稍大於Capsule Collider的消耗,而Sphere Collider的消耗則是明顯的少了很多,因此在許可的狀況之下應盡量使用Sphere Collider。
// 設定貼圖檔案的圖片壓縮格式 textureImporter.textureFormat = TextureImporterFormat.PVRTC_RGBA4; // 設定了Import Settings之後再使用AssetDatabase.ImportAsset進行asset的更新 AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate );
這是一個帶有類似Rim Light效果及Tint Color,並且可以與原始的Texture做Blending的不受光Fragment Shader,用於角色受擊效果。
Shader "Custom/Unlit Transparent Cutout With Color" {
Properties {
_Color ("Color (RGB) Blending (A)", Color) = (1,0,0,0)
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}
// Fragment shader by Janus Huang
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
Blend SrcAlpha OneMinusSrcAlpha
Lighting Off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
fixed4 vertex : POSITION;
fixed3 normal : NORMAL;
fixed2 texcoord : TEXCOORD0;
};
struct v2f {
fixed4 pos : SV_POSITION;
fixed2 uv : TEXCOORD0;
fixed4 color : COLOR;
};
fixed4 _MainTex_ST;
fixed4 _Color;
fixed _Cutoff;
v2f vert (appdata_base v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
fixed3 viewDir = normalize(ObjSpaceViewDir(v.vertex));
// 越是面向camera的vertex在dot計算後會獲得越大的計算結果
fixed dotProduct = dot(v.normal, viewDir);
// smoothstep用法同lerp, 但其曲線在頭尾都會趨緩
o.color = smoothstep(0.5, 1, dotProduct);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
sampler2D _MainTex;
fixed4 frag(v2f i) : COLOR {
fixed4 texcol = tex2D(_MainTex, i.uv);
// clip同AlphaTest
clip( texcol.a - _Cutoff );
// 受擊時的color計算 - 將貼圖加亮1.5倍後乘上dot計算後的黑白色(外黑內白)再加上_Color
fixed3 hitColor = texcol.rgb * 1.5 * i.color.rgb + _Color.rgb;
// 以_Color的alpha控制貼圖與受擊時的混合程度
texcol.rgb = lerp( texcol.rgb, hitColor, _Color.a);
return texcol;
}
ENDCG
}
}
}