Unity中多次按键触发旋转导致八角形出现非预期角度问题求助
Hey there! Let's fix that wonky octagon rotation issue you're dealing with—you’re totally right about the problem being overlapping coroutines messing up your starting angles. Here’s a clean, robust way to handle it so your octagon always lands on those nice 45° increments, even if you spam the buttons mid-rotation:
Core Issues to Fix
- Multiple coroutines running at once: When you press a button mid-rotation, you’re starting a new coroutine that fights with the old one, leading to weird in-between angles.
- Using real-time rotation as the starting point: Instead of tracking your intended target angle, you’re basing new rotations on whatever the current half-rotated angle is.
The Solution Code
Here’s the revised script that addresses both problems:
using UnityEngine; public class Movement : MonoBehaviour { // Track the currently running rotation coroutine so we can stop it if needed private Coroutine _currentRotationCoroutine; // Maintain our intended target Z angle (always a multiple of 45°) private float _targetZAngle; // Make the rotation step a constant for easy tweaks (e.g., change to 60° for a hexagon) private const float RotationStep = 45f; void Start() { // Initialize our target angle to match the object's starting rotation (rounded to nearest 45°) _targetZAngle = Mathf.Round(transform.eulerAngles.z / RotationStep) * RotationStep; // Ensure the object starts exactly on a valid angle transform.eulerAngles = new Vector3(0, 0, _targetZAngle); } IEnumerator RotateOctagon(float angleDelta, float inTime) { float startAngle = transform.eulerAngles.z; // Update our target angle to the next valid increment _targetZAngle += angleDelta; // Normalize the target angle to stay within 0-360° (avoids negative angles or overflow) _targetZAngle = Mathf.Repeat(_targetZAngle, 360f); float elapsedTime = 0f; while (elapsedTime < inTime) { elapsedTime += Time.deltaTime; // Use a 0-1 t value for smooth interpolation float t = elapsedTime / inTime; // LerpAngle handles 360° wrap-around correctly (e.g., 350° → 10° takes the short path) float currentAngle = Mathf.LerpAngle(startAngle, _targetZAngle, t); transform.eulerAngles = new Vector3(0, 0, currentAngle); yield return null; } // Ensure we end exactly on the target angle (no tiny floating-point errors) transform.eulerAngles = new Vector3(0, 0, _targetZAngle); // Clear the coroutine reference once finished _currentRotationCoroutine = null; } void Update() { if (Input.GetKeyDown(KeyCode.LeftArrow)) { // Stop any ongoing rotation before starting a new one if (_currentRotationCoroutine != null) { StopCoroutine(_currentRotationCoroutine); } _currentRotationCoroutine = StartCoroutine(RotateOctagon(RotationStep, 0.1f)); } if (Input.GetKeyDown(KeyCode.RightArrow)) { if (_currentRotationCoroutine != null) { StopCoroutine(_currentRotationCoroutine); } _currentRotationCoroutine = StartCoroutine(RotateOctagon(-RotationStep, 0.1f)); } if (Input.GetKeyDown(KeyCode.UpArrow)) { if (_currentRotationCoroutine != null) { StopCoroutine(_currentRotationCoroutine); } // 180° is 4x our 45° step _currentRotationCoroutine = StartCoroutine(RotateOctagon(RotationStep * 4, 0.1f)); } } }
How This Works
- Stopping old coroutines: We store a reference to the active rotation coroutine. When a new button is pressed, we stop the old one immediately—no more overlapping rotation logic.
- Target angle tracking:
_targetZAnglealways holds the valid, 45°-aligned angle we want to end up at. Even if we press a button mid-rotation, we just calculate the next valid target from this variable, not the object's current half-rotated angle. - Angle normalization:
Mathf.Repeatkeeps our target angle between 0-360°, so we don't get weird negative angles or values over 360° that can break Euler angle logic. - Smooth, correct interpolation:
Mathf.LerpAngleensures rotations take the shortest path around the circle, which is perfect for polygon rotations.
Example Behavior (Matching Your Request)
If your octagon starts at 0°, you press right (rotating toward -45°), and then press left when it’s at 30°:
- The right-rotation coroutine is stopped immediately.
- We calculate the new target angle:
-45° + 45° = 0°. - A new coroutine starts, smoothly rotating the octagon from its current 30° back to 0°—exactly what you wanted!
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

