Unity 2D/C#开发中护盾抛射物不从玩家位置生成且移动异常求助
问题背景
我正在开发一款2D上帝视角无尽竞技场战斗游戏,设定中护盾同时作为玩家的进攻手段:按住鼠标左键时,护盾会在玩家正前方生成,随玩家移动、旋转始终保持在玩家身前;松开鼠标左键后,护盾将作为抛射物向前发射。
遇到的问题
目前松开鼠标左键后,护盾仅向前移动一小段距离就会冻结,且无论玩家当前处于什么位置,护盾的运动表现都默认玩家位于坐标(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
相关产品推荐
相关产品推荐

