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

Unity Start()调用ApplyRadius改绕转半径报position赋值异常

问题成因

报错直接原因是Transform.position赋值时Y轴传入了NaN值,具体触发逻辑如下:

  • 首要触发点是除零运算:delay字段未手动赋值时默认值为0。第一帧Update执行流程为:Start()调用ApplyRadius完成半径设置后进入Update,time累加首帧时间增量(约0.02s),此时time > delay(0.02>0)条件成立,逻辑块会将time重置为0,后续执行高度Lerp计算时,插值系数为time / delay = 0 / 0 = NaN,Mathf.Lerp接收NaN系数后直接返回NaN,赋值给Y轴触发报错。运行时修改半径时已过首帧初始化阶段,若此时你已设置非0的delay值就不会触发该异常。
  • 潜在触发点:若脚本挂载物体初始位置与objToRotateAround位置完全重合,ApplyRadius中计算两点方向向量时会得到零向量,零向量调用normalized属性会返回各分量为NaN的向量,直接导致position赋值携带NaN,污染后续所有位置计算逻辑。
  • 初始值隐患:prevHeight、height为私有float字段,默认初始值为0,首次插值前未初始化高度值,会出现首帧高度从0跳变的问题。
修复方案

所有原有变量、API、核心逻辑保持不变,仅添加异常防护和初始化逻辑,修改点如下:

  • Start阶段提前初始化高度字段,避免首帧跳变
  • ApplyRadius中添加空引用、零向量校验,避免归一化得到NaN
  • 插值计算前添加除零保护,delay为0时直接取目标高度
  • 给配置类字段加合理默认值,避免默认0导致的逻辑异常

修复后完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotateAroundPoint : MonoBehaviour
{
    public GameObject objToRotateAround;
    [Header("The axis by which it will rotate around")]
    public Vector3 axis = Vector3.up;
    [Header("Angle covered per Second")]
    public float anglePerSecond = 30f;
    [SerializeField] private float radius = 5f;
    public float upperLimit = 5f;
    public float lowerLimit = 1f;
    public float delay = 2f;

    private float height;
    private float prevHeight;
    private float time;
    private float lastRadius;

    private void Start()
    {
        // 初始化高度值,避免首帧跳变
        prevHeight = transform.position.y;
        height = Random.Range(lowerLimit, upperLimit);
        time = 0;
        
        ApplyRadius();
    }

    void Update()
    {
        // Check if the radius was changed
        if (!Mathf.Approximately(radius, lastRadius))
        {
            ApplyRadius();
        }

        time += Time.deltaTime;
        if (time > delay)
        {
            prevHeight = height;
            height = Random.Range(lowerLimit, upperLimit);

            time = 0;
        }

        // Rotate with a frame-rate independent angle per second
        transform.RotateAround(objToRotateAround.transform.position, axis, anglePerSecond * Time.deltaTime);

        // For the Lerp you want a factor between 0 and 1
        // not between 0 and delay
        // => divide by delay gives you a factor between 0 and 1   
        float lerpFactor = delay <= 0 ? 1f : time / delay;
        transform.position = new Vector3(transform.position.x, Mathf.Lerp(prevHeight, height, lerpFactor), transform.position.z);
    }

    private void ApplyRadius()
    {
        if (objToRotateAround == null) return;
        
        // Get the direction vector from the pivot to your current object position
        Vector3 offset = transform.position - objToRotateAround.transform.position;
        // 零向量校验,避免归一化得到NaN
        if (offset == Vector3.zero)
        {
            offset = objToRotateAround.transform.forward;
        }
        var direction = offset.normalized;

        // set your object in the same direction but at distance of radius
        transform.position = objToRotateAround.transform.position + direction * radius;

        lastRadius = radius;
    }

 }

修复后首帧初始化不会再触发NaN报错,运行时修改半径的原有逻辑完全保留,同时兼容delay被设为0的极端配置场景。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:21:28