using UnityEngine; using TMPro; using UnityEngine.InputSystem; public class IncenseController : MonoBehaviour { [Header("References")] public Transform incensePivot; public Transform incenseStick; public ParticleSystem smokeParticles; [Header("Light (URP only)")] public UnityEngine.Rendering.Universal.Light2D glowLight; // URP 版本 // 如果用 Built-in,用這個: // public SpriteRenderer glowSprite; [Header("Falling Settings")] public float startHeight = 3f; public float targetHeight = -2.5f; public float fallDuration = 30f; [Header("Struggle Settings")] public float windForceMin = 20f; public float windForceMax = 60f; public float windChangeSpeed = 5f; public float playerControlStrength = 100f; [Header("Visual Settings")] public float maxGlowIntensity = 3f; [Header("UI")] public TextMeshProUGUI messageText; public TextMeshProUGUI angleText; public TextMeshProUGUI timerText; [Header("Audio (Optional)")] public AudioSource backgroundMusic; private float currentAngle = 90f; private float targetWindAngle = 90f; private float lastAngleValue = 90f; private float stability = 1f; private float fallTimer = 0f; private bool hasLanded = false; private float finalSincerity = 0f; void Start() { if (incensePivot != null) { Vector3 pos = incensePivot.position; pos.y = startHeight; incensePivot.position = pos; } currentAngle = Random.Range(60f, 120f); targetWindAngle = currentAngle; if (glowLight != null) { glowLight.intensity = 1f; } Debug.Log($"遊戲開始!時長: {fallDuration} 秒"); } void Update() { // 按 R 重新開始 if (Keyboard.current.rKey.wasPressedThisFrame) { UnityEngine.SceneManagement.SceneManager.LoadScene( UnityEngine.SceneManagement.SceneManager.GetActiveScene().name ); } if (!hasLanded) { UpdateFalling(); HandleInput(); CalculateStability(); UpdateVisuals(); UpdateUI(); } else { DisplayFinalResult(); } } void UpdateFalling() { fallTimer += Time.deltaTime; if (fallTimer >= fallDuration) { hasLanded = true; fallTimer = fallDuration; float angleDeviation = Mathf.Abs(currentAngle - 90f); finalSincerity = 1f - (angleDeviation / 30f); finalSincerity = Mathf.Clamp01(finalSincerity); Debug.Log($"角度: {currentAngle:F1}°, 誠意度: {finalSincerity * 100:F0}%"); return; } // 計算下降 float t = fallTimer / fallDuration; float currentHeight = Mathf.Lerp(startHeight, targetHeight, t); if (incensePivot != null) { Vector3 pos = incensePivot.position; pos.y = currentHeight; incensePivot.position = pos; } // 風力計算 float windMultiplier = 1f - (t * 0.5f); float currentWindMax = windForceMax * windMultiplier; float windChange = Random.Range(-currentWindMax, currentWindMax) * Time.deltaTime; targetWindAngle += windChange; targetWindAngle = Mathf.Clamp(targetWindAngle, 30f, 150f); currentAngle = Mathf.Lerp(currentAngle, targetWindAngle, windChangeSpeed * Time.deltaTime); currentAngle = Mathf.Clamp(currentAngle, 30f, 150f); // 2D 旋轉(Z 軸) if (incensePivot != null) { incensePivot.rotation = Quaternion.Euler(0, 0, currentAngle - 90f); } } void HandleInput() { if (Mouse.current.leftButton.isPressed) { Vector2 mouseDelta = Mouse.current.delta.ReadValue(); float mouseX = mouseDelta.x; currentAngle += mouseX * playerControlStrength * Time.deltaTime * 0.1f; // 可能需要調整係數 currentAngle = Mathf.Clamp(currentAngle, 30f, 150f); } } void CalculateStability() { float angleChange = Mathf.Abs(currentAngle - lastAngleValue); stability = Mathf.Clamp01(1f - angleChange / 10f); lastAngleValue = currentAngle; } void UpdateVisuals() { float angleDeviation = Mathf.Abs(currentAngle - 90f); float sincerity = 1f - (angleDeviation / 30f); sincerity = Mathf.Clamp01(sincerity); // 更新光線(URP) if (glowLight != null) { Color lightColor = Color.Lerp(Color.red, Color.yellow, sincerity); glowLight.color = lightColor; glowLight.intensity = Mathf.Lerp(0.5f, maxGlowIntensity, sincerity); } // 更新煙霧 if (smokeParticles != null) { var emission = smokeParticles.emission; emission.rateOverTime = Mathf.Lerp(5f, 30f, 1f - stability); } // 更新音樂音量(如果有) if (backgroundMusic != null) { backgroundMusic.volume = Mathf.Lerp(0.2f, 0.8f, sincerity); } } void UpdateUI() { // 角度顯示 if (angleText != null) { angleText.text = $"角度: {currentAngle:F0}°"; } // 倒數計時 if (timerText != null) { float remaining = fallDuration - fallTimer; timerText.text = $"倒計時{remaining:F1}秒"; if (remaining <= 5f) { float flicker = Mathf.Sin(Time.time * 10f) * 0.5f + 0.5f; timerText.color = Color.Lerp(Color.red, Color.yellow, flicker); timerText.fontSize = 40 + Mathf.Sin(Time.time * 8f) * 5f; } else if (remaining <= 10f) { timerText.color = Color.yellow; timerText.fontSize = 40; } else { timerText.color = Color.white; timerText.fontSize = 40; } } // 誠意訊息 if (messageText != null) { float angleDeviation = Mathf.Abs(currentAngle - 90f); float sincerity = 1f - (angleDeviation / 30f); sincerity = Mathf.Clamp01(sincerity); string message = ""; Color messageColor = Color.white; if (sincerity >= 0.95f) { message = "😊 完美!最高誠意!"; messageColor = new Color(0.2f, 1f, 0.2f); } else if (sincerity >= 0.75f) { message = "不錯!還算虔誠"; messageColor = new Color(0.5f, 1f, 0.5f); } else if (sincerity >= 0.60f) { message = "普通~可以更好"; messageColor = new Color(1f, 1f, 0.3f); } else if (sincerity >= 0.40f) { message = "誠意不足...需努力"; messageColor = new Color(1f, 0.6f, 0.2f); } else { message = "太歪了!需要反省"; messageColor = new Color(1f, 0.2f, 0.2f); } messageText.text = message; messageText.color = messageColor; } } void DisplayFinalResult() { // 光線閃爍 if (glowLight != null) { float flicker = 0.8f + Mathf.Sin(Time.time * 3f) * 0.2f; glowLight.intensity = maxGlowIntensity * finalSincerity * flicker; } // UI 顯示 if (timerText != null) { timerText.text = "時間到!"; timerText.color = Color.yellow; } if (angleText != null) { angleText.text = $"最終角度: {currentAngle:F0}°"; } if (messageText != null) { if (finalSincerity >= 0.95f) { messageText.text = "完美插香!最高誠意!"; messageText.color = Color.yellow; } else if (finalSincerity >= 0.75f) { messageText.text = $"不錯!誠意度: {finalSincerity * 100:F0}%"; messageText.color = new Color(0.5f, 1f, 0.5f); } else { messageText.text = $"可惜!誠意度: {finalSincerity * 100:F0}%"; messageText.color = new Color(1f, 0.6f, 0.2f); } } } }