Unity——子弹跟踪

Unity——子弹跟踪

在射击类游戏中,会经常遇到需要子弹自动跟踪的功能需求,考虑用简单的方法,实现一个子弹自动跟踪的效果。

重点实现逻辑功能,对于子弹的发射器的prefabs的设计不重点考虑,只使用简单的cube等3D物体来模拟子弹、发射器、目标。

实现思路

自动跟踪,即子弹的朝向始终面对目标物。

子弹的位置和朝向都跟随时间进行变化,最终到达目标物处。

代码实现

创建发射器

创建一个cube作为发射器,添加一个shot脚本,每2秒发射一个子弹。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class shot : MonoBehaviour
{
    public GameObject missile; // 子弹
    float currentTime;

    void Update()
    {
        currentTime += Time.deltaTime;
        if (currentTime > 2)
        {
            currentTime = 0;
            GameObject m = GameObject.Instantiate(missile);
            m.transform.localPosition = Vector3.zero;
            m.SetActive(true);
        }
    }
}

创建子弹

创建一个Capsule作为子弹,将该子弹拖放到上面shot脚本中的missile属性中。并为子弹添加一个track脚本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class track : MonoBehaviour
{
    public Transform target; //瞄准的目标
    Vector3 speed = new Vector3(0, 0, 5); //炮弹本地坐标速度
    Vector3 lastSpeed; //存储转向前炮弹的本地坐标速度
    int rotateSpeed = 90; //旋转的速度,单位 度/秒
    Vector3 finalForward; //目标到自身连线的向量,最终朝向
    float angleOffset;  //自己的forward朝向和mFinalForward之间的夹角
    RaycastHit hit;

    void Start()
    {
        //将炮弹的本地坐标速度转换为世界坐标
        speed = transform.TransformDirection(speed);
    }

    void Update()
    {
        CheckHint();
        UpdateRotation();
        UpdatePosition();
    }

    //射线检测,如果击中目标点则销毁炮弹
    void CheckHint()
    {
        if (Physics.Raycast(transform.position, transform.forward, out hit))
        {
            if (hit.transform == target && hit.distance < 1)
            {
                Destroy(gameObject);
            }
        }
    }

    //更新位置
    void UpdatePosition()
    {
        transform.position = transform.position + speed * Time.deltaTime;
    }

    //旋转,使其朝向目标点,要改变速度的方向
    void UpdateRotation()
    {
        //先将速度转为本地坐标,旋转之后再变为世界坐标
        lastSpeed = transform.InverseTransformDirection(speed);

        ChangeForward(rotateSpeed * Time.deltaTime);

        speed = transform.TransformDirection(lastSpeed);
    }

    void ChangeForward(float speed)
    {
        //获得目标点到自身的朝向
        finalForward = (target.position - transform.position).normalized;
        if (finalForward != transform.forward)
        {
            angleOffset = Vector3.Angle(transform.forward, finalForward);
            if (angleOffset > rotateSpeed)
            {
                angleOffset = rotateSpeed;
            }
            //将自身forward朝向慢慢转向最终朝向
            transform.forward = Vector3.Lerp(transform.forward, finalForward, speed / angleOffset);
        }
    }
}

创建目标物

创建一个sphere作为目标物。并拖到track脚本的target上。

效果

在这里插入图片描述


版权声明:本文为weixin_43165605原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。