后处理+FEEL完全改进
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2712eaaa5cd99242bdcacf69b09ef19
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9f6d40bf0b6ee642a3212e13c2c5bf1
|
||||
@@ -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 上的 FollowTarget,Z 轴旋转将作用于相机的 Dutch。
|
||||
/// 需要在 Virtual Camera 上挂载 MMCinemachineRotationShaker。
|
||||
/// </summary>
|
||||
[AddComponentMenu("")]
|
||||
[FeedbackPath("Camera/Cinemachine Rotation Shake")]
|
||||
[FeedbackHelp("控制 Cinemachine 相机的旋转抖动。X/Y 轴作用于 Shaker 指定的 FollowTarget,Z 轴作用于相机的 Dutch。需要在 Virtual Camera 上挂载 MMCinemachineRotationShaker。")]
|
||||
[FeedbackHelp("控制 Cinemachine 相机的旋转抖动。X/Y 轴作用于 Shaker 指定的 FollowTarget,Z 轴作用于相机的 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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user