using UnityEngine; using UnityEngine.UI; using IndianOceanAssets.Engine2_5D; namespace GameFramework { /// /// 受击泛红特效 —— 玩家受伤时屏幕四周闪烁红色暗角。 /// /// 挂载到场景中任意物体上(或由 GameHUD 自动创建)。 /// 运行时自动创建全屏暗角遮罩,监听 HealthSystem.onPlayerDamaged 事件。 /// public class DamageFlashOverlay : MonoBehaviour { [Header("特效参数")] [Tooltip("受击时暗角最大透明度(0~1)")] [SerializeField] private float flashAlpha = 0.8f; [Tooltip("闪烁淡出时间(秒)")] [SerializeField] private float fadeDuration = 0.4f; [Tooltip("暗角内圈半径(0~1,0=全屏幕红色,1=只有最边缘)")] [SerializeField] private float innerRadius = 0.8f; private Canvas _canvas; private Image _overlayImage; private float _currentAlpha; private bool _isFlashing; private void Start() { CreateOverlay(); HealthSystem.onPlayerDamaged += OnPlayerDamaged; } private void OnDestroy() { HealthSystem.onPlayerDamaged -= OnPlayerDamaged; } private void Update() { if (!_isFlashing) return; // 淡出 _currentAlpha -= Time.unscaledDeltaTime / fadeDuration; if (_currentAlpha <= 0f) { _currentAlpha = 0f; _isFlashing = false; _overlayImage.gameObject.SetActive(false); } _overlayImage.color = new Color(1f, 0f, 0f, _currentAlpha); } private void OnPlayerDamaged() { // 重置闪烁 _currentAlpha = flashAlpha; _isFlashing = true; _overlayImage.gameObject.SetActive(true); _overlayImage.color = new Color(1f, 0f, 0f, _currentAlpha); } /// /// 创建全屏暗角遮罩(运行时生成暗角纹理)。 /// private void CreateOverlay() { // 创建 Canvas var canvasObj = new GameObject("DamageFlashCanvas"); _canvas = canvasObj.AddComponent(); _canvas.renderMode = RenderMode.ScreenSpaceOverlay; _canvas.sortingOrder = 10000; // 在 HUD 之上 canvasObj.AddComponent(); // 创建全屏 Image var imageObj = new GameObject("DamageFlashImage"); imageObj.transform.SetParent(canvasObj.transform, false); var rect = imageObj.AddComponent(); rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.sizeDelta = Vector2.zero; _overlayImage = imageObj.AddComponent(); _overlayImage.sprite = CreateVignetteSprite(); _overlayImage.type = Image.Type.Simple; _overlayImage.raycastTarget = false; // 不阻挡点击 imageObj.SetActive(false); // 初始隐藏 } /// /// 运行时生成暗角纹理(中心透明,边缘红色)。 /// private Sprite CreateVignetteSprite() { int size = 256; var texture = new Texture2D(size, size, TextureFormat.RGBA32, false); var pixels = new Color[size * size]; float center = size * 0.5f; float maxDist = center; // 最大距离(角到中心) for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { // 计算到中心的归一化距离 float dx = (x - center) / center; float dy = (y - center) / center; float dist = Mathf.Sqrt(dx * dx + dy * dy); // 暗角效果:内圈透明,外圈不透明 float alpha; if (dist <= innerRadius) { alpha = 0f; } else { // 从内圈到边缘平滑过渡 float t = (dist - innerRadius) / (1.414f - innerRadius); // 1.414 = sqrt(2) alpha = Mathf.SmoothStep(0f, 1f, t); } pixels[y * size + x] = new Color(1f, 0f, 0f, alpha); } } texture.SetPixels(pixels); texture.Apply(); texture.filterMode = FilterMode.Bilinear; return Sprite.Create(texture, new Rect(0, 0, size, size), Vector2.one * 0.5f); } } }