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

Unity 2D/C#开发中护盾抛射物不从玩家位置生成且移动异常求助

问题背景

我正在开发一款2D上帝视角无尽竞技场战斗游戏,设定中护盾同时作为玩家的进攻手段:按住鼠标左键时,护盾会在玩家正前方生成,随玩家移动、旋转始终保持在玩家身前;松开鼠标左键后,护盾将作为抛射物向前发射。

遇到的问题

目前松开鼠标左键后,护盾仅向前移动一小段距离就会冻结,且无论玩家当前处于什么位置,护盾的运动表现都默认玩家位于坐标(0,0)点。

抛射物默认从(0,0)位置移动而非玩家当前位置
图中三角形为玩家角色

相关实现代码

玩家控制器脚本:

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

public class PlayerController : MonoBehaviour
{
    public Rigidbody2D rb;
    public GameObject Shield;
    public float moveSpeed = 4.3f;
    public float sheildSpeed = 2f;
    
    Vector2 movement;
    bool isDead = false;

    void Update()
    {
        movement.x = Input.GetAxisRaw("Horizontal");
        movement.y = Input.GetAxisRaw("Vertical");

        Vector3 mouseScreen = Input.mousePosition;
        Vector3 mouse = Camera.main.ScreenToWorldPoint(mouseScreen);

        transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(mouse.y - transform.position.y, mouse.x - transform.position.x) * Mathf.Rad2Deg - 90); 

        if (Input.GetMouseButtonDown(0)) {
            Shield = Instantiate(Shield, transform.position + transform.forward + transform.up, transform.rotation);
            Shield.transform.parent = transform;
        }

        if (Input.GetMouseButtonUp(0)) {
            Shield.transform.parent = null;
        } 
    }

    void FixedUpdate() {
        if (!isDead) {
            rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
        }
    }
}

护盾控制器脚本:

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

public class ShieldController : MonoBehaviour
{
    public float sheildSpeed = 2f;

    void FixedUpdate()
    {
        this.GetComponent<Rigidbody2D>().MovePosition(this.transform.up * sheildSpeed);       
    }
}

修复方案

根因定位

  • Rigidbody2D.MovePosition() 方法要求传入的是目标世界坐标,你当前只传入了 transform.up * sheildSpeed,相当于每次执行都强制把护盾位置设置为方向向量乘以速度的结果,方向向量本身模长为1,所以无论护盾当前在什么位置,都会被拉到原点附近,自然会出现从(0,0)出发、走一小段就不动的现象。
  • 移动逻辑没有乘以 Time.fixedDeltaTime,速度会受物理帧帧率影响,不符合预期。

代码修改

1. 修复护盾移动逻辑

修改 ShieldController 脚本如下:

using UnityEngine;

public class ShieldController : MonoBehaviour
{
    public float sheildSpeed = 2f;
    private Rigidbody2D _shieldRb;

    // 提前缓存组件,避免每帧调用GetComponent产生性能损耗
    private void Awake()
    {
        _shieldRb = GetComponent<Rigidbody2D>();
    }

    private void FixedUpdate()
    {
        // 正确逻辑:当前位置 + 方向 * 速度 * 时间增量
        _shieldRb.MovePosition(transform.position + transform.up * sheildSpeed * Time.fixedDeltaTime);
    }
}

2. 可选优化(规避运行时报错风险)

你当前的代码如果快速点击鼠标左键,会重复生成护盾、丢失上一个护盾的引用,建议修改 PlayerController 中生成护盾的判断逻辑:

// 只有当前没有生成护盾时才执行创建逻辑
if (Input.GetMouseButtonDown(0) && Shield == null) {
    // 2D场景不需要transform.forward,可直接乘以你需要的偏移量控制护盾和玩家的距离
    Shield = Instantiate(Shield, transform.position + transform.up * 0.5f, transform.rotation);
    Shield.transform.parent = transform;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 17:57:03