Unity 2D开发如何让枪械朝鼠标方向而非鼠标位置发射子弹
问题根源
你当前子弹速度随鼠标距离变化的原因非常直接:你赋值给子弹刚体速度的direction向量,是枪口到鼠标点的原始位移向量,这个向量的长度等于枪口和鼠标之间的实际世界单位距离。鼠标离枪口越近,向量长度越短,子弹速度就越低;鼠标越远速度越快,速度完全不受控制。
修复方案
不需要额外重新计算指向角度,只要对方向向量做归一化处理即可:归一化会把向量的长度固定为1,只保留纯粹的朝向信息,之后用这个单位方向向量乘以你预设的固定子弹速度,就能保证子弹永远沿枪口指向飞行,速度全程恒定,和鼠标与玩家的距离完全无关。
具体修改步骤
- 在类的公共变量区新增固定子弹速度参数,方便后续在编辑器调整数值
- 计算完枪口到鼠标的位移后,直接获取归一化后的单位方向向量
- 给子弹赋值速度时,用「单位方向向量 * 固定子弹速度」替换原来直接传入原始位移向量的写法
- 修正原代码中碰撞忽略的逻辑问题:不需要通过
Find查找子弹克隆体,直接传入当前生成的子弹实例即可
修正后的完整代码
public GameObject bullet; public GameObject player; public float bulletSpeed = 12f; // 子弹固定飞行速度,可根据需求在Inspector调整 // All the following is within an update function //Gets the mouse position, and assigns direction from gun to mouse Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); // 对齐z轴坐标,避免2D场景下方向计算出现偏差 mousePosition.z = transform.position.z; // 对位移向量做归一化,获取仅保留朝向信息的单位向量 Vector2 direction = (mousePosition - transform.position).normalized; float angle = Vector2.SignedAngle(Vector2.right, direction); Vector2 PlayerDimensions = player.transform.lossyScale; Vector2 PlayerLocation = player.transform.position; //If the Gun weapon type is selected if (weaponType == 2) { // Is used to flip the player sprite based on if the gun is facing left or right if (PlayerLocation.x > mousePosition.x) { PlayerDimensions.x = -1; player.transform.localScale = new Vector2(PlayerDimensions.x, PlayerDimensions.y); } else if (PlayerLocation.x < mousePosition.x) { PlayerDimensions.x = 1; player.transform.localScale = new Vector2(PlayerDimensions.x, PlayerDimensions.y); } // Aims the gun based on if player is facing left or right if (player.transform.lossyScale.x > 0) { transform.eulerAngles = new Vector3(0, 0, angle); } else if (player.transform.lossyScale.x < 0) { transform.eulerAngles = new Vector3(0, 0, 180 + angle); } } if (Input.GetMouseButtonDown(0) && weaponType == 2) { Debug.Log("Shoot"); Vector3 myPos = new Vector3(transform.position.x, transform.position.y); // 如果需要子弹生成时和枪口角度一致,可将Quaternion.identity替换为transform.rotation GameObject Bullet = Instantiate(bullet, myPos, Quaternion.identity); // 修正碰撞忽略逻辑,直接传入当前生成的子弹实例即可 Physics2D.IgnoreCollision(Bullet.GetComponent<BoxCollider2D>(), player.GetComponent<BoxCollider2D>(), true); // 用单位方向乘以固定速度赋值,保证子弹速度恒定 Bullet.GetComponent<Rigidbody2D>().velocity = direction * bulletSpeed; }
补充说明:如果你已经通过
angle变量控制了枪口的旋转角度,也可以直接用角度生成速度向量:Bullet.GetComponent<Rigidbody2D>().velocity = new Vector2(Mathf.Cos(angle * Mathf.Deg2Rad), Mathf.Sin(angle * Mathf.Deg2Rad)) * bulletSpeed;,效果和归一化方向向量完全一致,两种写法选一种即可。
内容的提问来源于stack exchange,提问作者Anthony Ruiz
相关产品推荐
相关产品推荐

