Unity俯视角射击游戏子弹旋转后移动方向异常问题
俯视角射击子弹旋转后移动方向异常问题
开发类似《星露谷物语》中《草原之王之旅》的俯视角射击游戏时,遇到以下问题:
- 上下瞄准射击时,将子弹旋转90度以匹配移动方向后,向上射击时子弹向左移动,向下射击时向右移动;
- 不旋转子弹时,移动方向正常。
现有代码
public class BulletMovement : MonoBehaviour { public Vector2 moveDirection; private GameObject player; public int speed; // Start is called before the first frame update void Start() { player = GameObject.Find("Player"); Move(); } // Update is called once per frame void Update() { transform.Translate(moveDirection * Time.deltaTime * speed); CheckIfOutOfBounds(); } //Moves the bullet in the direction the player is facing when the bullet is fired private void Move() { if (player.GetComponent<PlayerMovement>().GetPlayerFacing().Equals("up")) { RotateBullet(90); moveDirection = new Vector2(0, 1); } if (player.GetComponent<PlayerMovement>().GetPlayerFacing().Equals("down")) { RotateBullet(90); moveDirection = new Vector2(0, -1); } if (player.GetComponent<PlayerMovement>().GetPlayerFacing().Equals("left")) { //Moves the bullet in front of the gun transform.Translate(-0.363f, 0, 0); moveDirection = new Vector2(-1, 0); } if (player.GetComponent<PlayerMovement>().GetPlayerFacing().Equals("right")) { //Moves the bullet in front of the gun transform.Translate(0.363f, 0, 0); moveDirection = new Vector2(1, 0); } } //Destroys the bullet if it goes off-screen private void CheckIfOutOfBounds() { if (transform.position.x is > 10 or < -10) { Destroy(gameObject); } if (transform.position.y is > 10 or < -10) { Destroy(gameObject); } } private void RotateBullet(int degrees) { transform.rotation = Quaternion.Euler(new Vector3(0, 0, degrees)); } }
已尝试的方法
transform.Rotate(Vector3(0, 0, 90))transform.Rotate(Vector3.right)transform.rotation = Quaternion.Euler(new Vector3(0, 0, degrees))(当前使用)
问题原因
transform.Translate 默认使用自身局部坐标系,当子弹旋转后,局部坐标系的X/Y轴方向和世界坐标系不再一致。比如子弹向上旋转90度后,其局部X轴对应世界的Y轴,局部Y轴对应世界的-X轴,此时用世界坐标系的Vector2(0,1)调用Translate,就会导致子弹向局部X轴方向移动,对应世界的左方。
修复方案
- 修改Translate的坐标系参数:将Translate改为使用世界坐标系,避免局部旋转影响移动方向。
- 调整上下方向的旋转角度:向下射击时需要旋转-90度(或270度),才能让子弹图形朝向正确方向。
修改后的代码如下:
修复后的BulletMovement代码
public class BulletMovement : MonoBehaviour { public Vector2 moveDirection; private GameObject player; public int speed; private PlayerMovement playerMovement; // 缓存组件引用 void Start() { player = GameObject.Find("Player"); playerMovement = player.GetComponent<PlayerMovement>(); Move(); } void Update() { // 使用Space.World指定世界坐标系移动,不受自身旋转影响 transform.Translate(moveDirection * Time.deltaTime * speed, Space.World); CheckIfOutOfBounds(); } private void Move() { var playerFacing = playerMovement.GetPlayerFacing(); if (playerFacing.Equals("up")) { RotateBullet(90); moveDirection = new Vector2(0, 1); } else if (playerFacing.Equals("down")) { // 向下时旋转-90度,让子弹图形朝下 RotateBullet(-90); moveDirection = new Vector2(0, -1); } else if (playerFacing.Equals("left")) { transform.Translate(-0.363f, 0, 0, Space.World); moveDirection = new Vector2(-1, 0); } else if (playerFacing.Equals("right")) { transform.Translate(0.363f, 0, 0, Space.World); moveDirection = new Vector2(1, 0); } } private void CheckIfOutOfBounds() { if (transform.position.x > 10 || transform.position.x < -10) { Destroy(gameObject); } if (transform.position.y > 10 || transform.position.y < -10) { Destroy(gameObject); } } private void RotateBullet(int degrees) { transform.rotation = Quaternion.Euler(0, 0, degrees); } }
额外优化建议
- 缓存
PlayerMovement组件引用,避免重复调用GetComponent提升性能; - 将硬编码的子弹偏移值
0.363f改为公共变量,方便在Inspector面板中可视化调整。
内容的提问来源于stack exchange,提问作者A guy with questions
相关产品推荐
相关产品推荐

