【用Unity实现抛物线向目标点发射炮弹功能】

用Unity实现抛物线向目标点发射炮弹功能

游戏开发中经常会涉及到制作向特定的目标点投掷物体的功能,比如:塔防类、射击类、即时战斗类游戏…等等,首先需要明确的一点是,要打中目标点,发射的角度、发射点与目标点的距离是最重要的计算参数。如果发射的物体是具有方向性的实体,那被发射出去的物体是要有角度变化的,而不只是一条运动轨迹。
本功能实现原理是根据与目标点距离,实时设置炮弹的旋转角度。炮弹始终朝着自身正前方移动。话不多说,上代码!

  • 准备阶段
    实现此功能,我一共创建了三个脚本:
    DirectionalArtilleryShell.cs挂载到附加了Collider和Rigbody的炮弹物体上。
    DirectionalArtilleryController.cs 挂载到发射台上
    DirectionalArtilleryShootPoint.cs挂载到发射点组件上,其实这个脚本可以省略掉的,为了后面加上对发射台其他的操作,就先加上吧,哈哈。
    为了使用方便,发射的炮弹是通过 Resources.Load 实例化的,DirectionalArtilleryShell是发射的炮弹,FX_ZiMuDan_ChildHit是炮弹击中之后势力画出来的特效。
    炮弹和特效存放目录位置如图(可根据不同项目自行设置):
    存放炮弹和特效目录
    组件节点顺序
    组件节点顺序
  • 一、实现炮弹的飞行功能,脚本名称【DirectionalArtilleryShell】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DirectionalArtilleryShell : MonoBehaviour
{
    //打击目标
    private Transform Target;
    //发射速度
    private float speed = 0f;
    //最小接近距离
    private float min_distance = 0f;
    //是否需要追踪
    private bool IsTrace = false;
    //炮弹与目标点距离
    private float distanceToTarget;
    //是否移动
    private bool move_flag = true;
    //目标点坐标
    private Vector3 TargetPosition = Vector3.zero;
    //击中目标点时与目标点的角度
    public float HitAngle = 45f;
    //集中特效
    private GameObject HitEffect;

    private void Awake()
    {
        HitEffect = Resources.Load("Prefabs/ShellHitEffect/FX_ZiMuDan_ChildHit") as GameObject;
    }

    /// <summary>
    /// 参数: 攻击目标点、发射速度、最小停止运动距离
    /// </summary>
    public void SetShellData(Transform target,float speed,float distance,float hitAngle,bool isTrace) 
    {
        Target = target;
        TargetPosition = Target.position;
        this.speed = speed;
        min_distance = distance;
        HitAngle = hitAngle;
        IsTrace = isTrace;
        distanceToTarget = Vector3.Distance(transform.position, Target.position);
    }

    /// <summary>
    /// 发射炮弹
    /// </summary>
    public void Shoot() 
    {
        StartCoroutine(Parabola());
    }

    /// <summary>
    /// 炮弹主要实现
    /// </summary>
    /// <returns></returns>
    IEnumerator Parabola()
    {
        while (move_flag)
        {
            if (IsTrace)
            {
                TargetPosition = Target.position;
            }
            transform.LookAt(TargetPosition);
            float angle = Mathf.Min(1, Vector3.Distance(transform.position, TargetPosition) / distanceToTarget) * HitAngle;
            transform.rotation = transform.rotation * Quaternion.Euler(Mathf.Clamp(-angle, -42,42), 0, 0);
            float currentDist = Vector3.Distance(transform.position, TargetPosition);
            if (currentDist < min_distance)
            {
                move_flag = false;
            }
            transform.Translate(Vector3.forward * Mathf.Min(speed * Time.deltaTime, currentDist));
            yield return null;
        }
        if (move_flag == false)
        {
            transform.position = TargetPosition;
            StopCoroutine(Parabola());
            GameObject vfx = Instantiate(HitEffect);
            vfx.transform.position = transform.position;
            Destroy(gameObject);
        }
    }
}


  • 二、下面是实例化炮弹的控制器了,脚本名称【DirectionalArtilleryController】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DirectionalArtilleryController : MonoBehaviour
{
    [Header("攻击目标点")]
    public Transform Target;

    [Header("运动速度")]
    public float speed = 10;

    [Header("最小接近距离, 以停止运动")]
    public float min_distance = 0.5f;

    [Header("到达目标时与目标的角度")]
    public float HitAngle = 45f;

    [Header("是否追踪")]
    public bool IsTrace = false;

    //炮弹实例
    private GameObject DirShell;

    //炮弹发射位置
    private DirectionalArtilleryShootPoint ShootPoint = null;

    private void Awake()
    {
        DirShell = Resources.Load("Prefabs/DirectionalArtillery/DirectionalArtilleryShell") as GameObject;
    }

    private void Start()
    {
        if (ShootPoint == null)
        {
            ShootPoint = GetComponentInChildren<DirectionalArtilleryShootPoint>();
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            DirectionalArtilleryShell artilleryShell = CreatShell();
            artilleryShell.transform.SetParent(ShootPoint.transform);
            artilleryShell.transform.localPosition = Vector3.zero;
            artilleryShell.SetShellData(Target,speed,min_distance, HitAngle, IsTrace);
            artilleryShell.Shoot();
        }
    }

    /// <summary>
    /// 创建定向炮弹实例
    /// </summary>
    /// <returns></returns>
    private DirectionalArtilleryShell CreatShell() 
    {
        GameObject shellObj = Instantiate(DirShell);

        shellObj.transform.TryGetComponent(out DirectionalArtilleryShell shell);

        return shell;
    }
}

  • 三、下面是炮弹的发射位置,脚本名称【DirectionalArtilleryShootPoint 】
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DirectionalArtilleryShootPoint : MonoBehaviour
{
    //这是没有方法的空脚本确实没啥用...哈哈哈
}

按照上面的步骤设置好,把Target对象组件拖进脚本引用,设置好参数,其中IsTrace是是否追踪,如果开启则炮弹会实时计算出新的抛物线角度方向到目标点。运行编辑器,按下Space键就可以看到这样的效果啦:
炮弹向目标点发射效果

各位Unity兄弟萌,如果本文章对您有帮助,欢迎点赞和收藏啊!天气炎热,注意降温哦~ ovo

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇

)">
下一篇>>