多轮审查和修复
This commit is contained in:
37
Assets/Scripts/World/Liquid/LiquidPhysicsConfigSO.cs
Normal file
37
Assets/Scripts/World/Liquid/LiquidPhysicsConfigSO.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// Assets/Scripts/World/Liquid/LiquidPhysicsConfigSO.cs
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BaseGames.World.Liquid
|
||||
{
|
||||
[CreateAssetMenu(menuName = "World/LiquidPhysicsConfig")]
|
||||
public class LiquidPhysicsConfigSO : ScriptableObject
|
||||
{
|
||||
[Header("水下物理")]
|
||||
[Range(0f, 1f)]
|
||||
public float GravityScale = 0.3f; // 水下重力系数(越小越漂浮)
|
||||
[Range(0f, 1f)]
|
||||
public float BuoyancyForce = 0.5f; // 上浮力(每帧施加的向上力)
|
||||
public float MaxSwimSpeed = 4.0f; // 最大游泳速度 (m/s)
|
||||
public float SwimAcceleration = 8.0f; // 游泳加速度
|
||||
public float SurfaceExitSpeed = 5.0f; // 跃出水面时的冲量
|
||||
public float SinkSpeed = 2.0f; // 无游泳能力时自然下沉速度 (m/s)
|
||||
public float DiveSpeedMultiplier = 1.5f; // 主动下潜时的速度倍率
|
||||
|
||||
[Header("浅水/泥水速度缩放")]
|
||||
[Range(0.1f, 1.0f)]
|
||||
public float ShallowSpeedScale = 0.65f; // ShallowWater 类型水平移动速度倍率
|
||||
[Range(0.1f, 1.0f)]
|
||||
public float MudSpeedScale = 0.50f; // Mud 类型水平移动速度倍率
|
||||
|
||||
[Header("溺死计时(无游泳能力时)")]
|
||||
public float DrownTime = 3.0f; // 屏气倒计时(秒),倒计时结束则触发死亡
|
||||
|
||||
[Header("进出液体")]
|
||||
public float SplashEntryDelay = 0.05f; // 溅水特效延迟(配合动画)
|
||||
public float DragCoefficient = 3.0f; // 水下阻力系数(减缓水平移动)
|
||||
|
||||
[Header("视觉")]
|
||||
public VolumeProfile WaterVolumeProfile; // 水下后处理 Profile(可为 null)
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/World/Liquid/LiquidPhysicsConfigSO.cs.meta
Normal file
11
Assets/Scripts/World/Liquid/LiquidPhysicsConfigSO.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79a8b38fe4021c44b8cb86900cbb8a5f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
12
Assets/Scripts/World/Liquid/LiquidType.cs
Normal file
12
Assets/Scripts/World/Liquid/LiquidType.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
// Assets/Scripts/World/Liquid/LiquidType.cs
|
||||
namespace BaseGames.World.Liquid
|
||||
{
|
||||
public enum LiquidType
|
||||
{
|
||||
Water, // 可游泳(需 Swim 能力)
|
||||
ShallowWater, // 浅水(水中慢走,无需游泳能力,速度 ×0.65)
|
||||
Mud, // 泥水(移动极慢,无需游泳能力,速度 ×0.50)
|
||||
Acid, // 接触即死(HazardZone 处理)
|
||||
Lava, // 接触即死(HazardZone 处理)
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/World/Liquid/LiquidType.cs.meta
Normal file
11
Assets/Scripts/World/Liquid/LiquidType.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87548f201d0ce4c4d9e94f38f429b689
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
54
Assets/Scripts/World/Liquid/LiquidZone.cs
Normal file
54
Assets/Scripts/World/Liquid/LiquidZone.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
// Assets/Scripts/World/Liquid/LiquidZone.cs
|
||||
using BaseGames.Core.Events;
|
||||
using MoreMountains.Feedbacks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.World.Liquid
|
||||
{
|
||||
/// <summary>
|
||||
/// 挂在液态区域根 GameObject 上。
|
||||
/// 酸液/熔岩时需同时挂载 HazardZone(InstantKill 类型)。
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Collider2D))]
|
||||
public class LiquidZone : MonoBehaviour
|
||||
{
|
||||
[Header("液体类型")]
|
||||
[SerializeField] private LiquidType _liquidType = LiquidType.Water;
|
||||
|
||||
[Header("区域标识(存档/跨系统识别)")]
|
||||
[SerializeField] private string _zoneId;
|
||||
|
||||
[Header("伤害(Water 类型专用;Acid/Lava 由子节点 HazardZone 处理)")]
|
||||
[SerializeField] private bool _dealsDrowningDamage = false;
|
||||
[SerializeField] private float _drowningDamagePerSecond = 5f;
|
||||
|
||||
[Header("物理配置")]
|
||||
[SerializeField] private LiquidPhysicsConfigSO _physicsConfig;
|
||||
|
||||
[Header("Event Channels")]
|
||||
[SerializeField] private LiquidEventChannelSO _onPlayerEntered;
|
||||
[SerializeField] private LiquidEventChannelSO _onPlayerExited;
|
||||
|
||||
[Header("Feedback")]
|
||||
[SerializeField] private MMFeedbacks _splashEnterFeedback;
|
||||
[SerializeField] private MMFeedbacks _splashExitFeedback;
|
||||
|
||||
public LiquidType Type => _liquidType;
|
||||
public LiquidPhysicsConfigSO Physics => _physicsConfig;
|
||||
public string ZoneId => _zoneId;
|
||||
|
||||
private void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
_splashEnterFeedback?.PlayFeedbacks();
|
||||
_onPlayerEntered?.Raise(new LiquidEvent(_zoneId, _liquidType.ToString()));
|
||||
}
|
||||
|
||||
private void OnTriggerExit2D(Collider2D other)
|
||||
{
|
||||
if (!other.CompareTag("Player")) return;
|
||||
_splashExitFeedback?.PlayFeedbacks();
|
||||
_onPlayerExited?.Raise(new LiquidEvent(_zoneId, _liquidType.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/World/Liquid/LiquidZone.cs.meta
Normal file
11
Assets/Scripts/World/Liquid/LiquidZone.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7a2e8fb64e1e3a4fb0e2cd6f5c3ccc1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,56 @@
|
||||
// Assets/Scripts/World/Liquid/UnderwaterPostProcessingController.cs
|
||||
using System.Collections;
|
||||
using BaseGames.Core.Events;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace BaseGames.World.Liquid
|
||||
{
|
||||
public class UnderwaterPostProcessingController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Volume _underwaterVolume; // 水下专属 Volume(WeightMode)
|
||||
[SerializeField] private float _blendInDuration = 0.3f;
|
||||
[SerializeField] private float _blendOutDuration = 0.3f;
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidEntered; // EVT_LiquidEntered
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidExited; // EVT_LiquidExited
|
||||
|
||||
private Coroutine _blendCoroutine;
|
||||
private readonly CompositeDisposable _subs = new();
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_onLiquidEntered?.Subscribe(OnLiquidEntered).AddTo(_subs);
|
||||
_onLiquidExited?.Subscribe(OnLiquidExited).AddTo(_subs);
|
||||
}
|
||||
|
||||
private void OnDisable() => _subs.Clear();
|
||||
|
||||
private void OnLiquidEntered(LiquidEvent evt)
|
||||
{
|
||||
if (evt.LiquidType != nameof(LiquidType.Water)) return;
|
||||
BlendVolume(1f, _blendInDuration);
|
||||
}
|
||||
|
||||
private void OnLiquidExited(LiquidEvent evt) => BlendVolume(0f, _blendOutDuration);
|
||||
|
||||
private void BlendVolume(float target, float duration)
|
||||
{
|
||||
if (_blendCoroutine != null) StopCoroutine(_blendCoroutine);
|
||||
_blendCoroutine = StartCoroutine(BlendRoutine(target, duration));
|
||||
}
|
||||
|
||||
private IEnumerator BlendRoutine(float target, float duration)
|
||||
{
|
||||
if (_underwaterVolume == null) yield break;
|
||||
float start = _underwaterVolume.weight;
|
||||
float elapsed = 0f;
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
_underwaterVolume.weight = Mathf.Lerp(start, target, elapsed / duration);
|
||||
yield return null;
|
||||
}
|
||||
_underwaterVolume.weight = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d973b7199e1c854685e66fab26091bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
69
Assets/Scripts/World/Liquid/WaterDangerState.cs
Normal file
69
Assets/Scripts/World/Liquid/WaterDangerState.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
// Assets/Scripts/World/Liquid/WaterDangerState.cs
|
||||
|
||||
using BaseGames.Core.Events;
|
||||
using BaseGames.Player;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.World.Liquid
|
||||
{
|
||||
/// <summary>
|
||||
/// 当玩家进入 Water 类型液体且未解锁游泳能力时,触发溺水倒计时。
|
||||
/// 订阅 EVT_LiquidEntered / EVT_LiquidExited 事件频道。
|
||||
/// </summary>
|
||||
public class WaterDangerState : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private LiquidPhysicsConfigSO _config;
|
||||
[SerializeField] private PlayerStats _playerStats; // 检查 Swim 能力
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidEntered; // EVT_LiquidEntered
|
||||
[SerializeField] private LiquidEventChannelSO _onLiquidExited; // EVT_LiquidExited
|
||||
[SerializeField] private FloatEventChannelSO _onDrownProgress; // 0~1 倒计时进度(HUD 用)
|
||||
[SerializeField] private VoidEventChannelSO _onPlayerDrowned; // 触发死亡
|
||||
|
||||
private float _drownTimer;
|
||||
private bool _isActive;
|
||||
private readonly CompositeDisposable _subs = new();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Debug.Assert(_config != null, "[WaterDangerState] _config 未赋值,请在 Inspector 中指定 LiquidPhysicsConfigSO。", this);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_onLiquidEntered?.Subscribe(OnEnterLiquid).AddTo(_subs);
|
||||
_onLiquidExited?.Subscribe(OnExitLiquid).AddTo(_subs);
|
||||
}
|
||||
|
||||
private void OnDisable() => _subs.Clear();
|
||||
|
||||
public void OnEnterLiquid(LiquidEvent evt)
|
||||
{
|
||||
if (evt.LiquidType != nameof(LiquidType.Water)) return;
|
||||
if (_playerStats != null && _playerStats.HasAbility(AbilityType.Swim)) return;
|
||||
_isActive = true;
|
||||
_drownTimer = _config.DrownTime;
|
||||
}
|
||||
|
||||
public void OnExitLiquid(LiquidEvent evt)
|
||||
{
|
||||
_isActive = false;
|
||||
_drownTimer = _config.DrownTime;
|
||||
_onDrownProgress?.Raise(0f);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_isActive) return;
|
||||
_drownTimer -= Time.deltaTime;
|
||||
|
||||
float drownTime = _config.DrownTime;
|
||||
_onDrownProgress?.Raise(1f - (_drownTimer / drownTime));
|
||||
|
||||
if (_drownTimer <= 0f)
|
||||
{
|
||||
_isActive = false;
|
||||
_onPlayerDrowned?.Raise();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/World/Liquid/WaterDangerState.cs.meta
Normal file
11
Assets/Scripts/World/Liquid/WaterDangerState.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8dc9fa2201584e04e93b12f7dc7bc6e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user