3D俯视角游戏中如何让球形子弹朝鼠标光标方向发射?
修复3D俯视角子弹朝向鼠标的问题
你的问题根源在于ScreenToWorldPoint(Input.mousePosition)的使用方式错误:Input.mousePosition只包含屏幕坐标的x/y值,z值为0,而ScreenToWorldPoint需要z值来确定相对于相机的深度,这导致你得到的是相机近平面上的点,而非鼠标在地面的投影位置。
下面是两种可靠的修复方案:
方案一:在Bullet中用射线检测获取地面投影点
修改Bullet脚本的Start方法,通过射线检测计算鼠标在目标平面(y=0.5)的交点:
public class Bullet : MonoBehaviour { [SerializeField] private float speed = 5.0f; private Vector3 bulletDirection; void Start() { // 从相机向鼠标位置发射射线 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 定义子弹飞行的平面高度 float targetY = 0.5f; Plane groundPlane = new Plane(Vector3.up, targetY); // 计算射线与平面的交点 if (groundPlane.Raycast(ray, out float distance)) { Vector3 targetPoint = ray.GetPoint(distance); // 计算方向并忽略y轴分量(保持水平飞行) bulletDirection = (targetPoint - transform.position).normalized; bulletDirection.y = 0; } else { // fallback:如果射线未命中平面,使用相机到目标平面的距离作为深度 Vector3 mousePosWithDepth = Input.mousePosition; mousePosWithDepth.z = Camera.main.transform.position.y - targetY; Vector3 targetPoint = Camera.main.ScreenToWorldPoint(mousePosWithDepth); targetPoint.y = targetY; bulletDirection = (targetPoint - transform.position).normalized; bulletDirection.y = 0; } Debug.Log("Target: " + ray.GetPoint(distance) + ", Direction: " + bulletDirection); } void Update() { transform.Translate(bulletDirection * speed * Time.deltaTime); } }
方案二:在PlayerController中提前计算方向(推荐)
将发射逻辑集中在PlayerController中,提前计算好子弹方向再传递给Bullet,这样Bullet无需处理鼠标输入,职责更清晰:
1. 修改PlayerController的发射代码
public class PlayerController : MonoBehaviour { public Bullet bulletPrefab; private float targetY = 0.5f; void Update() { if (Input.GetMouseButtonDown(0)) { FireBullet(); } } void FireBullet() { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); Plane groundPlane = new Plane(Vector3.up, targetY); Vector3 targetPoint; if (groundPlane.Raycast(ray, out float distance)) { targetPoint = ray.GetPoint(distance); } else { Vector3 mousePosWithDepth = Input.mousePosition; mousePosWithDepth.z = Camera.main.transform.position.y - targetY; targetPoint = Camera.main.ScreenToWorldPoint(mousePosWithDepth); targetPoint.y = targetY; } // 计算水平方向 Vector3 direction = (targetPoint - transform.position).normalized; direction.y = 0; // 实例化子弹并传递方向 Bullet bullet = Instantiate(bulletPrefab, transform.position, Quaternion.identity); bullet.SetDirection(direction); } }
2. 修改Bullet脚本
public class Bullet : MonoBehaviour { [SerializeField] private float speed = 5.0f; private Vector3 bulletDirection; public void SetDirection(Vector3 direction) { bulletDirection = direction; } void Update() { transform.Translate(bulletDirection * speed * Time.deltaTime); } }
两种方案都能准确获取鼠标在地面的投影位置,确保子弹朝鼠标方向飞行。方案二更符合代码职责分离的原则,便于后续扩展。
内容的提问来源于stack exchange,提问作者EPiedrahita
相关产品推荐
相关产品推荐

