diff --git a/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs b/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs
index 52cba1f..ce6c797 100644
--- a/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs
+++ b/unity/Assets/2.5D Engine/Scripts/HealthSystem.cs
@@ -1,10 +1,14 @@
using UnityEngine;
+using System;
using GameFramework;
namespace IndianOceanAssets.Engine2_5D
{
// Handles health, damage, and death for entities
public class HealthSystem : MonoBehaviour
{
+ /// 玩家受伤时触发(用于受击特效等)
+ public static Action onPlayerDamaged;
+
[Range(1, 100)]
[SerializeField]
private int maxHealth = 5; // Maximum health
@@ -31,6 +35,10 @@ namespace IndianOceanAssets.Engine2_5D
health -= damageAmount;
+ // 玩家受伤时触发事件(用于受击泛红特效)
+ if (isPlayer && onPlayerDamaged != null)
+ onPlayerDamaged.Invoke();
+
// If dead
if (health <= 0)
{
diff --git a/unity/Assets/Scenes/Gameplay.unity b/unity/Assets/Scenes/Gameplay.unity
index 27e43da..ad787b5 100644
--- a/unity/Assets/Scenes/Gameplay.unity
+++ b/unity/Assets/Scenes/Gameplay.unity
@@ -6185,6 +6185,18 @@ PrefabInstance:
propertyPath: m_Name
value: enemy_05
objectReference: {fileID: 0}
+ - target: {fileID: 6306576444274981952, guid: 7c1df93486acb4e44bd78734e13d87a0, type: 3}
+ propertyPath: m_LocalScale.x
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 6306576444274981952, guid: 7c1df93486acb4e44bd78734e13d87a0, type: 3}
+ propertyPath: m_LocalScale.y
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 6306576444274981952, guid: 7c1df93486acb4e44bd78734e13d87a0, type: 3}
+ propertyPath: m_LocalScale.z
+ value: 0.7
+ objectReference: {fileID: 0}
- target: {fileID: 6306576444274981952, guid: 7c1df93486acb4e44bd78734e13d87a0, type: 3}
propertyPath: m_LocalPosition.x
value: 6.49
@@ -6225,6 +6237,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
+ - target: {fileID: 6306576444274981952, guid: 7c1df93486acb4e44bd78734e13d87a0, type: 3}
+ propertyPath: m_ConstrainProportionsScale
+ value: 1
+ objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@@ -10212,6 +10228,18 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
+ - target: {fileID: 2393803201260214047, guid: 8a195b2e97ff3d24f81953f5aec10187, type: 3}
+ propertyPath: m_LocalScale.x
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 2393803201260214047, guid: 8a195b2e97ff3d24f81953f5aec10187, type: 3}
+ propertyPath: m_LocalScale.y
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 2393803201260214047, guid: 8a195b2e97ff3d24f81953f5aec10187, type: 3}
+ propertyPath: m_LocalScale.z
+ value: 0.7
+ objectReference: {fileID: 0}
- target: {fileID: 2393803201260214047, guid: 8a195b2e97ff3d24f81953f5aec10187, type: 3}
propertyPath: m_LocalPosition.x
value: 1.4899998
@@ -10252,6 +10280,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
+ - target: {fileID: 2393803201260214047, guid: 8a195b2e97ff3d24f81953f5aec10187, type: 3}
+ propertyPath: m_ConstrainProportionsScale
+ value: 1
+ objectReference: {fileID: 0}
- target: {fileID: 8673329150658497095, guid: 8a195b2e97ff3d24f81953f5aec10187, type: 3}
propertyPath: m_Name
value: enemy_02
@@ -13415,6 +13447,22 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
+ - target: {fileID: 1609478081808774938, guid: 6f6889c3968492343b4a748ec94e1d4d, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 2.69
+ objectReference: {fileID: 0}
+ - target: {fileID: 6055015580396346534, guid: 6f6889c3968492343b4a748ec94e1d4d, type: 3}
+ propertyPath: m_LocalScale.x
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 6055015580396346534, guid: 6f6889c3968492343b4a748ec94e1d4d, type: 3}
+ propertyPath: m_LocalScale.y
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 6055015580396346534, guid: 6f6889c3968492343b4a748ec94e1d4d, type: 3}
+ propertyPath: m_LocalScale.z
+ value: 0.7
+ objectReference: {fileID: 0}
- target: {fileID: 6055015580396346534, guid: 6f6889c3968492343b4a748ec94e1d4d, type: 3}
propertyPath: m_LocalPosition.x
value: 11.49
@@ -13455,6 +13503,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
+ - target: {fileID: 6055015580396346534, guid: 6f6889c3968492343b4a748ec94e1d4d, type: 3}
+ propertyPath: m_ConstrainProportionsScale
+ value: 1
+ objectReference: {fileID: 0}
- target: {fileID: 6153816677019540685, guid: 6f6889c3968492343b4a748ec94e1d4d, type: 3}
propertyPath: m_Name
value: enemy_01
@@ -22068,6 +22120,9 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
gameState: 0
+ lightExpandDuration: 1.5
+ lightExpandTargetRadius: 20
+ fadeOutDuration: 1
--- !u!4 &1385715428
Transform:
m_ObjectHideFlags: 0
@@ -32132,6 +32187,18 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
+ - target: {fileID: 1123674622178506746, guid: 8f8c995dea0cb274baeaf2a7bdfe1037, type: 3}
+ propertyPath: m_LocalScale.x
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 1123674622178506746, guid: 8f8c995dea0cb274baeaf2a7bdfe1037, type: 3}
+ propertyPath: m_LocalScale.y
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 1123674622178506746, guid: 8f8c995dea0cb274baeaf2a7bdfe1037, type: 3}
+ propertyPath: m_LocalScale.z
+ value: 0.7
+ objectReference: {fileID: 0}
- target: {fileID: 1123674622178506746, guid: 8f8c995dea0cb274baeaf2a7bdfe1037, type: 3}
propertyPath: m_LocalPosition.x
value: 1.4899998
@@ -32172,6 +32239,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
+ - target: {fileID: 1123674622178506746, guid: 8f8c995dea0cb274baeaf2a7bdfe1037, type: 3}
+ propertyPath: m_ConstrainProportionsScale
+ value: 1
+ objectReference: {fileID: 0}
- target: {fileID: 5471001682465061791, guid: 8f8c995dea0cb274baeaf2a7bdfe1037, type: 3}
propertyPath: m_Name
value: enemy_04
@@ -33851,6 +33922,18 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
+ - target: {fileID: 6513886605935214580, guid: 75afe3f1a4ed9f64abe61fa9c3070a7d, type: 3}
+ propertyPath: m_LocalScale.x
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 6513886605935214580, guid: 75afe3f1a4ed9f64abe61fa9c3070a7d, type: 3}
+ propertyPath: m_LocalScale.y
+ value: 0.7
+ objectReference: {fileID: 0}
+ - target: {fileID: 6513886605935214580, guid: 75afe3f1a4ed9f64abe61fa9c3070a7d, type: 3}
+ propertyPath: m_LocalScale.z
+ value: 0.7
+ objectReference: {fileID: 0}
- target: {fileID: 6513886605935214580, guid: 75afe3f1a4ed9f64abe61fa9c3070a7d, type: 3}
propertyPath: m_LocalPosition.x
value: 11.49
@@ -33891,6 +33974,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
+ - target: {fileID: 6513886605935214580, guid: 75afe3f1a4ed9f64abe61fa9c3070a7d, type: 3}
+ propertyPath: m_ConstrainProportionsScale
+ value: 1
+ objectReference: {fileID: 0}
- target: {fileID: 9149581610257369843, guid: 75afe3f1a4ed9f64abe61fa9c3070a7d, type: 3}
propertyPath: m_Name
value: enemy_03
diff --git a/unity/Assets/UI/DamageFlashOverlay.cs b/unity/Assets/UI/DamageFlashOverlay.cs
new file mode 100644
index 0000000..2ccbf36
--- /dev/null
+++ b/unity/Assets/UI/DamageFlashOverlay.cs
@@ -0,0 +1,138 @@
+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