LightGlueCursorSettings.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using UnityEngine;
  2. namespace LightGlue.Unity.Game
  3. {
  4. /// <summary>
  5. /// 全局光标/跟随平滑设置(可挂在全局预制上,与 LightGlueManager 同节点或独立)。
  6. /// - 供 SimpleCameraPositionMarker、LightGlueCameraAimController 等读取,统一调节平滑参数。
  7. /// - 支持本地持久化(PlayerPrefs),启动时自动加载,修改后需调用 SaveToLocal() 保存。
  8. /// </summary>
  9. public class LightGlueCursorSettings : MonoBehaviour
  10. {
  11. public static LightGlueCursorSettings Instance { get; private set; }
  12. private const string KeyPrefix = "LightGlueCursor_";
  13. private const string KeyMarkerSmooth = KeyPrefix + "MarkerSmooth";
  14. private const string KeyMarkerLerp = KeyPrefix + "MarkerLerp";
  15. private const string KeyMarkerJitter = KeyPrefix + "MarkerJitter";
  16. private const string KeyCameraSmooth = KeyPrefix + "CameraSmooth";
  17. private const string KeyCameraLerp = KeyPrefix + "CameraLerp";
  18. private const string KeyCameraJitter = KeyPrefix + "CameraJitter";
  19. [Header("标记器跟随(SimpleCameraPositionMarker)")]
  20. [Tooltip("是否对 UI 标记位置做平滑插值")]
  21. public bool markerEnableSmoothFollow = true;
  22. [Tooltip("位置平滑插值速度,值越大响应越快")]
  23. public float markerPositionLerpSpeed = 100f;
  24. [Tooltip("抖动阈值(像素),小于该距离的位移将被忽略")]
  25. public float markerJitterThresholdPixels = 25f;
  26. [Tooltip("平滑曲线:横轴为进度 [0,1],纵轴为插值系数。由快到慢用缓出")]
  27. public AnimationCurve markerSmoothCurve = new AnimationCurve(
  28. new Keyframe(0f, 0f, 0f, 2f),
  29. new Keyframe(1f, 1f, 2f, 0f));
  30. [Header("相机朝向跟随(LightGlueCameraAimController)")]
  31. [Tooltip("是否对 CameraToLook 的旋转做平滑插值")]
  32. public bool cameraAimEnableSmoothRotation = true;
  33. [Tooltip("旋转平滑插值速度,值越大响应越快")]
  34. public float cameraAimRotationLerpSpeed = 100f;
  35. [Tooltip("旋转抖动阈值(角度,度),小于该角度变化将被忽略")]
  36. public float cameraAimRotationJitterThresholdDeg = 0.5f;
  37. [Tooltip("旋转平滑曲线:横轴为进度 [0,1],纵轴为插值系数")]
  38. public AnimationCurve cameraAimSmoothCurve = new AnimationCurve(
  39. new Keyframe(0f, 0f, 0f, 2f),
  40. new Keyframe(1f, 1f, 2f, 0f));
  41. /// <summary> 是否在 Awake 时从本地加载已保存的参数。 </summary>
  42. [Header("持久化")]
  43. [Tooltip("启动时是否从本地(PlayerPrefs)加载上次保存的参数")]
  44. public bool loadFromLocalOnAwake = true;
  45. [Header("显示控制")]
  46. [Tooltip("要控制显示/隐藏的 UI 根节点。不指定则使用本 GameObject")]
  47. public GameObject panelRoot;
  48. private void Awake()
  49. {
  50. if (Instance != null && Instance != this)
  51. {
  52. gameObject.SetActive(false);
  53. Destroy(gameObject);
  54. return;
  55. }
  56. Instance = this;
  57. if(panelRoot != null) panelRoot.SetActive(false);
  58. DontDestroyOnLoad(gameObject);
  59. if (loadFromLocalOnAwake)
  60. LoadFromLocal();
  61. }
  62. private void OnDestroy()
  63. {
  64. if (Instance == this)
  65. Instance = null;
  66. }
  67. /// <summary>
  68. /// 从本地(PlayerPrefs)加载已保存的参数;若无记录则保持当前 Inspector 默认值。
  69. /// </summary>
  70. public void LoadFromLocal()
  71. {
  72. if (PlayerPrefs.HasKey(KeyMarkerSmooth))
  73. markerEnableSmoothFollow = PlayerPrefs.GetInt(KeyMarkerSmooth) != 0;
  74. if (PlayerPrefs.HasKey(KeyMarkerLerp))
  75. markerPositionLerpSpeed = PlayerPrefs.GetFloat(KeyMarkerLerp);
  76. if (PlayerPrefs.HasKey(KeyMarkerJitter))
  77. markerJitterThresholdPixels = PlayerPrefs.GetFloat(KeyMarkerJitter);
  78. if (PlayerPrefs.HasKey(KeyCameraSmooth))
  79. cameraAimEnableSmoothRotation = PlayerPrefs.GetInt(KeyCameraSmooth) != 0;
  80. if (PlayerPrefs.HasKey(KeyCameraLerp))
  81. cameraAimRotationLerpSpeed = PlayerPrefs.GetFloat(KeyCameraLerp);
  82. if (PlayerPrefs.HasKey(KeyCameraJitter))
  83. cameraAimRotationJitterThresholdDeg = PlayerPrefs.GetFloat(KeyCameraJitter);
  84. }
  85. /// <summary>
  86. /// 将当前参数保存到本地(PlayerPrefs),下次启动将自动加载。
  87. /// </summary>
  88. public void SaveToLocal()
  89. {
  90. PlayerPrefs.SetInt(KeyMarkerSmooth, markerEnableSmoothFollow ? 1 : 0);
  91. PlayerPrefs.SetFloat(KeyMarkerLerp, markerPositionLerpSpeed);
  92. PlayerPrefs.SetFloat(KeyMarkerJitter, markerJitterThresholdPixels);
  93. PlayerPrefs.SetInt(KeyCameraSmooth, cameraAimEnableSmoothRotation ? 1 : 0);
  94. PlayerPrefs.SetFloat(KeyCameraLerp, cameraAimRotationLerpSpeed);
  95. PlayerPrefs.SetFloat(KeyCameraJitter, cameraAimRotationJitterThresholdDeg);
  96. PlayerPrefs.Save();
  97. }
  98. /// <summary>
  99. /// 恢复为代码默认值并保存到本地。
  100. /// </summary>
  101. public void ResetToDefaultAndSave()
  102. {
  103. markerEnableSmoothFollow = true;
  104. markerPositionLerpSpeed = 100f;
  105. markerJitterThresholdPixels = 25f;
  106. cameraAimEnableSmoothRotation = true;
  107. cameraAimRotationLerpSpeed = 100f;
  108. cameraAimRotationJitterThresholdDeg = 0.5f;
  109. SaveToLocal();
  110. }
  111. /// <summary> 获取实际控制显示隐藏的 GameObject(panelRoot 为空则为本物体)。 </summary>
  112. private GameObject GetPanelRoot()
  113. {
  114. return panelRoot != null ? panelRoot : gameObject;
  115. }
  116. /// <summary> 显示设置面板。 </summary>
  117. public void ShowPanel()
  118. {
  119. GetPanelRoot().SetActive(true);
  120. }
  121. /// <summary> 隐藏设置面板。 </summary>
  122. public void HidePanel()
  123. {
  124. GetPanelRoot().SetActive(false);
  125. }
  126. /// <summary> 切换设置面板显示状态。 </summary>
  127. public void TogglePanel()
  128. {
  129. GameObject root = GetPanelRoot();
  130. root.SetActive(!root.activeSelf);
  131. }
  132. /// <summary> 当前面板是否处于显示状态。 </summary>
  133. public bool IsPanelVisible()
  134. {
  135. return GetPanelRoot().activeSelf;
  136. }
  137. }
  138. }