Unity抽奖轮盘控制器脚本:结果打印方法重复调用问题
Unity抽奖轮盘多次打印奖品结果的问题修复
问题分析
- 多次打印的原因:大概率是按钮点击监听被重复添加,或者场景中存在多个
PrizeWheelController实例,导致每次点击触发多次协程,最终多次调用DetermineAndDisplayPrize。 - 角度错误的原因:依赖累加的
totalRotation计算最终角度,而Unity的localEulerAngles会自动归一化旋转值,导致totalRotation和轮盘实际显示的角度不一致。
修复方案
1. 避免重复添加按钮监听
将按钮监听的添加/移除逻辑移到OnEnable/OnDisable中,防止重复绑定:
private void OnEnable() { spinButton.onClick.AddListener(SpinWheel); } private void OnDisable() { spinButton.onClick.RemoveListener(SpinWheel); }
同时检查场景中是否有多个挂载了该脚本的物体,确保只保留一个实例。
2. 使用轮盘实际旋转角度判断奖品
放弃累加的totalRotation,直接读取轮盘的localEulerAngles.x作为最终角度,保证和视觉上的角度一致:
private void DetermineAndDisplayPrize() { float finalRotation = NormalizeAngle(insideWheel.localEulerAngles.x); string prize = DeterminePrize(finalRotation); Debug.Log("Final Rotation: " + finalRotation); Debug.Log("Prize won: " + prize); }
3. 优化轮盘停止逻辑
修改协程中的循环条件,让轮盘在速度降为0时立即停止,无需等待剩余的spinDuration:
while (spinTime < spinDuration && spinSpeed > 0f) { spinTime += Time.deltaTime; spinSpeed = Mathf.Max(spinSpeed - decelerationRate * Time.deltaTime, 0f); float rotationStep = spinSpeed * Time.deltaTime; totalRotation += rotationStep; insideWheel.localEulerAngles = new Vector3(totalRotation, 0f, 0f); yield return null; }
完整修复后的脚本
using UnityEngine; using UnityEngine.UI; using System.Collections; public class PrizeWheelController : MonoBehaviour { public Transform insideWheel; public float initialSpinSpeed = 1500.0f; public float minSpinDuration = 2.0f; public float maxSpinDuration = 5.0f; public float decelerationRate = 300.0f; public Button spinButton; private bool isSpinning = false; private bool prizeDetermined = false; private float spinSpeed; private float totalRotation = 0f; private void OnEnable() { spinButton.onClick.AddListener(SpinWheel); } private void OnDisable() { spinButton.onClick.RemoveListener(SpinWheel); } private IEnumerator SpinWheelRoutine() { isSpinning = true; prizeDetermined = false; spinButton.interactable = false; float spinDuration = Random.Range(minSpinDuration, maxSpinDuration); float spinTime = 0f; spinSpeed = initialSpinSpeed; totalRotation = 0f; while (spinTime < spinDuration && spinSpeed > 0f) { spinTime += Time.deltaTime; spinSpeed = Mathf.Max(spinSpeed - decelerationRate * Time.deltaTime, 0f); float rotationStep = spinSpeed * Time.deltaTime; totalRotation += rotationStep; insideWheel.localEulerAngles = new Vector3(totalRotation, 0f, 0f); yield return null; } yield return new WaitForSeconds(5.0f); // 轮盘停止后等待5秒再显示结果 if (!prizeDetermined) { DetermineAndDisplayPrize(); prizeDetermined = true; } isSpinning = false; spinButton.interactable = true; } public void SpinWheel() { if (!isSpinning) { StartCoroutine(SpinWheelRoutine()); } } private void DetermineAndDisplayPrize() { float finalRotation = NormalizeAngle(insideWheel.localEulerAngles.x); string prize = DeterminePrize(finalRotation); Debug.Log("Final Rotation: " + finalRotation); Debug.Log("Prize won: " + prize); } private float NormalizeAngle(float angle) { return (angle % 360 + 360) % 360; } private string DeterminePrize(float angle) { if (angle >= 0 && angle <= 45) return "$0"; if (angle >= 46 && angle <= 90) return "$1000"; if (angle >= 91 && angle <= 135) return "$600"; if (angle >= 136 && angle <= 180) return "$400"; if (angle >= 181 && angle <= 225) return "3x"; if (angle >= 226 && angle <= 270) return "$800"; if (angle >= 271 && angle <= 315) return "$200"; if (angle >= 316 && angle < 360) return "2x"; return "Unknown Prize"; } }
内容的提问来源于stack exchange,提问作者thegu
相关产品推荐
相关产品推荐

