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

Unity2D集成Netcode后实例化RigidBody2D动量异常求助

Unity2D Netcode 移动异常问题修复

问题描述

Unity2D新手使用Netcode for GameObjects实现多人联机后,预制体移动异常:按住A键时动量始终为0,按住D键时动量固定在1.5,跳跃功能正常,已用Debug.Log排查但未定位根源。注:speed参数由预制体内的Stats.cs脚本设置。

错误代码

using Unity.Netcode;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.UI;

public class PlayerMovement : NetworkBehaviour
{
    //Only To Monitor Motion
    
    public float momentum;
    public float horizontal;
    public float vertical;
    //Character Stats
    public float speed;
    public float jumpingPower;
    private bool canJump;
    private int dbJump;
    private float baseSpeed;
    public bool isGrounded;
    


    public Rigidbody2D rb;
    [SerializeField] private Transform groundCheck1;
    [SerializeField] private Transform groundCheck2;
    [SerializeField] private Transform groundCheck3;
    [SerializeField] private LayerMask groundLayer;

    public bool isFacingRight = true;
    

    //KB Check 
    private Knockback kb;


    private void Start()
    {
        kb = GetComponent<Knockback>();
        dbJump = 0;
        canJump = true;
        horizontal = 0;
        baseSpeed = speed;
        isGrounded = true;
    }
    void Update()
    {
        if (!IsOwner) return;


        if (rb.linearVelocityY <= -61 && !Input.GetKey(KeyCode.S))
        {
            rb.linearVelocityY += (rb.linearVelocityY + 60) * -1;
        }
        if (dbJump == 0)
        {
            canJump = false;
        }
        if (IsGrounded())
        {
            canJump = true;
            dbJump = 1;
        }

        if (IsOwner)
        {
            horizontal = Input.GetAxisRaw("Horizontal");
            
            
            if (horizontal == 1 && momentum <= speed)
            {
                Debug.Log("horizontal 1 detected");
                if (horizontal == 1 && momentum <= 0)
                {
                    momentum += 1.5f;
                    Debug.Log("Momemtum ++");
                }
                momentum += baseSpeed * 0.05f;
                Debug.Log("Momemtum +");
                if (momentum > speed)
                {
                    momentum = speed;
                }
            }
            else if (horizontal == -1 && momentum >= (speed * -1))
            {
                Debug.Log("horizontal -1 detected");
                if (horizontal == 1 && momentum >= 0)
                {
                    momentum -= 1.5f;
                    Debug.Log("Momemtum --");
                }
                momentum -= baseSpeed * 0.05f;
                Debug.Log("Momemtum -");
                if (momentum < speed * -1)
                {
                    momentum = speed*-1;
                }
            }
            else if (horizontal == 0)
            {
                Debug.Log("horizontal 0");
                if (momentum > 0.4f)
                {
                    momentum -= 0.75f;
                }
                else if (momentum < -0.4f)
                {
                    momentum += 0.75f;
                }
                else if (!Input.GetKeyDown(KeyCode.D)&& !Input.GetKeyDown(KeyCode.A))
                {
                    momentum = 0;
                }
            }

            if ((Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.Space)) && canJump)
            {
                rb.linearVelocity = new Vector2(rb.linearVelocity.x, jumpingPower);
                dbJump -= 1;
            }

            if ((Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.Space)) && rb.linearVelocity.y > 0f)
            {
                rb.linearVelocity = new Vector2(rb.linearVelocity.x, rb.linearVelocity.y * 0.5f);
            }

            
                Flip();
            
            
        }
        if (vertical != 0)
        {
            isGrounded = false;
        }
        else
        {
            isGrounded = true;
        }

    }

    private void FixedUpdate()
    {

        vertical = rb.linearVelocity.y;
        rb.linearVelocity = new Vector2(momentum, rb.linearVelocity.y);
        if (Input.GetKey(KeyCode.S) && vertical > -117.70f)
        {
            rb.linearVelocity = new Vector2(momentum, rb.linearVelocity.y - 5);
        }
        else if (Input.GetKey(KeyCode.S) && vertical < -117.70f)
        {
            rb.linearVelocity = new Vector2(momentum, -117.7f);
        }
        if ((Input.GetKeyUp(KeyCode.S) && rb.linearVelocity.y < -60))
        {
            rb.linearVelocity = new Vector2(momentum, -60);
        }
    }

    private bool IsGrounded()
    {
        return Physics2D.OverlapCircle(groundCheck1.position, 0.2f, groundLayer)|| Physics2D.OverlapCircle(groundCheck2.position, 0.2f, groundLayer) || Physics2D.OverlapCircle(groundCheck3.position, 0.2f, groundLayer);
    }

    public void Flip()
    {
            if (isFacingRight && horizontal < 0f || !isFacingRight && horizontal > 0f)
            {
                isFacingRight = !isFacingRight;
                Vector3 localScale = transform.localScale;
                localScale.x *= -1f;
                transform.localScale = localScale;
            }
    }
}

问题根源及修复方案

1. 左移分支逻辑错误

左移代码块内的判断条件写错,horizontal == 1永远无法成立(此时horizontal为-1),导致左移时无初始动量变化,修正如下:

else if (horizontal == -1 && momentum >= (speed * -1))
{
    Debug.Log("horizontal -1 detected");
    // 修正匹配左移的判断条件
    if (horizontal == -1 && momentum >= 0)
    {
        momentum -= 1.5f;
        Debug.Log("Momemtum --");
    }
    momentum -= baseSpeed * 0.05f;
    Debug.Log("Momemtum -");
    if (momentum < speed * -1)
    {
        momentum = speed*-1;
    }
}

2. 基础速度未正确赋值

Start()中baseSpeed = speed;依赖Stats.cs对speed的赋值,需确保Stats.cs在Awake/Start阶段主动给PlayerMovement的speed赋值,例如:

// 在Stats.cs的Awake或Start中添加
void Awake()
{
    GetComponent<PlayerMovement>().speed = 你的目标速度值;
}

若baseSpeed为0,会导致按住D键时动量仅能增加初始的1.5,后续无法提升;左移时动量无变化,始终为0。

3. 停止逻辑优化

原代码中horizontal == 0分支的按键判断逻辑错误(GetKeyDown仅检测瞬间按下),简化为直接归0:

else if (horizontal == 0)
{
    Debug.Log("horizontal 0");
    if (momentum > 0.4f)
    {
        momentum -= 0.75f;
    }
    else if (momentum < -0.4f)
    {
        momentum += 0.75f;
    }
    else
    {
        momentum = 0;
    }
}

4. 移除冗余权限判断

Update开头已有if (!IsOwner) return;,后续无需重复判断if (IsOwner),避免逻辑混乱。

验证步骤

  1. 修正上述代码后,运行游戏测试左右移动
  2. 用Debug.Log输出baseSpeed和momentum的值,确认速度参数正确赋值
  3. 检查Netcode的玩家对象Owner权限是否正确分配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 13:57:32