You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity技术问题:无法让坦克子弹朝鼠标指向方向发射

坦克朝鼠标方向发射子弹的实现问题

我正尝试实现坦克朝鼠标指向的方向发射子弹的功能。目前坦克已能旋转朝向鼠标,但不知道如何让子弹飞向正确的方向;顶部的炮塔可以正确旋转,我不确定是否可以利用该炮塔的旋转角度来确定子弹的发射方向。该项目基于Unity 3D开发,采用的是2.5D斜视角俯览模式,相关代码如下:

public class tankScript : MonoBehaviour
{
    public float rotateSpeed = 90;
    public float speed = 5.0f;
    public float fireInterval = 0.5f;
    public float bulletSpeed = 20;
    public Transform spawnPoint;
    public GameObject bulletObject;
    float nextFire;

    Camera cam;
    Collider planecollider;
    RaycastHit hit;
    Ray ray;
    Vector3 mouseDirection;

    void Start()
    {
        nextFire = Time.time + fireInterval;

        cam = GameObject.Find("Main Camera").GetComponent<Camera>();
        planecollider = GameObject.Find("Plane").GetComponent<Collider>();
    }

    void Update()
    {
        var transAmount = speed * Time.deltaTime;
        var rotateAmount = rotateSpeed * Time.deltaTime;

        if (Input.GetKey("w"))
        {
            transform.Translate(0, 0, transAmount);
        }
        if (Input.GetKey("s"))
        {
            transform.Translate(0, 0, -transAmount);
        }
        if (Input.GetKey("a"))
        {
            transform.Rotate(0, -rotateAmount, 0);
        }
        if (Input.GetKey("d"))
        {
            transform.Rotate(0, rotateAmount, 0);
        }
        if (Input.GetButtonDown("Fire1") && Time.time > nextFire)
        {
            nextFire = Time.time + fireInterval;
            fire();
        }
    }

    void fire()
    {
        ray = cam.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit))
        {
            if (hit.collider == planecollider)
            {
                mouseDirection = new Vector3(hit.point.x, 0.25f, hit.point.z);
                float step = bulletSpeed * Time.deltaTime;
                var bullet = Instantiate(bulletObject, spawnPoint.position, spawnPoint.rotation);
                bullet.GetComponent<Rigidbody>().transform.localPosition = Vector3.MoveTowards(transform.localPosition, mouseDirection, step);

            }
        }
    }
}

解决方案

你完全可以利用炮塔的旋转角度来确定子弹方向,这是最直接的方式——既然炮塔已经能正确对准鼠标,那挂载在炮塔上的spawnPoint的朝向就是子弹该飞行的方向。另外你当前的fire()方法存在逻辑错误:Vector3.MoveTowards只在实例化子弹时执行一次,无法让子弹持续移动,正确的做法是通过Rigidbody给子弹施加速度,或在子弹脚本中处理持续移动。

方法一:复用炮塔朝向(推荐)

如果spawnPoint是绑定在炮塔上的Transform,它的forward方向就是炮塔指向的方向,直接用这个方向给子弹加速度:

void fire()
{
    // 实例化子弹,继承spawnPoint的位置和旋转
    var bullet = Instantiate(bulletObject, spawnPoint.position, spawnPoint.rotation);
    Rigidbody rb = bullet.GetComponent<Rigidbody>();
    if (rb != null)
    {
        // 给子弹施加沿炮塔前方向的速度
        rb.velocity = spawnPoint.forward * bulletSpeed;
    }
}

这种方式完全复用了你已实现的炮塔旋转逻辑,不需要额外的射线检测计算方向,简洁高效。

方法二:通过鼠标射线计算方向

如果坚持用鼠标点击的平面点计算方向,需要计算子弹生成位置到鼠标点的归一化方向向量,再给子弹施加速度:

void fire()
{
    ray = cam.ScreenPointToRay(Input.mousePosition);
    if (Physics.Raycast(ray, out hit) && hit.collider == planecollider)
    {
        // 忽略Y轴差异,保持水平方向计算
        Vector3 targetPos = new Vector3(hit.point.x, spawnPoint.position.y, hit.point.z);
        Vector3 moveDirection = (targetPos - spawnPoint.position).normalized;

        var bullet = Instantiate(bulletObject, spawnPoint.position, Quaternion.LookRotation(moveDirection));
        Rigidbody rb = bullet.GetComponent<Rigidbody>();
        if (rb != null)
        {
            rb.velocity = moveDirection * bulletSpeed;
        }
    }
}

这里用Quaternion.LookRotation让子弹朝向目标方向,同时给Rigidbody设置速度,确保子弹持续向鼠标点移动。

额外注意事项

  • 确保子弹的Rigidbody组件未勾选Is Kinematic,否则速度设置不会生效。
  • 若选择在子弹脚本中处理移动,可在Update方法中调用transform.Translate(transform.forward * bulletSpeed * Time.deltaTime),但用Rigidbody的方式更符合Unity物理系统的规范。
  • 务必将spawnPoint绑定在炮塔的Transform层级下,确保其旋转与炮塔同步。

内容的提问来源于stack exchange,提问作者Ben Goodall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 06:47:36