后处理+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

@@ -0,0 +1,106 @@
using UnityEngine;
using MoreMountains.Feedbacks;
using MoreMountains.Tools;
namespace MoreMountains.FeedbacksForThirdParty
{
/// <summary>
/// 这个 Feedback 用于触发 MMCinemachineCameraDistanceShakeEvent
/// 进而控制挂载了 MMCinemachineCameraDistanceShaker 的相机距离。
/// </summary>
[AddComponentMenu("")]
[FeedbackHelp("This feedback allows you to control the Camera Distance of a Cinemachine Camera over time. You need a MMCinemachineCameraDistanceShaker on your camera.")]
[FeedbackPath("Camera/Cinemachine Camera Distance")]
public class MMF_CinemachineCameraDistance : MMF_Feedback
{
/// 用于禁用此类 Feedback 的静态开关
public static bool FeedbackTypeAuthorized = true;
/// 用于在 Inspector 列表中显示的颜色(这里使用了 Cinemachine 标志性的红色/橙色)
#if UNITY_EDITOR
public override Color FeedbackColor { get { return MMFeedbacksInspectorColors.CameraColor; } }
public override bool EvaluateRequiresSetup() { return (GameObject.FindObjectOfType<MMCinemachineCameraDistanceShaker>() == null); }
//public override string RequiredTargetText { get { return "MMCinemachineCameraDistanceShaker"; } }
public override string RequiresSetupText { get { return "This feedback requires that a MMCinemachineCameraDistanceShaker be present in your scene, typically on your Cinemachine Camera."; } }
#endif
[MMFInspectorGroup("Camera Distance", true, 72)]
[Tooltip("震动持续时间")]
public float ShakeDuration = 0.2f;
[Tooltip("是否使用相对值。如果勾选,将会在当前距离的基础上增加/减少;如果不勾选,则直接设置距离为绝对值。")]
public bool RelativeDistance = true;
[Tooltip("控制距离变化的曲线")]
public AnimationCurve ShakeDistance = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.5f, 1), new Keyframe(1, 0));
[Tooltip("曲线值为 0 时对应的距离(或增量)")]
public float RemapDistanceZero = 0f;
[Tooltip("曲线值为 1 时对应的距离(或增量)")]
public float RemapDistanceOne = -2f; // 默认 -2意味着产生“瞬间拉近”的效果非常适合打击感
[Tooltip("如果勾选Shake 结束后将重置 Shaker 的参数")]
public bool ResetShakerValuesAfterShake = true;
[Tooltip("如果勾选Shake 结束后相机的距离将恢复到初始值")]
public bool ResetTargetValuesAfterShake = true;
/// <summary>
/// 播放 Feedback
/// </summary>
protected override void CustomPlayFeedback(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (!Active || !FeedbackTypeAuthorized)
{
return;
}
// 触发我们在上一步中定义的 Event
MMCinemachineCameraDistanceShakeEvent.Trigger(
ShakeDistance,
ShakeDuration,
RemapDistanceZero,
RemapDistanceOne,
RelativeDistance,
feedbacksIntensity,
ChannelData,
ResetShakerValuesAfterShake,
ResetTargetValuesAfterShake,
NormalPlayDirection,
ComputedTimescaleMode
);
}
/// <summary>
/// 停止 Feedback
/// </summary>
protected override void CustomStopFeedback(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (!Active || !FeedbackTypeAuthorized)
{
return;
}
MMCinemachineCameraDistanceShakeEvent.Trigger(
ShakeDistance,
ShakeDuration,
RemapDistanceZero,
RemapDistanceOne,
RelativeDistance,
feedbacksIntensity,
ChannelData,
ResetShakerValuesAfterShake,
ResetTargetValuesAfterShake,
NormalPlayDirection,
ComputedTimescaleMode,
stop: true
);
}
protected override void CustomRestoreInitialValues()
{
MMCinemachineCameraDistanceShakeEvent.Trigger(ShakeDistance, FeedbackDuration, 0f, 1f, false, restore: true);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e2712eaaa5cd99242bdcacf69b09ef19

View File

@@ -0,0 +1,126 @@
using MoreMountains.FeedbacksForThirdParty;
using MoreMountains.Tools;
using UnityEngine;
namespace MoreMountains.Feedbacks
{
public struct MMCinemachinePositionShakeEvent
{
static private event Delegate OnEvent;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void RuntimeInitialization()
{
OnEvent = null;
}
public static void Register(Delegate callback)
{
OnEvent += callback;
}
public static void Unregister(Delegate callback)
{
OnEvent -= callback;
}
public delegate void Delegate(MMF_Feedback source, AnimationCurve shakeCurve, float duration, Vector3 positionAmplitude,
float feedbacksIntensity = 1.0f, MMChannelData channelData = null, bool resetShakerValuesAfterShake = true,
bool resetTargetValuesAfterShake = true, bool forwardDirection = true, TimescaleModes timescaleMode = TimescaleModes.Scaled,
bool stop = false);
public static void Trigger(MMF_Feedback source, AnimationCurve shakeCurve, float duration, Vector3 positionAmplitude,
float feedbacksIntensity = 1.0f, MMChannelData channelData = null, bool resetShakerValuesAfterShake = true,
bool resetTargetValuesAfterShake = true, bool forwardDirection = true, TimescaleModes timescaleMode = TimescaleModes.Scaled,
bool stop = false)
{
OnEvent?.Invoke(source, shakeCurve, duration, positionAmplitude, feedbacksIntensity, channelData, resetShakerValuesAfterShake,
resetTargetValuesAfterShake, forwardDirection, timescaleMode, stop);
}
}
[FeedbackPath("Camera/Cinemachine Position Shake")]
public class MMF_CinemachinePosition : MMF_Feedback
{
public static bool FeedbackTypeAuthorized = true;
public override float FeedbackDuration { get { return ApplyTimeMultiplier(Duration); } set { Duration = value; } }
public override bool HasChannel => true;
#if UNITY_EDITOR
public override Color FeedbackColor { get { return MMFeedbacksInspectorColors.CameraColor; } }
public override bool EvaluateRequiresSetup() { return (GameObject.FindObjectOfType<MMCinemachinePositionShaker>() == null); }
public override string RequiredTargetText { get { return "MMCinemachinePositionShaker"; } }
public override string RequiresSetupText { get { return "This feedback requires a MMCinemachinePositionShaker on your Camera."; } }
#endif
[MMFInspectorGroup("Position Shake", true, 39)]
public float Duration = 0.2f;
[Tooltip("The maximum amplitude of the shake.")]
public Vector3 PositionAmplitude = new Vector3(0.5f, 0.5f, 0f);
[Tooltip("The curve along which the shake will be animated.")]
public AnimationCurve ShakeCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.2f, 1), new Keyframe(1, 0));
[MMFInspectorGroup("Distance Attenuation", true, 38)]
[Tooltip("如果勾选,抖动强度将根据摄像机与反馈位置的距离而衰减")]
public bool UseAttenuation = false;
[Tooltip("在这个范围内,抖动为全强度")]
public float AttenuationRange = 50f;
[Tooltip("定义强度随距离变化的曲线 (0代表近处/全强度, 1代表远处/无强度)")]
public AnimationCurve AttenuationCurve = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0f));
[Header("Gizmos")]
public bool DrawGizmos = true;
protected override void CustomPlayFeedback(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (!Active || !FeedbackTypeAuthorized) return;
float intensityMultiplier = ComputeIntensity(feedbacksIntensity, position);
// 处理距离衰减
if (UseAttenuation && Camera.main != null)
{
float distance = Vector3.Distance(position, Camera.main.transform.position);
float normalizedDistance = Mathf.Clamp01(distance / AttenuationRange);
// 乘上衰减系数
intensityMultiplier *= AttenuationCurve.Evaluate(normalizedDistance);
}
// 触发事件
MMCinemachinePositionShakeEvent.Trigger(
this,
ShakeCurve,
FeedbackDuration,
PositionAmplitude,
intensityMultiplier,
ChannelData,
true, // resetShakerValues (在这种叠加模式下这个参数其实没用了,但保持签名一致)
true, // resetTargetValues (同上)
NormalPlayDirection,
ComputedTimescaleMode
);
}
protected override void CustomStopFeedback(Vector3 position, float feedbacksIntensity = 1.0f)
{
if (!Active || !FeedbackTypeAuthorized) return;
MMCinemachinePositionShakeEvent.Trigger(
this, ShakeCurve, FeedbackDuration, PositionAmplitude,
0f, ChannelData, stop: true
);
}
public override void OnDrawGizmosSelectedHandler()
{
if (UseAttenuation && DrawGizmos)
{
Gizmos.color = MMColors.ReunoYellow;
Gizmos.DrawWireSphere(Owner.transform.position, AttenuationRange);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c9f6d40bf0b6ee642a3212e13c2c5bf1

View File

@@ -1,28 +1,21 @@
using MoreMountains.FeedbacksForThirdParty;
using MoreMountains.Feedbacks;
using MoreMountains.Tools;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Scripting.APIUpdating;
namespace MoreMountains.Feedbacks
namespace MoreMountains.FeedbacksForThirdParty
{
/// <summary>
/// 这个 Feedback 用于控制 Cinemachine 相机的旋转抖动。
/// X/Y 轴旋转将作用于 Shaker 上的 FollowTargetZ 轴旋转将作用于相机的 Dutch。
/// 需要在 Virtual Camera 上挂载 MMCinemachineRotationShaker。
/// </summary>
[AddComponentMenu("")]
[FeedbackPath("Camera/Cinemachine Rotation Shake")]
[FeedbackHelp("控制 Cinemachine 相机的旋转抖动。X/Y 轴作用于 Shaker 指定的 FollowTargetZ 轴作用于相机的 Dutch。需要在 Virtual Camera 上挂载 MMCinemachineRotationShaker。")]
[FeedbackHelp("控制 Cinemachine 相机的旋转抖动。X/Y 轴作用于 Shaker 指定的 FollowTargetZ 轴作用于相机的 Dutch。支持多个 Feedback 混合叠加。")]
public class MMF_CinemachineRotation : MMF_Feedback
{
/// 用于禁用此类 Feedback 的静态开关
public static bool FeedbackTypeAuthorized = true;
#if UNITY_EDITOR
public override Color FeedbackColor => MMFeedbacksInspectorColors.CameraColor;
public override bool HasCustomInspectors => true;
public override bool HasAutomaticShakerSetup => true;
public override bool EvaluateRequiresSetup() { return (GameObject.FindObjectOfType<MMCinemachineRotationShaker>() == null); }
public override string RequiredTargetText { get { return "MMCinemachineRotationShaker"; } }
public override string RequiresSetupText { get { return "This feedback requires a MMCinemachineRotationShaker on your Camera."; } }
#endif
public override float FeedbackDuration { get { return ApplyTimeMultiplier(Duration); } set { Duration = value; } }
@@ -39,7 +32,7 @@ namespace MoreMountains.Feedbacks
[Tooltip("定义抖动随时间变化的曲线")]
public AnimationCurve ShakeCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.2f, 1), new Keyframe(1, 0));
[MMFInspectorGroup("Distance Attenuation (距离衰减)", true, 38)]
[MMFInspectorGroup("Distance Attenuation", true, 38)]
[Tooltip("如果勾选,抖动强度将根据摄像机与反馈位置的距离而衰减")]
public bool UseAttenuation = false;
[Tooltip("在这个范围内,抖动为全强度")]
@@ -47,12 +40,6 @@ namespace MoreMountains.Feedbacks
[Tooltip("定义强度随距离变化的曲线 (0代表近处/全强度, 1代表远处/无强度)")]
public AnimationCurve AttenuationCurve = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 0f));
[Space]
[Tooltip("抖动结束后是否重置 Shaker 的值为默认值")]
public bool ResetShakerValuesAfterShake = true;
[Tooltip("抖动结束后是否将目标的旋转归零")]
public bool ResetTargetValuesAfterShake = true;
[Header("Gizmos")]
public bool DrawGizmos = true;
@@ -66,20 +53,22 @@ namespace MoreMountains.Feedbacks
if (UseAttenuation && Camera.main != null)
{
float distance = Vector3.Distance(position, Camera.main.transform.position);
// 简单的线性映射,或者使用曲线
float normalizedDistance = Mathf.Clamp01(distance / AttenuationRange);
// 乘上衰减系数
intensityMultiplier *= AttenuationCurve.Evaluate(normalizedDistance);
}
// 触发事件 (叠加模式下ResetShakerValuesAfterShake 和 ResetTargetValuesAfterShake 不再起主要作用,但保留参数)
MMCinemachineRotationShakeEvent.Trigger(
this,
ShakeCurve,
FeedbackDuration,
RotationAmplitude,
0f, 1f, false, // RemapMin/Max 和 Relative 暂时不用,保留接口
0f, 1f, false,
intensityMultiplier,
ChannelData,
ResetShakerValuesAfterShake,
ResetTargetValuesAfterShake,
true, // resetShaker
true, // resetTarget
NormalPlayDirection,
ComputedTimescaleMode
);
@@ -88,14 +77,14 @@ namespace MoreMountains.Feedbacks
protected override void CustomStopFeedback(Vector3 position, float feedbacksIntensity = 1)
{
if (!Active || !FeedbackTypeAuthorized) return;
base.CustomStopFeedback(position, feedbacksIntensity);
MMCinemachineRotationShakeEvent.Trigger(ShakeCurve, FeedbackDuration, RotationAmplitude, 0f, 1f, false, stop: true);
// 发送 Stop 指令,这会清除 Shaker 中的所有列表
MMCinemachineRotationShakeEvent.Trigger(this, ShakeCurve, FeedbackDuration, RotationAmplitude, 0f, 1f, false, stop: true);
}
protected override void CustomRestoreInitialValues()
{
if (!Active || !FeedbackTypeAuthorized) return;
MMCinemachineRotationShakeEvent.Trigger(ShakeCurve, FeedbackDuration, RotationAmplitude, 0f, 1f, false, restore: true);
MMCinemachineRotationShakeEvent.Trigger(this, ShakeCurve, FeedbackDuration, RotationAmplitude, 0f, 1f, false, restore: true);
}
public override void OnDrawGizmosSelectedHandler()
@@ -106,20 +95,5 @@ namespace MoreMountains.Feedbacks
Gizmos.DrawWireSphere(Owner.transform.position, AttenuationRange);
}
}
public override void AutomaticShakerSetup()
{
// 自动查找并添加 Shaker
#if MM_CINEMACHINE
Cinemachine.CinemachineVirtualCamera vcam = Object.FindObjectOfType<Cinemachine.CinemachineVirtualCamera>();
if (vcam != null)
{
if (vcam.GetComponent<MMCinemachineRotationShaker>() == null)
{
vcam.gameObject.AddComponent<MMCinemachineRotationShaker>();
}
}
#endif
}
}
}