Unity中制作类Overwatch带抛射物与特效的FPS武器方案
Unity FPS抛射武器命中屏幕中心问题修复
需求与问题
- 目标:制作《守望先锋》风格抛射型武器,屏幕右侧显示武器模型,准星固定在屏幕中心;射击时可见子弹、弹道轨迹、枪口闪光,抛射物沿直线飞向屏幕中心(保留预判射击机制),视觉上子弹从枪管射出。
- 问题:当前代码生成的抛射物无法精准命中屏幕中心。
当前实现代码
public class ProjectileGun : MonoBehaviour, Gun { private float timerBetweenShoot; private int amoNow; private Camera fpsCam; public float timeBetweenShootSize; public int amo; public GameObject positionToSpawnBullet; public GameObject bulletPrefab; public Animator animator; public void altShoot() { // 无副武器射击逻辑 } public void shoot() { Instantiate(bulletPrefab, positionToSpawnBullet.transform.position, positionToSpawnBullet.transform.rotation); } public void reload() { amoNow = amo; } void Start() { amoNow = amo; timerBetweenShoot = timeBetweenShootSize; fpsCam = Camera.current; } void Update() { if(Input.GetKey(KeyCode.Mouse0)){ timerBetweenShoot -= Time.deltaTime; if(timerBetweenShoot < 0){ if(amoNow > 0){ shoot(); animator.SetBool("Shoot", true); animator.SetBool("Reload", false); amoNow--; }else{ animator.SetBool("Shoot", false); } timerBetweenShoot = timeBetweenShootSize; } }else{ animator.SetBool("Shoot", false); } if(Input.GetKey(KeyCode.R)){ if(amoNow < amo){ reload(); animator.SetBool("Reload", true); } } } }
问题根源
当前代码直接使用枪管的旋转作为子弹的飞行方向,但枪管位于屏幕右侧,其自身朝向与屏幕中心的射线方向存在偏差,导致子弹飞行轨迹偏离准星。
修复方案
关键修改点
- 获取屏幕中心的世界空间射线:通过主相机计算屏幕中心对应的世界方向,这是子弹需要飞向的目标方向。
- 修正子弹的生成旋转:不再使用枪管的旋转,而是根据屏幕中心射线方向设置子弹的朝向,同时保持子弹从枪管位置生成。
- 优化相机获取逻辑:将
Camera.current替换为Camera.main,避免场景中存在多个相机时的获取错误。
修正后的完整代码
public class ProjectileGun : MonoBehaviour, Gun { private float timerBetweenShoot; private int amoNow; private Camera fpsCam; public float timeBetweenShootSize; public int amo; public GameObject positionToSpawnBullet; public GameObject bulletPrefab; public Animator animator; public void altShoot() { // 无副武器射击逻辑 } public void shoot() { // 获取屏幕中心的射线 Ray ray = fpsCam.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0)); // 计算子弹需要朝向的方向 Vector3 targetDirection = ray.direction; // 生成子弹,使用目标方向设置旋转 GameObject bullet = Instantiate(bulletPrefab, positionToSpawnBullet.transform.position, Quaternion.LookRotation(targetDirection)); // 可选:如果子弹有飞行脚本,确保其沿forward方向移动 // bullet.GetComponent<Bullet>().SetDirection(targetDirection); } public void reload() { amoNow = amo; } void Start() { amoNow = amo; timerBetweenShoot = timeBetweenShootSize; // 使用Camera.main更可靠,需确保主相机标签为MainCamera fpsCam = Camera.main; } void Update() { if(Input.GetKey(KeyCode.Mouse0)){ timerBetweenShoot -= Time.deltaTime; if(timerBetweenShoot < 0){ if(amoNow > 0){ shoot(); animator.SetBool("Shoot", true); animator.SetBool("Reload", false); amoNow--; }else{ animator.SetBool("Shoot", false); } timerBetweenShoot = timeBetweenShootSize; } }else{ animator.SetBool("Shoot", false); } if(Input.GetKey(KeyCode.R)){ if(amoNow < amo){ reload(); animator.SetBool("Reload", true); } } } }
补充说明
- 确保你的子弹脚本(如果有)是沿自身
forward方向飞行的,这样修正后的旋转才能让子弹精准飞向屏幕中心。 - 若要添加枪口闪光,可在
shoot方法中同时生成枪口闪光特效,位置设置为枪管位置即可。 - 预判射击机制可保留:因为子弹是沿屏幕中心射线飞行,玩家可以通过提前瞄准目标位置实现预判。
内容的提问来源于stack exchange,提问作者Atom
相关产品推荐
相关产品推荐

