This commit is contained in:
ShallowT1Dream
2026-09-10 17:29:24 +08:00
parent 3071ec4b8f
commit 80aa4f0436
20 changed files with 32618 additions and 0 deletions
@@ -0,0 +1,156 @@
diff --git a/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectBase.cs b/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectBase.cs
index c3ceb2fd..210257d0 100644
--- a/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectBase.cs
+++ b/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectBase.cs
@@ -196,8 +196,11 @@ namespace Coffee.UIEffects
Profiler.BeginSample("(UIE)[UIEffect] GetModifiedMaterial");
var samplingScaleId = (uint)(Mathf.InverseLerp(0.01f, 100, actualSamplingScale) * uint.MaxValue);
- var rootId = (uint)(transitionRoot != null ? transitionRoot.GetHashCode() : 0);
- var hash = new Hash128((uint)baseMaterial.GetHashCode(), effectId, samplingScaleId, rootId);
+ // 使用特效配置哈希作为材质共享 key,相同配置的特效共享同一材质,从而可以合批。
+ // root 仅在特效需要视图矩阵(transition/gradation/detail/shiny)时才影响材质。
+ var configId = context.configId;
+ var rootId = context.useViewMatrix && transitionRoot ? (uint)transitionRoot.GetInstanceID() : 0u;
+ var hash = new Hash128((uint)baseMaterial.GetInstanceID(), configId, samplingScaleId, rootId);
if (!MaterialRepository.Valid(hash, _material))
{
Profiler.BeginSample("(UIE)[UIEffect] GetModifiedMaterial > Get or create material");
diff --git a/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectContext.cs b/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectContext.cs
index c315f4cb..48b6ae4b 100644
--- a/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectContext.cs
+++ b/unity/my_libs/unityLib/UIEffect-main/Packages/src/Runtime/UIEffectContext.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Reflection;
using Coffee.UIEffectInternal;
using UnityEngine;
using UnityEngine.Profiling;
@@ -263,6 +264,126 @@ namespace Coffee.UIEffects
|| m_DetailFilter != DetailFilter.None
|| m_EdgeMode == EdgeMode.Shiny;
+ /// <summary>
+ /// 特效配置的稳定指纹。自动遍历所有序列化配置字段生成,因此插件新增属性时无需手动维护字段清单。
+ /// 相同配置会得到相同指纹,从而可以共享同一个材质并参与合批。
+ /// </summary>
+ public uint configId
+ {
+ get
+ {
+ unchecked
+ {
+ var h = (uint)2166136261;
+ var fields = s_ConfigFields;
+ for (var i = 0; i < fields.Length; i++)
+ {
+ var f = fields[i];
+ h = Mix(h, (uint)f.Name.GetHashCode());
+ h = Mix(h, HashValue(f.GetValue(this)));
+ }
+
+ // Avalanche 混淆(MurmurHash3 终混),让相近配置散列到不同指纹。
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+ return h;
+ }
+ }
+ }
+
+ private static uint Mix(uint h, uint v)
+ {
+ h ^= v;
+ h *= 16777619;
+ return h;
+ }
+
+ /// <summary>
+ /// 对任意配置值做内容哈希。值类型会逐字段展开,嵌套结构体(Color、Vector2/3/4、MinMax01 等)
+ /// 无需单独写类型处理即可贡献全部数据。只有 UnityEngine.Object 和 Gradient 需要显式处理,
+ /// 因为它们的默认哈希基于引用而非内容。
+ /// </summary>
+ private static uint HashValue(object value)
+ {
+ if (value == null) return 0u;
+
+ if (value is UnityEngine.Object obj)
+ {
+ return obj ? (uint)obj.GetInstanceID() : 0u;
+ }
+
+ if (value is Gradient gradient)
+ {
+ return GradientHash(gradient);
+ }
+
+ var type = value.GetType();
+ if (type.IsPrimitive || type.IsEnum)
+ {
+ return unchecked((uint)value.GetHashCode());
+ }
+
+ if (type.IsValueType)
+ {
+ return HashFields(value, type);
+ }
+
+ return unchecked((uint)value.GetHashCode());
+ }
+
+ private static uint HashFields(object boxed, Type type)
+ {
+ unchecked
+ {
+ if (!s_FieldCache.TryGetValue(type, out var fields))
+ {
+ fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ s_FieldCache[type] = fields;
+ }
+
+ var h = (uint)2166136261;
+ for (var i = 0; i < fields.Length; i++)
+ {
+ h = Mix(h, HashValue(fields[i].GetValue(boxed)));
+ }
+
+ return h;
+ }
+ }
+
+ private static uint GradientHash(Gradient gradient)
+ {
+ unchecked
+ {
+ var h = (uint)2166136261;
+
+ var colorKeys = gradient.colorKeys;
+ for (var i = 0; i < colorKeys.Length; i++)
+ {
+ h = Mix(h, HashValue(colorKeys[i].color));
+ h = Mix(h, HashValue(colorKeys[i].time));
+ }
+
+ var alphaKeys = gradient.alphaKeys;
+ for (var i = 0; i < alphaKeys.Length; i++)
+ {
+ h = Mix(h, HashValue(alphaKeys[i].alpha));
+ h = Mix(h, HashValue(alphaKeys[i].time));
+ }
+
+ return h;
+ }
+ }
+
+ private static readonly FieldInfo[] s_ConfigFields = typeof(UIEffectContext)
+ .GetFields(BindingFlags.Public | BindingFlags.Instance);
+
+ private static readonly Dictionary<Type, FieldInfo[]> s_FieldCache =
+ new Dictionary<Type, FieldInfo[]>();
+
private Texture2D _gradationRampTex;
private Texture2D _transitionRampTex;
private bool _isGradientDirty = true;