方法一:使用 FairyGUI 内置的 BlurFilter(推荐)
1. 基本使用
csharp
using FairyGUI;
// 创建模糊滤镜
BlurFilter blurFilter = new BlurFilter();
blurFilter.blurSize = 2f; // 模糊半径
blurFilter.downsample = 1; // 下采样倍数,值越大性能越好但质量越低
// 应用到组件
GComponent comp = GetComponent<GComponent>();
comp.filter = blurFilter;
2. 动态模糊效果
csharp
using UnityEngine;
using FairyGUI;
public class BlurEffectDemo : MonoBehaviour
{
private GComponent _mainView;
private BlurFilter _blurFilter;
void Start()
{
// 创建UI
_mainView = UIPackage.CreateObject("PackageName", "ComponentName").asCom;
GRoot.inst.AddChild(_mainView);
// 创建模糊滤镜
_blurFilter = new BlurFilter();
_blurFilter.blurSize = 0f;
_mainView.filter = _blurFilter;
// 添加按钮控制
GButton btn = _mainView.GetChild("btn_blur").asButton;
btn.onClick.Add(() => {
// 开启模糊动画
PlayBlurAnimation(5f, 0.3f);
});
}
void PlayBlurAnimation(float targetBlurSize, float duration)
{
// 使用 FairyGUI 的动画系统
GTween.To(_blurFilter.blurSize, targetBlurSize, duration)
.SetEase(EaseType.Linear)
.OnUpdate(tweener => {
_blurFilter.blurSize = tweener.value.x;
_mainView.InvalidateBatchingState();
});
}
}
方法二:使用 RenderTexture + 后处理Shader
1. 创建高斯模糊 Shader
glsl
// GaussianBlur.shader
Shader "FairyGUI/GaussianBlur"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_BlurSize ("Blur Size", Range(0, 10)) = 1
}
SubShader
{
Tags { "Queue"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float _BlurSize;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
// 高斯模糊核心算法
float2 texelSize = _MainTex_TexelSize.xy * _BlurSize;
float4 color = float4(0, 0, 0, 0);
float weightSum = 0;
// 5x5 高斯核
float weights[5] = {0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216};
float offsets[5] = {0.0, 1.0, 2.0, 3.0, 4.0};
// 水平模糊
color += tex2D(_MainTex, i.uv) * weights[0];
for(int j = 1; j < 5; j++)
{
color += tex2D(_MainTex, i.uv + float2(offsets[j] * texelSize.x, 0)) * weights[j];
color += tex2D(_MainTex, i.uv - float2(offsets[j] * texelSize.x, 0)) * weights[j];
}
return color;
}
ENDCG
}
}
}
2. 在代码中使用
csharp
using UnityEngine;
using FairyGUI;
public class AdvancedBlur : MonoBehaviour
{
private RenderTexture _blurRT;
private Material _blurMaterial;
void Start()
{
// 创建模糊材质
_blurMaterial = new Material(Shader.Find("FairyGUI/GaussianBlur"));
// 创建 UI
GComponent comp = UIPackage.CreateObject("Package", "Component").asCom;
// 先渲染到 RenderTexture
CreateBlurTexture(comp);
}
void CreateBlurTexture(GComponent comp)
{
// 获取 UI 的渲染尺寸
Vector2 size = comp.size;
// 创建 RenderTexture
_blurRT = new RenderTexture((int)size.x, (int)size.y, 0);
// 设置模糊参数
_blurMaterial.SetFloat("_BlurSize", 3f);
// 创建一个图片显示模糊结果
GImage blurImage = new GImage();
blurImage.SetSize(size.x, size.y);
blurImage.texture = new NTexture(_blurRT);
// 将模糊图片添加到 UI
comp.AddChild(blurImage);
}
}
方法三:使用 Unity Post Processing Stack v2
1. 配置步骤
-
安装 Post Processing Package
-
创建 Post Process Layer 和 Volume
-
添加 Blur 效果
2. 代码实现
csharp
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
using FairyGUI;
public class PostProcessBlur : MonoBehaviour
{
public PostProcessVolume blurVolume;
private DepthOfField _dof;
void Start()
{
// 获取或创建 DepthOfField 效果
blurVolume.profile.TryGetSettings(out _dof);
// 创建UI
GComponent comp = UIPackage.CreateObject("Package", "Component").asCom;
GRoot.inst.AddChild(comp);
// 添加切换模糊的按钮
GButton btn = comp.GetChild("btn_toggle_blur").asButton;
btn.onClick.Add(ToggleBlur);
}
void ToggleBlur()
{
if (_dof != null)
{
_dof.active = !_dof.active;
// 设置模糊参数
_dof.focusDistance.value = 0.1f;
_dof.aperture.value = 32f;
_dof.focalLength.value = 50f;
}
}
}
方法四:性能优化建议
1. 缓存模糊结果
csharp
public class CachedBlur
{
private Dictionary<string, NTexture> _blurCache = new Dictionary<string, NTexture>();
public NTexture GetCachedBlur(GObject obj, float blurSize)
{
string cacheKey = $"{obj.id}_{blurSize}";
if (!_blurCache.ContainsKey(cacheKey))
{
// 生成模糊纹理
NTexture blurTex = GenerateBlurTexture(obj, blurSize);
_blurCache[cacheKey] = blurTex;
}
return _blurCache[cacheKey];
}
private NTexture GenerateBlurTexture(GObject obj, float blurSize)
{
// 实现纹理生成逻辑
return null;
}
}
2. 按需模糊
csharp
public class OnDemandBlur : MonoBehaviour
{
public GComponent targetComp;
public float checkInterval = 0.5f;
void Start()
{
StartCoroutine(CheckAndApplyBlur());
}
IEnumerator CheckAndApplyBlur()
{
while (true)
{
// 检查是否需要模糊(例如UI是否在屏幕上)
if (IsUIVisible())
{
ApplyBlurIfNeeded();
}
yield return new WaitForSeconds(checkInterval);
}
}
bool IsUIVisible()
{
// 检查UI是否在屏幕内
return targetComp.onStage;
}
}
注意事项
-
性能考量:
-
移动设备建议使用较小的 blurSize(≤3)
-
使用 downsampling 提高性能
-
避免每帧更新模糊效果
-
-
内存管理:
-
及时释放不再使用的 RenderTexture
-
使用对象池管理模糊材质
-
-
平台兼容性:
-
在 iOS 上确保使用正确的 Metal/GLES 配置
-
Android 上注意纹理格式兼容性
-
选择哪种方法取决于你的具体需求:
-
简单模糊:使用 FairyGUI 的 BlurFilter
-
高质量模糊:使用自定义 Shader + RenderTexture
-
全屏后处理:使用 Post Processing Stack
-
性能优先:使用缓存和按需渲染策略
验证和确认
1. 官方文档支持
FairyGUI 官方文档明确支持 BlurFilter:
-
BlurFilter类存在于FairyGUI命名空间 -
这是官方提供的内置滤镜效果
2. 实际使用示例
这里提供一个完整可运行的示例:
csharp
using UnityEngine;
using FairyGUI;
public class BlurDemo : MonoBehaviour
{
void Start()
{
// 1. 创建UI
GComponent view = UIPackage.CreateObject("包名", "组件名").asCom;
view.SetSize(400, 300);
view.Center();
GRoot.inst.AddChild(view);
// 2. 添加一个文本组件用于测试
GTextField text = new GTextField();
text.text = "这是测试文本,将会被模糊";
text.SetSize(200, 50);
text.SetXY(100, 125);
view.AddChild(text);
// 3. 创建并应用模糊滤镜
BlurFilter blur = new BlurFilter();
blur.blurSize = 3f; // 模糊程度,0-10
blur.downsample = 1; // 下采样,1表示不降采样
// 应用到整个组件
view.filter = blur;
// 或者应用到特定子组件
// text.filter = blur;
Debug.Log("模糊滤镜已应用!当前模糊大小:" + blur.blurSize);
}
}
3. 关键参数说明
csharp
// 创建模糊滤镜
BlurFilter blur = new BlurFilter();
// 主要参数:
blur.blurSize = 2f; // 模糊半径,值越大越模糊(0-10)
blur.downsample = 1; // 下采样,1=原始,2=1/2分辨率,性能更好但质量更低
blur.color = Color.white; // 颜色叠加
blur.strength = 1; // 模糊强度(0-1)
4. 动态修改示例
csharp
public class DynamicBlur : MonoBehaviour
{
private BlurFilter _blurFilter;
private GComponent _target;
void Start()
{
_target = GetComponent<GComponent>();
// 创建模糊滤镜
_blurFilter = new BlurFilter();
_target.filter = _blurFilter;
// 按钮点击事件
GButton btn = _target.GetChild("btnBlur").asButton;
btn.onClick.Add(() => {
// 点击时增加模糊
_blurFilter.blurSize += 1f;
if (_blurFilter.blurSize > 5f)
_blurFilter.blurSize = 0f;
// 必须调用这个来刷新显示
_target.InvalidateBatchingState();
});
}
void Update()
{
// 实时更新模糊(如果需要)
if (Input.GetKeyDown(KeyCode.Space))
{
_blurFilter.blurSize = 2f;
_target.InvalidateBatchingState();
}
}
}
5. 常见应用场景
csharp
// 场景1:弹窗背景模糊
public void ShowPopupWithBlur()
{
// 获取当前界面
GComponent currentView = GetCurrentView();
// 创建模糊滤镜
BlurFilter blur = new BlurFilter();
blur.blurSize = 2f;
currentView.filter = blur;
// 显示弹窗
ShowPopup();
// 弹窗关闭时移除模糊
// popup.OnClose += () => currentView.filter = null;
}
// 场景2:加载界面模糊
public void ShowLoadingWithBlur(GComponent target)
{
BlurFilter blur = new BlurFilter();
blur.blurSize = 3f;
blur.downsample = 2; // 使用下采样提高性能
target.filter = blur;
}
6. 性能测试代码
csharp
using System.Diagnostics;
using FairyGUI;
public class BlurPerformanceTest : MonoBehaviour
{
void Start()
{
TestBlurPerformance();
}
void TestBlurPerformance()
{
GComponent comp = UIPackage.CreateObject("包名", "组件名").asCom;
Stopwatch sw = new Stopwatch();
// 测试不同模糊半径的性能
for (int i = 1; i <= 5; i++)
{
sw.Restart();
BlurFilter blur = new BlurFilter();
blur.blurSize = i;
blur.downsample = 1;
comp.filter = blur;
comp.InvalidateBatchingState();
sw.Stop();
Debug.Log($"模糊半径 {i},耗时:{sw.ElapsedMilliseconds}ms");
}
}
}
注意事项
-
必须调用
InvalidateBatchingState():csharp
// 修改模糊参数后必须调用 component.InvalidateBatchingState(); -
下采样优化:
csharp
// 移动设备建议使用下采样 blur.downsample = 2; // 性能更好,但效果稍差 -
避免过度使用:
-
不要在每帧都修改模糊参数
-
不使用时设置为
null来释放资源:csharp
component.filter = null;
-
验证你的项目
如果你不确定,可以在项目中运行这个测试:
csharp
// 测试脚本
void TestBlur()
{
GTextField text = new GTextField();
text.text = "测试模糊";
text.SetSize(200, 50);
GRoot.inst.AddChild(text);
BlurFilter blur = new BlurFilter();
blur.blurSize = 3f;
text.filter = blur;
Debug.Log("如果没有报错,说明 BlurFilter 可用");
}