CubeController.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. using UnityEngine;
  2. public class CubeController : MonoBehaviour
  3. {
  4. [SerializeField] private bool isDebug = false;
  5. [Header("基础旋转设置")]
  6. [SerializeField] private float baseRotationSpeed = 30f;
  7. [SerializeField] private float directionChangeInterval = 3f;
  8. [Header("随机范围")]
  9. [SerializeField] private Vector3 minRotationSpeed = new Vector3(-50, -50, -50);
  10. [SerializeField] private Vector3 maxRotationSpeed = new Vector3(50, 50, 50);
  11. [Header("增强效果设置")]
  12. [SerializeField] private bool useEaseInOut = true;
  13. [SerializeField] private AnimationCurve easeCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
  14. [SerializeField] private bool useRandomCurve = false;
  15. [SerializeField] private AnimationCurve[] randomCurves;
  16. private Vector3 targetRotationSpeed;
  17. private Vector3 currentRotationSpeed;
  18. private Vector3 previousRotationSpeed;
  19. private float timeSinceLastDirectionChange;
  20. private AnimationCurve currentCurve;
  21. // ==================================================
  22. private void Start() => Init();
  23. private void Update()
  24. {
  25. // 更新时间
  26. timeSinceLastDirectionChange += Time.deltaTime;
  27. // 计算插值进度(0到1)
  28. float progress = Mathf.Clamp01(timeSinceLastDirectionChange / directionChangeInterval);
  29. // 应用缓动插值
  30. if (useEaseInOut && currentCurve != null)
  31. {
  32. float easedProgress = currentCurve.Evaluate(progress);
  33. currentRotationSpeed = Vector3.Lerp(previousRotationSpeed, targetRotationSpeed, easedProgress);
  34. }
  35. else
  36. {
  37. // 线性插值
  38. currentRotationSpeed = Vector3.Lerp(previousRotationSpeed, targetRotationSpeed, progress);
  39. }
  40. // 应用旋转
  41. transform.Rotate(currentRotationSpeed * Time.deltaTime);
  42. // 定期改变旋转方向和曲线
  43. if (timeSinceLastDirectionChange >= directionChangeInterval)
  44. {
  45. GenerateNewRotationTarget();
  46. if (useRandomCurve)
  47. {
  48. SelectRandomCurve();
  49. }
  50. timeSinceLastDirectionChange = 0f;
  51. }
  52. }
  53. private void OnGUI() => DEBUG_ShowInfo();
  54. private void OnDrawGizmos() => DEBUG_DrawGizmo();
  55. private void OnDestroy() => UnInit();
  56. // ==================================================
  57. private void Init()
  58. {
  59. // 初始化随机曲线数组(如果没有手动赋值)
  60. if (randomCurves == null || randomCurves.Length == 0) { SetDefaultCurves(); }
  61. // 初始化旋转速度
  62. GenerateNewRotationTarget();
  63. currentRotationSpeed = targetRotationSpeed;
  64. previousRotationSpeed = currentRotationSpeed;
  65. // 选择初始曲线
  66. SelectRandomCurve();
  67. // Wireframe
  68. meshFilter = GetComponent<MeshFilter>();
  69. CreateLineMaterial();
  70. // 隐藏原来的网格渲染器
  71. MeshRenderer originalRenderer = GetComponent<MeshRenderer>();
  72. if (originalRenderer != null)
  73. {
  74. originalRenderer.enabled = false;
  75. }
  76. }
  77. private void UnInit()
  78. {
  79. if (lineMaterial != null) { DestroyImmediate(lineMaterial); }
  80. }
  81. // ==================================================
  82. /// <summary>
  83. /// 设置默认曲线
  84. /// </summary>
  85. private void SetDefaultCurves()
  86. {
  87. // 创建一组默认的动画曲线
  88. randomCurves = new AnimationCurve[6];
  89. // 1. 标准缓入缓出
  90. randomCurves[0] = AnimationCurve.EaseInOut(0, 0, 1, 1);
  91. // 2. 快速开始慢速结束
  92. randomCurves[1] = new AnimationCurve(
  93. new Keyframe(0, 0),
  94. new Keyframe(0.2f, 0.8f),
  95. new Keyframe(1, 1)
  96. );
  97. // 3. 慢速开始快速结束
  98. randomCurves[2] = new AnimationCurve(
  99. new Keyframe(0, 0),
  100. new Keyframe(0.8f, 0.2f),
  101. new Keyframe(1, 1)
  102. );
  103. // 4. 弹性效果
  104. randomCurves[3] = new AnimationCurve(
  105. new Keyframe(0, 0),
  106. new Keyframe(0.3f, 1.1f),
  107. new Keyframe(0.6f, 0.9f),
  108. new Keyframe(1, 1)
  109. );
  110. // 5. 阶梯效果
  111. randomCurves[4] = new AnimationCurve(
  112. new Keyframe(0, 0),
  113. new Keyframe(0.3f, 0.3f),
  114. new Keyframe(0.31f, 0.7f),
  115. new Keyframe(1, 1)
  116. );
  117. // 6. 平滑线性
  118. randomCurves[5] = new AnimationCurve(
  119. new Keyframe(0, 0),
  120. new Keyframe(1, 1)
  121. );
  122. }
  123. private void GenerateNewRotationTarget()
  124. {
  125. // 保存当前速度作为插值起点
  126. previousRotationSpeed = currentRotationSpeed;
  127. // 生成新的随机旋转速度
  128. targetRotationSpeed = new Vector3(
  129. Random.Range(minRotationSpeed.x, maxRotationSpeed.x),
  130. Random.Range(minRotationSpeed.y, maxRotationSpeed.y),
  131. Random.Range(minRotationSpeed.z, maxRotationSpeed.z)
  132. );
  133. }
  134. private void SelectRandomCurve()
  135. {
  136. if (randomCurves != null && randomCurves.Length > 0)
  137. {
  138. int randomIndex = Random.Range(0, randomCurves.Length);
  139. currentCurve = randomCurves[randomIndex];
  140. }
  141. else
  142. {
  143. // 回退到默认缓动曲线
  144. currentCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
  145. }
  146. }
  147. // 编辑器方法:重新生成目标
  148. [ContextMenu("重新生成旋转目标")]
  149. public void RegenerateTarget()
  150. {
  151. GenerateNewRotationTarget();
  152. if (useRandomCurve)
  153. {
  154. SelectRandomCurve();
  155. }
  156. timeSinceLastDirectionChange = 0f;
  157. }
  158. // 编辑器方法:设置基础速度
  159. [ContextMenu("应用基础速度")]
  160. public void ApplyBaseSpeed()
  161. {
  162. minRotationSpeed = new Vector3(-baseRotationSpeed, -baseRotationSpeed, -baseRotationSpeed);
  163. maxRotationSpeed = new Vector3(baseRotationSpeed, baseRotationSpeed, baseRotationSpeed);
  164. RegenerateTarget();
  165. }
  166. // ==================================================
  167. #region Wireframe
  168. [Header("线框设置")]
  169. [SerializeField] private Color wireframeColor = Color.cyan;
  170. [SerializeField] private float lineWidth = 0.02f;
  171. private MeshFilter meshFilter;
  172. private Material lineMaterial;
  173. private void CreateLineMaterial()
  174. {
  175. // 创建用于绘制线的材质
  176. lineMaterial = new Material(Shader.Find("Hidden/Internal-Colored"));
  177. lineMaterial.hideFlags = HideFlags.HideAndDontSave;
  178. }
  179. private void OnRenderObject()
  180. {
  181. if (meshFilter == null || meshFilter.sharedMesh == null)
  182. return;
  183. // 设置材质
  184. lineMaterial.SetPass(0);
  185. GL.PushMatrix();
  186. GL.MultMatrix(transform.localToWorldMatrix);
  187. GL.Begin(GL.LINES);
  188. GL.Color(wireframeColor);
  189. Mesh mesh = meshFilter.sharedMesh;
  190. Vector3[] vertices = mesh.vertices;
  191. int[] triangles = mesh.triangles;
  192. // 绘制所有三角形的边
  193. for (int i = 0; i < triangles.Length; i += 3)
  194. {
  195. DrawTriangleLine(vertices[triangles[i]], vertices[triangles[i + 1]], vertices[triangles[i + 2]]);
  196. }
  197. GL.End();
  198. GL.PopMatrix();
  199. }
  200. private void DrawTriangleLine(Vector3 a, Vector3 b, Vector3 c)
  201. {
  202. GL.Vertex(a);
  203. GL.Vertex(b);
  204. GL.Vertex(b);
  205. GL.Vertex(c);
  206. GL.Vertex(c);
  207. GL.Vertex(a);
  208. }
  209. #endregion
  210. // ==================================================
  211. #region DEBUG
  212. // 在Inspector中显示调试信息
  213. private void DEBUG_ShowInfo()
  214. {
  215. if (!isDebug) { return; }
  216. if (Application.isPlaying)
  217. {
  218. GUILayout.BeginArea(new Rect(10, 10, 300, 150));
  219. GUILayout.Label($"当前旋转速度: {currentRotationSpeed}");
  220. GUILayout.Label($"目标旋转速度: {targetRotationSpeed}");
  221. GUILayout.Label($"时间进度: {timeSinceLastDirectionChange:F1}/{directionChangeInterval}");
  222. GUILayout.Label($"进度百分比: {timeSinceLastDirectionChange / directionChangeInterval * 100:F1}%");
  223. GUILayout.EndArea();
  224. }
  225. }
  226. // 可视化调试(在Scene视图中显示)
  227. private void DEBUG_DrawGizmo()
  228. {
  229. if (!isDebug) { return; }
  230. if (Application.isPlaying)
  231. {
  232. // 绘制旋转轴指示器
  233. Gizmos.color = Color.red;
  234. Vector3 direction = currentRotationSpeed.normalized;
  235. Gizmos.DrawRay(transform.position, direction * 2f);
  236. // 绘制速度大小的球体
  237. Gizmos.color = Color.blue;
  238. float speed = currentRotationSpeed.magnitude / 100f;
  239. Gizmos.DrawWireSphere(transform.position, speed);
  240. }
  241. }
  242. #endregion
  243. }