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

Unity C#重力计算函数返回NaN值的原因排查求助

Unity引力计算脚本NaN错误排查思路

问题场景

使用以下脚本计算天体间引力时,场景中两个物体均触发Input force is { NaN, NaN, NaN }错误,已确认无明显除零情况,需要排查原因。

脚本代码

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

public class Gravity : MonoBehaviour
{
    public const float gravity = 10;
    public float mass = 10f;
    public bool active = true;
    public Rigidbody rigidbody;
    public Transform transform;
    GameObject[] otherObjs;
    Gravity[] otherGravities;

    void Start () {
        rigidbody = gameObject.GetComponent<Rigidbody>();
        transform = gameObject.transform;
        otherObjs = GameObject.FindGameObjectsWithTag("Body");
        otherGravities = new Gravity[otherObjs.Length];
        for (int i = 0; i < otherObjs.Length; i++)
        {
            otherGravities[i] = otherObjs[i].GetComponent<Gravity>();
        }
    }

    void FixedUpdate () {
        rigidbody.AddForce(CalculateGravity());
    }

    Vector3 CalculateGravity () {
        Vector3 finalGravity = new Vector3(0, 0, 0);
        foreach (Gravity current in otherGravities) {
            float distance = Vector3.Distance(transform.position, current.transform.position);
            Vector3 unNormalDirection = transform.position - current.transform.position;
            Vector3 direction = unNormalDirection.normalized;
            Vector3 gravitationalPull = ((mass * current.mass) / (distance * distance)) * direction;
            finalGravity += gravitationalPull;
        }
        return finalGravity;
    }
}

错误信息

rigidbody.force assign attempt for 'Sun' is not valid. Input force is { NaN, NaN, NaN }.
UnityEngine.Rigidbody:AddForce (UnityEngine.Vector3)
Gravity:FixedUpdate () (at Assets/Scripts/Gravity.cs:27)

排查思路

  • 排除自身对象遍历:GameObject.FindGameObjectsWithTag("Body")会将挂载该脚本的自身(如果标签为Body)也加入数组。当遍历到自身时,Vector3.Distance返回0,此时对零向量执行normalized操作会直接得到(NaN, NaN, NaN),最终导致引力计算结果为NaN。需在遍历前添加判断跳过自身:

    foreach (Gravity current in otherGravities) {
        if (current == this) continue; // 跳过自身
        // 剩余计算逻辑
    }
    
  • 校验数组元素有效性:若场景中存在标签为Body但未挂载Gravity脚本的物体,otherGravities数组会包含null元素。遍历到null时访问current.transform会引发空引用,虽不一定直接导致NaN,但会破坏计算逻辑。建议在Start方法中筛选有效组件,改用List存储:

    List<Gravity> validGravities = new List<Gravity>();
    foreach (var obj in otherObjs)
    {
        Gravity comp = obj.GetComponent<Gravity>();
        if (comp != null && comp != this)
        {
            validGravities.Add(comp);
        }
    }
    otherGravities = validGravities.ToArray();
    
  • 检查质量与距离的合法性:

    1. 确认所有物体的mass值未被设置为NaN或无穷大,可在CalculateGravity中添加日志输出mass和current.mass的值验证。
    2. 即使排除了自身,若两物体位置完全重合(距离为0),零向量归一化仍会产生NaN。需添加距离阈值判断,跳过极近距离的计算:
      float distance = Vector3.Distance(transform.position, current.transform.position);
      if (distance < 0.001f) continue; // 跳过极近距离,避免异常
      
  • 修正引力方向逻辑:当前代码中unNormalDirection = transform.position - current.transform.position得到的是远离对方的方向,与引力“相互吸引”的逻辑相反。虽不会导致NaN,但会引发物理行为异常,建议修正为:

    Vector3 unNormalDirection = current.transform.position - transform.position;
    
  • 确认常量gravity的使用:脚本中定义了gravity常量但未参与计算,实际引力公式缺少引力系数,需补全:

    Vector3 gravitationalPull = (gravity * mass * current.mass) / (distance * distance) * direction;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:15:43