345 lines
11 KiB
C#
345 lines
11 KiB
C#
using SmoothShakeFree;
|
|
using UnityEngine;
|
|
|
|
public class effectEventController : MonoBehaviour
|
|
{
|
|
public enum CameraOffsetAxis
|
|
{
|
|
X,
|
|
Y,
|
|
Z
|
|
}
|
|
|
|
public static effectEventController Instance { get; private set; }
|
|
|
|
[Header("Multi Note Screen Shake")]
|
|
public bool enableMultiNoteScreenShake = true;
|
|
public float multiNoteScreenShakeAmplitude = 0.08f;
|
|
|
|
[Header("Camera Drift")]
|
|
public bool enableCameraDrift = false;
|
|
public Vector2 cameraDriftRange = new Vector2(0.15f, 0.08f);
|
|
public float cameraDriftSpeed = 0.3f;
|
|
|
|
[Header("Player Skill 10 Camera Offset")]
|
|
public float playerSkillCameraOffsetAmount = 0.6f;
|
|
public CameraOffsetAxis playerSkillCameraOffsetAxis = CameraOffsetAxis.Y;
|
|
|
|
[Header("Track Crash")]
|
|
[SerializeField] private TrackCrashController trackCrashController;
|
|
|
|
private Transform cachedShakeTarget;
|
|
private Transform cachedCameraDriftPivot;
|
|
private Transform cachedCameraSkillPivot;
|
|
private Vector3 cameraDriftBaseLocalPosition;
|
|
private Vector3 cameraSkillBaseLocalPosition;
|
|
private float cameraDriftSeedX;
|
|
private float cameraDriftSeedY;
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance == null)
|
|
{
|
|
Instance = this;
|
|
cameraDriftSeedX = Random.Range(0f, 1000f);
|
|
cameraDriftSeedY = Random.Range(1000f, 2000f);
|
|
CacheShakeTarget();
|
|
return;
|
|
}
|
|
|
|
if (Instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
CacheShakeTarget();
|
|
ResetCameraDriftIfNeeded();
|
|
CacheTrackCrashController();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
UpdateCameraDrift();
|
|
UpdatePlayerSkillCameraOffset();
|
|
}
|
|
|
|
private void CacheShakeTarget()
|
|
{
|
|
if (Camera.main != null)
|
|
{
|
|
cachedShakeTarget = Camera.main.transform;
|
|
PrewarmShakeComponent();
|
|
EnsureCameraDriftPivot();
|
|
EnsureCameraSkillPivot();
|
|
}
|
|
}
|
|
|
|
private void CacheTrackCrashController()
|
|
{
|
|
if (trackCrashController == null)
|
|
{
|
|
trackCrashController = SceneObjectLookupCache.FindAny<TrackCrashController>();
|
|
}
|
|
}
|
|
|
|
private void PrewarmShakeComponent()
|
|
{
|
|
if (cachedShakeTarget == null)
|
|
return;
|
|
|
|
SmoothShake shake = cachedShakeTarget.GetComponent<SmoothShake>();
|
|
if (shake == null)
|
|
{
|
|
shake = cachedShakeTarget.gameObject.AddComponent<SmoothShake>();
|
|
}
|
|
|
|
if (shake.positionShake == null) shake.positionShake = new Shaker();
|
|
if (shake.rotationShake == null) shake.rotationShake = new Shaker();
|
|
if (shake.shakers == null || shake.shakers.Length != 2)
|
|
shake.shakers = new[] { shake.positionShake, shake.rotationShake };
|
|
if (shake.sum == null || shake.sum.Length != 2)
|
|
shake.sum = new Vector3[2];
|
|
}
|
|
|
|
private void EnsureCameraDriftPivot()
|
|
{
|
|
if (cachedShakeTarget == null)
|
|
return;
|
|
|
|
if (cachedCameraDriftPivot != null)
|
|
return;
|
|
|
|
Transform currentParent = cachedShakeTarget.parent;
|
|
if (currentParent != null && currentParent.name == "__effect_event_camera_drift_pivot")
|
|
{
|
|
cachedCameraDriftPivot = currentParent;
|
|
cameraDriftBaseLocalPosition = cachedCameraDriftPivot.localPosition;
|
|
return;
|
|
}
|
|
|
|
GameObject pivotObject = new GameObject("__effect_event_camera_drift_pivot");
|
|
Transform pivot = pivotObject.transform;
|
|
|
|
if (currentParent != null)
|
|
{
|
|
pivot.SetParent(currentParent, false);
|
|
pivot.localPosition = cachedShakeTarget.localPosition;
|
|
pivot.localRotation = cachedShakeTarget.localRotation;
|
|
pivot.localScale = Vector3.one;
|
|
}
|
|
else
|
|
{
|
|
pivot.position = cachedShakeTarget.position;
|
|
pivot.rotation = cachedShakeTarget.rotation;
|
|
}
|
|
|
|
cachedShakeTarget.SetParent(pivot, true);
|
|
cachedShakeTarget.localRotation = Quaternion.identity;
|
|
|
|
cachedCameraDriftPivot = pivot;
|
|
cameraDriftBaseLocalPosition = cachedCameraDriftPivot.localPosition;
|
|
}
|
|
|
|
private void EnsureCameraSkillPivot()
|
|
{
|
|
if (cachedShakeTarget == null)
|
|
return;
|
|
|
|
if (cachedCameraSkillPivot != null)
|
|
return;
|
|
|
|
Transform currentParent = cachedShakeTarget.parent;
|
|
if (currentParent != null && currentParent.name == "__effect_event_camera_skill_pivot")
|
|
{
|
|
cachedCameraSkillPivot = currentParent;
|
|
cameraSkillBaseLocalPosition = cachedCameraSkillPivot.localPosition;
|
|
return;
|
|
}
|
|
|
|
GameObject pivotObject = new GameObject("__effect_event_camera_skill_pivot");
|
|
Transform pivot = pivotObject.transform;
|
|
|
|
if (currentParent != null)
|
|
{
|
|
pivot.SetParent(currentParent, false);
|
|
pivot.localPosition = cachedShakeTarget.localPosition;
|
|
pivot.localRotation = cachedShakeTarget.localRotation;
|
|
pivot.localScale = Vector3.one;
|
|
}
|
|
else
|
|
{
|
|
pivot.position = cachedShakeTarget.position;
|
|
pivot.rotation = cachedShakeTarget.rotation;
|
|
pivot.localScale = Vector3.one;
|
|
}
|
|
|
|
cachedShakeTarget.SetParent(pivot, true);
|
|
cachedShakeTarget.localPosition = Vector3.zero;
|
|
cachedShakeTarget.localRotation = Quaternion.identity;
|
|
|
|
cachedCameraSkillPivot = pivot;
|
|
cameraSkillBaseLocalPosition = cachedCameraSkillPivot.localPosition;
|
|
}
|
|
|
|
private void UpdateCameraDrift()
|
|
{
|
|
if (cachedShakeTarget == null)
|
|
{
|
|
CacheShakeTarget();
|
|
}
|
|
|
|
if (cachedShakeTarget == null)
|
|
return;
|
|
|
|
EnsureCameraDriftPivot();
|
|
if (cachedCameraDriftPivot == null)
|
|
return;
|
|
|
|
if (!enableCameraDrift)
|
|
{
|
|
ResetCameraDriftIfNeeded();
|
|
return;
|
|
}
|
|
|
|
float speed = Mathf.Max(0f, cameraDriftSpeed);
|
|
float time = GameplayClock.NowSongTime * speed;
|
|
float offsetX = (Mathf.PerlinNoise(cameraDriftSeedX, time) - 0.5f) * 2f * Mathf.Abs(cameraDriftRange.x);
|
|
float offsetY = (Mathf.PerlinNoise(cameraDriftSeedY, time) - 0.5f) * 2f * Mathf.Abs(cameraDriftRange.y);
|
|
|
|
cachedCameraDriftPivot.localPosition = cameraDriftBaseLocalPosition + new Vector3(offsetX, offsetY, 0f);
|
|
}
|
|
|
|
private void ResetCameraDriftIfNeeded()
|
|
{
|
|
if (cachedCameraDriftPivot == null)
|
|
return;
|
|
|
|
cachedCameraDriftPivot.localPosition = cameraDriftBaseLocalPosition;
|
|
}
|
|
|
|
private void UpdatePlayerSkillCameraOffset()
|
|
{
|
|
if (cachedShakeTarget == null)
|
|
{
|
|
CacheShakeTarget();
|
|
}
|
|
|
|
if (cachedShakeTarget == null)
|
|
return;
|
|
|
|
EnsureCameraSkillPivot();
|
|
if (cachedCameraSkillPivot == null)
|
|
return;
|
|
|
|
Vector3 targetLocalPosition = cameraSkillBaseLocalPosition;
|
|
if (PlayerSkillService.IsSkillEnabled(10))
|
|
{
|
|
float offset = playerSkillCameraOffsetAmount;
|
|
switch (playerSkillCameraOffsetAxis)
|
|
{
|
|
case CameraOffsetAxis.X:
|
|
targetLocalPosition.x += offset;
|
|
break;
|
|
case CameraOffsetAxis.Y:
|
|
targetLocalPosition.y += offset;
|
|
break;
|
|
case CameraOffsetAxis.Z:
|
|
targetLocalPosition.z += offset;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cachedCameraSkillPivot.localPosition != targetLocalPosition)
|
|
{
|
|
cachedCameraSkillPivot.localPosition = targetLocalPosition;
|
|
}
|
|
}
|
|
|
|
public static void RefreshPlayerSkillCameraOffset()
|
|
{
|
|
effectEventController controller = Instance != null ? Instance : SceneObjectLookupCache.FindAny<effectEventController>();
|
|
if (controller == null)
|
|
return;
|
|
|
|
controller.CacheShakeTarget();
|
|
controller.UpdatePlayerSkillCameraOffset();
|
|
}
|
|
|
|
public static void TryTriggerMultiNoteShake()
|
|
{
|
|
effectEventController controller = Instance != null ? Instance : SceneObjectLookupCache.FindAny<effectEventController>();
|
|
if (controller == null)
|
|
return;
|
|
|
|
controller.TriggerMultiNoteShakeInternal();
|
|
}
|
|
|
|
public static void TryTriggerTrackCrash(int trackIndex)
|
|
{
|
|
effectEventController controller = Instance != null ? Instance : SceneObjectLookupCache.FindAny<effectEventController>();
|
|
if (controller == null)
|
|
return;
|
|
|
|
controller.TriggerTrackCrashInternal(trackIndex);
|
|
}
|
|
|
|
private void TriggerMultiNoteShakeInternal()
|
|
{
|
|
if (!enableMultiNoteScreenShake)
|
|
return;
|
|
|
|
if (cachedShakeTarget == null)
|
|
{
|
|
CacheShakeTarget();
|
|
}
|
|
|
|
if (cachedShakeTarget == null)
|
|
return;
|
|
|
|
float amplitudeValue = Mathf.Max(0f, multiNoteScreenShakeAmplitude);
|
|
if (amplitudeValue <= 0f)
|
|
return;
|
|
|
|
SmoothShake shake = cachedShakeTarget.GetComponent<SmoothShake>();
|
|
if (shake == null)
|
|
{
|
|
shake = cachedShakeTarget.gameObject.AddComponent<SmoothShake>();
|
|
}
|
|
|
|
if (shake.positionShake == null) shake.positionShake = new Shaker();
|
|
if (shake.rotationShake == null) shake.rotationShake = new Shaker();
|
|
|
|
shake.positionShake.noiseType = Shaker.NoiseType.SineWave;
|
|
shake.positionShake.amplitude = new Vector3(amplitudeValue, amplitudeValue, 0f);
|
|
shake.positionShake.frequency = new Vector3(20f, 20f, 0f);
|
|
shake.rotationShake.amplitude = Vector3.zero;
|
|
shake.rotationShake.frequency = Vector3.zero;
|
|
|
|
shake.timeSettings.constantShake = false;
|
|
shake.timeSettings.fadeInDuration = 0.03f;
|
|
shake.timeSettings.holdDuration = 0.04f;
|
|
shake.timeSettings.fadeOutDuration = 0.05f;
|
|
|
|
if (shake.timeSettings.fadeInCurve == null || shake.timeSettings.fadeInCurve.length == 0)
|
|
shake.timeSettings.fadeInCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);
|
|
if (shake.timeSettings.fadeOutCurve == null || shake.timeSettings.fadeOutCurve.length == 0)
|
|
shake.timeSettings.fadeOutCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f);
|
|
|
|
shake.shakers = new[] { shake.positionShake, shake.rotationShake };
|
|
shake.sum = new Vector3[2];
|
|
shake.StartShake();
|
|
}
|
|
|
|
private void TriggerTrackCrashInternal(int trackIndex)
|
|
{
|
|
CacheTrackCrashController();
|
|
if (trackCrashController == null)
|
|
return;
|
|
|
|
trackCrashController.TriggerTrackCrash(trackIndex);
|
|
}
|
|
}
|