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

Unity C#开发中Vector3传变量触发Rigidbody NaN报错问题咨询

问题描述

无C#基础,计划在大学一年级入学前暑假自学Unity,当前正在开发角色行走控制功能:实现角色朝向转向逻辑时,正向移动功能正常,但执行转向操作后,即使把角色旋转角度重置为0,后续控制角色前进时会触发报错:
rigidbody.force assign attempt for 'Fox' is not valid. Input force is {NaN, 0.000000, NaN}.

原有实现代码如下:

using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
//private quaternion rotation;

public class PlayerController : MonoBehaviour
{
    
public Rigidbody rb;
public float moveSpeed = 10f;
public float rotationSpeed = 7f;

public float rotation;


private float xInput;
private float zInput;
private float directionInput;
public GameObject player;
// Start is called before the first frame update
void Start()
{
    
}

// Update is called once per frame
void Update()
{
    ProcessInputs();
    if (Input.GetKeyDown("a"))
    {
        player.transform.Rotate(0f, -(rotationSpeed), 0f, Space.World);
    }
    if (Input.GetKeyDown("d"))
    {
        player.transform.Rotate(0f,  rotationSpeed, 0f, Space.World);
    }
}
private void FixedUpdate()
{
    //Movement
    Move();
}

private void ProcessInputs()
{
    xInput = Input.GetAxis("Horizontal");
    zInput = Input.GetAxis("Vertical");


}

private void Move()
{
    
    //float xMove;
    //float zMove;        

    rotation = player.transform.rotation.y;
    if (rotation == 0)
    {
        float xMove = 0f;
        float zMove = zInput;

        rb.AddForce(new Vector3(xMove, 0f, zMove) * moveSpeed);
    }
    else if (rotation <= 90)
    {
        float zMove = (float)(Math.Sqrt((zInput*zInput) - ((zInput * (1/(Math.Cos(90 - rotation)))) * (zInput * (1/(Math.Cos(90 - rotation))))) ));
        float xMove = (float)(Math.Sqrt((zInput*zInput) - ((zInput * (1/(Math.Sin(90 - rotation)))) * (zInput * (1/(Math.Sin(90 - rotation))))) ));

        rb.AddForce(new Vector3(xMove, 0f, zMove) * moveSpeed);
    }
    
    //Math.Sqrt((zInput*zInput) - ((zInput * (1/(Math.Cos(rotation)))) * (zInput * (1/(Math.Cos(rotation))))) );
    //Math.Sqrt((zInput*zInput) - ((zInput * (1/(Math.Sin(rotation)))) * (zInput * (1/(Math.Sin(rotation))))) );
   //rb.AddForce(new Vector3(0f, 0f, zInput) * moveSpeed);
   //rb.AddForce(new Vector3(xMove, 0f, zMove) * moveSpeed);
}
}

手动编写的旋转后移动分量计算逻辑存在缺陷,导致传入Vector3的分量出现NaN值,需要定位问题原因并获取正确实现方案。

问题根因
  • 角度读取方式错误:player.transform.rotation是四元数(Quaternion)类型,其y分量是四元数的内部计算值,不是直观的0-360度欧拉角,取值范围为-1到1,直接把这个值传入三角函数计算得到的结果完全不符合预期。
  • 数学计算逻辑存在漏洞:手动实现的分量计算公式中,根号下的运算结果极易出现负数——当三角函数计算出的系数大于1时,平方差结果为负,对负数执行开平方运算会直接得到NaN(非数字)值,这就是刚体力赋值报错的直接原因。
  • 转向触发逻辑不合理:使用Input.GetKeyDown()检测转向输入,该API仅在按键按下的第一帧触发,按住按键不会持续触发转向,操作逻辑不符合常规游戏控制习惯。
  • 帧率相关逻辑缺失:转向计算未考虑帧率差,不同设备上转向速度会随帧率波动,帧率越高转向越快。
正确实现方案

不需要手动编写三角函数计算移动分量,Unity原生提供了方向转换API,可以直接将角色本地空间的移动输入转换为世界空间的移动方向,完全规避手动计算带来的错误,代码逻辑更简洁稳定。

修正后完整代码如下:

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public Rigidbody rb;
    public float moveSpeed = 10f;
    public float rotationSpeed = 7f;
    
    private float xInput;
    private float zInput;

    void Update()
    {
        ProcessInputs();
        // 按住A/D时持续转向,改用GetKey持续检测输入,乘以deltaTime保证不同帧率下转向速度一致
        if (Input.GetKey(KeyCode.A))
        {
            transform.Rotate(0f, -rotationSpeed * Time.deltaTime, 0f, Space.World);
        }
        if (Input.GetKey(KeyCode.D))
        {
            transform.Rotate(0f, rotationSpeed * Time.deltaTime, 0f, Space.World);
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    private void ProcessInputs()
    {
        xInput = Input.GetAxis("Horizontal");
        zInput = Input.GetAxis("Vertical");
    }

    private void Move()
    {
        // 本地移动方向:x轴对应左右,z轴对应前后,归一化保证斜向移动速度和正向一致
        Vector3 localMoveDir = new Vector3(xInput, 0f, zInput).normalized;
        // 将本地方向转换为世界空间方向,自动适配角色当前朝向,无需手动计算三角函数
        Vector3 worldMoveDir = transform.TransformDirection(localMoveDir);
        rb.AddForce(worldMoveDir * moveSpeed);
    }
}

额外优化提示

  • 给Rigidbody组件设置合适的Drag(阻力)值,避免角色移动后一直滑动无法停下。
  • 如果不需要完全手动控制转向,可以直接用Quaternion.LookRotation配合移动输入实现更顺滑的自动朝向,不需要单独写A/D转向逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:12:22