You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity摆锤Y轴旋转失效求助:条件判断未触发

问题分析与解决方案

核心问题点

  • 浮点数精度导致判断失效:angle == limit永远无法触发,因为Mathf.Sin返回连续变化值,Time.time是逐帧递增的浮点数,几乎不可能让Sin(...)刚好等于1,自然angle也不会精确等于limit。
  • 旋转逻辑错误:transform.Rotate(0, 180 * Time.time, 0)是错误写法,Time.time是游戏运行总时长,这会让旋转角度随时间无限增大,而非固定旋转180度。
  • 旋转被强制覆盖:每次Update都通过Quaternion.Euler(0, 0, angle)设置局部旋转,会把Y轴旋转强制重置为0,导致之前的Y轴旋转操作被立刻抹除。

修改后的代码

using UnityEngine;

public class PendulumScript : MonoBehaviour
{
    [SerializeField] public float speed = 1.5f;
    public float limit = 75f;
    public bool randomStart = false;
    private float randomOffset = 0;
    private bool limitReached = false;
    private Quaternion originalRotation;
    private float previousAngle; // 记录上一帧摆角,用于判断是否到达峰值

    void Awake()
    {
        if (randomStart)
        {
            randomOffset = Random.Range(0f, Mathf.PI * 2f); // 用0-2π范围随机初始相位,符合正弦周期特性
        }

        originalRotation = transform.localRotation;
        previousAngle = limit * Mathf.Sin(randomOffset); // 初始化上一帧角度
    }

    void Update()
    {
        // 计算当前摆角,将speed放入Sin参数中控制摆动速度
        float currentAngle = limit * Mathf.Sin(Time.time * speed + randomOffset);
        // 仅修改Z轴摆动角度,保留X、Y轴现有旋转值
        transform.localRotation = Quaternion.Euler(transform.localEulerAngles.x, 
                                                   transform.localEulerAngles.y, 
                                                   currentAngle);

        // 判断到达正极限:角度接近limit,且上一帧角度小于当前角度(确保仅在峰值触发一次)
        if (!limitReached && Mathf.Abs(currentAngle - limit) < 0.1f && previousAngle < currentAngle)
        {
            // 直接设置Y轴旋转值,确保固定旋转180度
            transform.localEulerAngles = new Vector3(transform.localEulerAngles.x,
                                                    transform.localEulerAngles.y + 180f,
                                                    transform.localEulerAngles.z);
            limitReached = true;
        }
        // 判断到达负极限:角度接近-limit,且上一帧角度大于当前角度
        else if (limitReached && Mathf.Abs(currentAngle + limit) < 0.1f && previousAngle > currentAngle)
        {
            // 重置为初始旋转状态
            transform.localRotation = originalRotation;
            limitReached = false;
        }

        // 更新上一帧角度记录
        previousAngle = currentAngle;
    }
}

关键修改说明

  1. 替换精确相等判断:用Mathf.Abs(currentAngle - limit) < 0.1f判断角度是否接近极限,同时通过前后帧角度的大小变化,确保只在到达峰值的那一帧触发逻辑,避免重复触发导致闪烁。
  2. 修复旋转逻辑:直接通过localEulerAngles设置Y轴旋转值,确保旋转180度是固定操作,不会随时间产生异常变化。
  3. 避免旋转覆盖:设置局部旋转时保留当前X、Y轴的旋转值,仅修改Z轴,保证Y轴的旋转不会被重置。
  4. 优化随机初始相位:将随机值范围调整为0到2π,符合正弦函数的周期特性,初始摆动位置更合理。

内容的提问来源于stack exchange,提问作者Prince K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 09:51:16