增加受击泛红效果
This commit is contained in:
@@ -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
|
||||
{
|
||||
/// <summary>玩家受伤时触发(用于受击特效等)</summary>
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using IndianOceanAssets.Engine2_5D;
|
||||
|
||||
namespace GameFramework
|
||||
{
|
||||
/// <summary>
|
||||
/// 受击泛红特效 —— 玩家受伤时屏幕四周闪烁红色暗角。
|
||||
///
|
||||
/// 挂载到场景中任意物体上(或由 GameHUD 自动创建)。
|
||||
/// 运行时自动创建全屏暗角遮罩,监听 HealthSystem.onPlayerDamaged 事件。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建全屏暗角遮罩(运行时生成暗角纹理)。
|
||||
/// </summary>
|
||||
private void CreateOverlay()
|
||||
{
|
||||
// 创建 Canvas
|
||||
var canvasObj = new GameObject("DamageFlashCanvas");
|
||||
_canvas = canvasObj.AddComponent<Canvas>();
|
||||
_canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
_canvas.sortingOrder = 10000; // 在 HUD 之上
|
||||
canvasObj.AddComponent<CanvasScaler>();
|
||||
|
||||
// 创建全屏 Image
|
||||
var imageObj = new GameObject("DamageFlashImage");
|
||||
imageObj.transform.SetParent(canvasObj.transform, false);
|
||||
var rect = imageObj.AddComponent<RectTransform>();
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.sizeDelta = Vector2.zero;
|
||||
|
||||
_overlayImage = imageObj.AddComponent<Image>();
|
||||
_overlayImage.sprite = CreateVignetteSprite();
|
||||
_overlayImage.type = Image.Type.Simple;
|
||||
_overlayImage.raycastTarget = false; // 不阻挡点击
|
||||
imageObj.SetActive(false); // 初始隐藏
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行时生成暗角纹理(中心透明,边缘红色)。
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: DH8Z4XurAC+mXJCLMO3KhftlwfsTEfnqj4q0hJGAb8EiGnEHR1zldgM=
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -57,6 +57,13 @@ namespace GameFramework
|
||||
UpdateSoulCount(ScoreManager.Instance != null ? ScoreManager.Instance.CurrentScore : 0);
|
||||
|
||||
UpdateLifeIcons();
|
||||
|
||||
// 自动创建受击泛红特效(如果场景中没有)
|
||||
if (FindObjectOfType<DamageFlashOverlay>() == null)
|
||||
{
|
||||
var overlayObj = new GameObject("DamageFlashOverlay");
|
||||
overlayObj.AddComponent<DamageFlashOverlay>();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
|
||||
Reference in New Issue
Block a user