NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/UI/Tween/UICustomBoundsFade.cs

102 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// UICustomBoundsFade.cs
// 挂在使用 UI/Default-Gama shader 的 Graphic 对象上。
// 指定一个目标 RectTransform每帧将其世界坐标四角范围同步到 _CustomFadeRect。
// 当前 Graphic 会在该范围内渐变,边缘外完全透明。
using UnityEngine;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace NLD.UI
{
[RequireComponent(typeof(Graphic))]
[DisallowMultipleComponent]
public class UICustomBoundsFade : MonoBehaviour
{
[Tooltip("使用 UI-Default-Gama shader 的基础材质(必须指定,否则脚本不生效)")]
[SerializeField] private Material _baseMaterial;
[Tooltip("目标 GameObject 的 RectTransform渐变范围以其世界坐标四角为准")]
public RectTransform targetRect;
[Tooltip("渐变过渡宽度UV 分数0 = 硬切边界0.5 = 渐变延伸到 bounds 中心。与 bounds 物理尺寸无关")]
[Range(0f, 0.5f)]
public float softness = 0.1f;
[Tooltip("渐变曲线指数1 = 线性,>1 慢起快收,<1 快起慢收")]
[Range(0.1f, 5f)]
public float curve = 1f;
// ── 内部状态 ──────────────────────────────────────────────────
private Graphic _graphic;
private Material _materialInstance;
private static readonly int _propRect = Shader.PropertyToID("_CustomFadeRect");
private static readonly int _propSoftness = Shader.PropertyToID("_CustomFadeSoftness");
private static readonly int _propCurve = Shader.PropertyToID("_CustomFadeCurve");
private const string _keyword = "USE_CUSTOM_BOUNDS_FADE";
// ── 生命周期 ──────────────────────────────────────────────────
private void OnEnable()
{
_graphic = GetComponent<Graphic>();
if (_graphic == null) return;
// 优先使用指定的 Gama 基础材质,否则回退到 Graphic 当前材质
Material original = _baseMaterial != null ? _baseMaterial : _graphic.material;
_materialInstance = new Material(original)
{
name = original.name + "_CustomBoundsFade"
};
_materialInstance.EnableKeyword(_keyword);
_graphic.material = _materialInstance;
SyncToMaterial();
}
private void OnDisable()
{
if (_graphic != null)
_graphic.material = null; // 置 null 即回退到 defaultMaterial
if (_materialInstance != null)
{
DestroyImmediate(_materialInstance);
_materialInstance = null;
}
}
private void LateUpdate() => SyncToMaterial();
// ── 核心同步 ──────────────────────────────────────────────────
private void SyncToMaterial()
{
if (_materialInstance == null || targetRect == null) return;
// GetWorldCorners: [0]=BL [1]=TL [2]=TR [3]=BR
var corners = new Vector3[4];
targetRect.GetWorldCorners(corners);
float xMin = corners[0].x;
float yMin = corners[0].y;
float xMax = corners[2].x;
float yMax = corners[2].y;
_materialInstance.SetVector(_propRect, new Vector4(xMin, yMin, xMax, yMax));
_materialInstance.SetFloat (_propSoftness, softness);
_materialInstance.SetFloat (_propCurve, curve);
}
#if UNITY_EDITOR
// Editor 下实时预览OnValidate 在 inspector 改值时调用)
private void OnValidate()
{
if (!Application.isPlaying && _materialInstance != null)
SyncToMaterial();
}
#endif
}
}