后处理+FEEL完全改进

This commit is contained in:
SoulliesOfficial
2025-12-22 18:36:29 -05:00
parent c3914da4ac
commit a2052bfe16
1427 changed files with 193092 additions and 374110 deletions

View File

@@ -1,35 +1,107 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Cielonos.MainGame.Characters;
using UniRx;
using UnityEngine;
using SLSFramework.General;
namespace Cielonos.MainGame.Characters
{
public partial class SelfTimeSubmodule : SubmoduleBase<CharacterBase>
{
public FloatReactiveProperty timeScaleCoefficient;
public float TimeScale => timeScaleCoefficient.Value * Time.timeScale;
public float DeltaTime => timeScaleCoefficient.Value * Time.deltaTime;
private TimeManager timeManager => TimeManager.Instance;
private IObservable<float> timeScaleObservable;
public FloatReactiveProperty localTimeScale;
private float globalTimeScale => timeManager.globalTimeScale.Value;
private float playerTimeScale => timeManager.playerTimeScale.Value;
private float alliedMinionTimeScale => timeManager.alliedMinionTimeScale.Value;
private float enemyTimeScale => timeManager.enemyTimeScale.Value;
private float nonPlayerTimeScale => timeManager.nonPlayerTimeScale.Value;
public float TimeScale => owner.fraction switch
{
Fraction.Player => localTimeScale.Value * globalTimeScale * playerTimeScale,
Fraction.AlliedMinion => localTimeScale.Value * globalTimeScale * alliedMinionTimeScale * nonPlayerTimeScale,
Fraction.Enemy => localTimeScale.Value * globalTimeScale * enemyTimeScale * nonPlayerTimeScale,
Fraction.Neutral => localTimeScale.Value * globalTimeScale * nonPlayerTimeScale,
_ => localTimeScale.Value * globalTimeScale
};
public float DeltaTime => owner.fraction switch
{
Fraction.Player => Time.deltaTime * localTimeScale.Value * globalTimeScale * playerTimeScale,
Fraction.AlliedMinion => Time.deltaTime * localTimeScale.Value * globalTimeScale * alliedMinionTimeScale * nonPlayerTimeScale,
Fraction.Enemy => Time.deltaTime * localTimeScale.Value * globalTimeScale * enemyTimeScale * nonPlayerTimeScale,
Fraction.Neutral => Time.deltaTime * localTimeScale.Value * globalTimeScale * nonPlayerTimeScale,
_ => Time.deltaTime * localTimeScale.Value * globalTimeScale
};
public SelfTimeSubmodule(CharacterBase entity) : base(entity)
{
timeScaleCoefficient = new FloatReactiveProperty(1);
localTimeScale = new FloatReactiveProperty(1);
switch (owner.fraction)
{
case Fraction.Player:
// 依赖: local, global, player
timeScaleObservable =
localTimeScale.CombineLatest(
timeManager.globalTimeScale,
timeManager.playerTimeScale,
(local, global, player) => local * global * player
);
break;
case Fraction.AlliedMinion:
// 依赖: local, global, alliedMinion, nonPlayer
timeScaleObservable =
localTimeScale.CombineLatest(
timeManager.globalTimeScale,
timeManager.alliedMinionTimeScale,
timeManager.nonPlayerTimeScale,
(local, global, minion, nonPlayer) => local * global * minion * nonPlayer
);
break;
case Fraction.Enemy:
// 依赖: local, global, enemy, nonPlayer
timeScaleObservable =
localTimeScale.CombineLatest(
timeManager.globalTimeScale,
timeManager.enemyTimeScale,
timeManager.nonPlayerTimeScale,
(local, global, enemy, nonPlayer) => local * global * enemy * nonPlayer
);
break;
case Fraction.Neutral:
// 依赖: local, global, nonPlayer
timeScaleObservable =
localTimeScale.CombineLatest(
timeManager.globalTimeScale,
timeManager.nonPlayerTimeScale,
(local, global, nonPlayer) => local * global * nonPlayer
);
break;
default:
throw new ArgumentOutOfRangeException();
}
if (entity.animationSc != null)
{
timeScaleCoefficient.Subscribe(x =>
timeScaleObservable.Subscribe(timeScale =>
{
entity.animationSc.fullBodyFuncAnimSm.currentPlaySpeedMultiplier = x;
entity.animationSc.fullBodyFuncAnimSm.currentPlaySpeedMultiplier = timeScale;
});
}
if (entity.animationSc.animator != null)
{
timeScaleCoefficient.Subscribe(x =>
timeScaleObservable.Subscribe(timeScale =>
{
entity.animationSc.animator.speed = x;
entity.animationSc.animator.speed = timeScale;
});
}
}
@@ -59,6 +131,26 @@ namespace Cielonos.MainGame.Characters
() => onComplete?.Invoke() // 4. 流结束时TakeWhile 返回 false执行 Action
).AddTo(owner); // 5. 绑定生命周期到角色,防止内存泄漏
}
public IDisposable AddGlobalTimer(float duration, Action onComplete, Action onUpdate = null)
{
// 用于记录累积时间
float accumulatedTime = 0f;
return Observable.EveryUpdate()
.Select(_ => Time.deltaTime) // 1. 获取每帧的全局 DeltaTime
.TakeWhile(dt =>
{
// 2. 累加时间
accumulatedTime += dt;
// 3. 如果累积时间小于总时长,继续流;否则停止流并触发 OnCompleted
return accumulatedTime < duration;
})
.Subscribe(
_ => onUpdate?.Invoke(), // 每帧更新时执行 Action
() => onComplete?.Invoke() // 4. 流结束时TakeWhile 返回 false执行 Action
).AddTo(owner); // 5. 绑定生命周期到角色,防止内存泄漏
}
}
public partial class SelfTimeSubmodule
@@ -84,7 +176,7 @@ namespace Cielonos.MainGame.Characters
hitStopDisposable?.Dispose();
// 2. 设置当前的缩放倍率
timeScaleCoefficient.Value = targetScale;
localTimeScale.Value = targetScale;
// 3. 开启计时器
// 注意:这里使用 Scheduler.MainThread它是基于 Time.time (全局时间) 的。
@@ -95,7 +187,7 @@ namespace Cielonos.MainGame.Characters
.Subscribe(_ =>
{
// 计时结束,恢复为 1
timeScaleCoefficient.Value = 1f;
localTimeScale.Value = 1f;
hitStopDisposable = null;
})
.AddTo(owner); // 安全性:如果角色在顿帧期间死亡/销毁,自动取消计时器
@@ -105,17 +197,16 @@ namespace Cielonos.MainGame.Characters
/// 使用曲线动态修改本地时间流速
/// </summary>
/// <param name="duration">持续时间(秒)</param>
/// <param name="start">曲线值为0时对应的时间倍率通常是初始值</param>
/// <param name="peak">曲线值为1时对应的时间倍率通常是极值</param>
/// <param name="curve">时间变化曲线归一化X轴0~1Y轴通常0~1。如果为null则使用默认的“先升后降”抛物线。</param>
public void ModifyTimeScale(float duration, float start, float peak, AnimationCurve curve = null)
/// <param name="zeroValue">曲线起点值</param>
/// <param name="oneValue">曲线终点值</param>
/// <param name="easeType">插值曲线(null 则使用默认的 EaseInOut (从0到1) 曲线)</param>
public void ModifyTimeScale(float duration, EaseType easeType, float zeroValue = 0, float oneValue = 1)
{
// 1. 清理旧的计时器
hitStopDisposable?.Dispose();
// 2. 处理默认曲线逻辑
curve ??= DefaultParabola;
AnimationCurve curve = Ease.GetCurve(easeType);
// 3. 记录开始时的累计时间
float timer = 0f;
@@ -125,30 +216,27 @@ namespace Cielonos.MainGame.Characters
.Subscribe(
_ =>
{
// 累加时间 (使用 Time.deltaTime 以响应全局暂停)
timer += Time.deltaTime;
// 累加时间
timer += DeltaTime;
// 计算归一化进度 (0.0 ~ 1.0)
float progress = Mathf.Clamp01(timer / duration);
// 计算归一化时间(0 1
float normalizedTime = Mathf.Clamp01(timer / duration);
// 核心逻辑:
// A. 从曲线获取当前的“强度” (Y轴值)
float curveValue = curve.Evaluate(progress);
// 根据曲线获取当前的插值系数
float curveValue = curve.Evaluate(normalizedTime);
// B. 在 start 和 peak 之间根据强度进行插
// 当 curveValue = 0 时,结果为 start
// 当 curveValue = 1 时,结果为 peak
float currentScale = Mathf.Lerp(start, peak, curveValue);
// 计算当前的时间缩放
float currentScale = curveValue * (oneValue - zeroValue) + zeroValue;
// C. 应用到响应式属性
timeScaleCoefficient.Value = currentScale;
// 应用到 timeScaleCoefficient
localTimeScale.Value = currentScale;
},
() =>
{
// 5. 计时结束后的收尾工作
// 通常为了安全,结束后我们会强制恢复到 1.0 (正常速度)
// 或者你可以恢复到 start视具体需求而定
timeScaleCoefficient.Value = 1f;
localTimeScale.Value = 1f;
hitStopDisposable = null;
}
)
@@ -159,7 +247,7 @@ namespace Cielonos.MainGame.Characters
public void ResetTimeScale()
{
hitStopDisposable?.Dispose();
timeScaleCoefficient.Value = 1f;
localTimeScale.Value = 1f;
}
}
}