Unity2D中实现子弹的弧线轨迹

Unity2D中实现子弹的弧线轨迹

    • 前言
    • 设计思路
    • 代码实现
    • 第一次发blog的感想

前言

大家好!我是第一次写blog的Unity2D初学者,最近在研究射击RPG时看到一些比较酷炫的弧线子弹射击,很多2D平台射击游戏、弹幕射击游戏都使用了这种功能,今天试着做了一下这个功能的实现,和大家分享下。
Unity2D中实现子弹的弧线轨迹_第1张图片
这里借用bilibili视频av54898959的图片,具体思路也借鉴于这个视频,大家可以去看看~
视频传送门:如何做出漂亮的追踪子弹轨迹

设计思路

首先对弧线运动做一下几何分析,如下图:
Unity2D中实现子弹的弧线轨迹_第2张图片
这里我们看到,其实弧线运动时,每一刻的速度都遵循同一个特点:都偏向目标点的同一侧且为弧线外侧。因此可以构想出两种思路:

  1. 逐帧矫正
    在每一帧中都先将子弹朝向矫正向正对目标点,然后在这个方向的基础上进行一定程度的偏转,保证每一刻的速度组合为弧线的切线;
  2. 利用插值法
    在加载物体时将初始朝向设置为存在较大偏转,然后利用插值法(这里是使用弧型插值Slerp方法)逐帧向正对目标点的方向靠近,实现“弧线接近”的感觉。

代码实现

方法1的实现:

    float moveSpeed;
    Vector3 moveDir;
    Vector3 destination;
    float targetAngle,circleAngle;//矫正用的角度和偏离用的角度

    // Start is called before the first frame update
    void Start()
    {
        moveSpeed = 7;
        circleAngle = 40;//弧线中矫正后偏转方向
        destination = new Vector3(3.49f, 0, 0);
        moveDir = Vector3.right;
    }

    //每一帧矫正指向目标,并添加偏转
    // Update is called once per frame
    void Update()
    {
    	//获取当前目标方向
        moveDir = destination - thistf.position;
        targetAngle = 360 - Mathf.Atan2(moveDir.x, moveDir.y) * Mathf.Rad2Deg;
        //矫正方向到正对目标点
        this.transform.eulerAngles = new Vector3(0, 0, 90 + targetAngle);
        //产生偏移以制造弧度
        this.transform.rotation = this.transform.rotation * Quaternion.Euler(0, 0, circleAngle);
        //translate方法的位移在不输入第二个参数的情况下默认基于self坐标系
        this.transform.Translate(Vector3.right * Time.deltaTime * moveSpeed);
    }
    

方法2的实现:
先放个鬼畜版的错误教学(螺旋升天哈哈哈)

    void Update()
    {
        this.transform.right = Vector3.Slerp(this.transform.up, destination - this.transform.position, 0.5f/Vector3.Distance(destination,this.transform.position));
        this.transform.position += this.transform.up * moveSpeed * Time.deltaTime;
    }

这是正确的代码:

    //方法2:基于Slerp方法矫正指向,初始化时的朝向可以任意设置
    void Update()
    {
    //这里第三个float参数为偏转速度,设置为越靠近值越大,以免接近的趋势不够无法击中目标
        this.transform.right = Vector3.Slerp(this.transform.right, destination - this.transform.position, 0.5f/Vector3.Distance(destination,this.transform.position));
        this.transform.position += this.transform.right * moveSpeed * Time.deltaTime;
    }

注意一下:
这里的right向量取决于你子弹sprite的指向,像我用的图片就是右方为正向,如果你的图片是以上方为正方就应该写为Vector3.up和transform.up。

第一次发blog的感想

第一次发blog,之前更多的是在CSDN这个资源充足,大佬云集的平台上了解知识。这次开始写blog一方面是为了给自己对知识的掌握更深入,一方面也希望能把自己学习的知识分享给其他人,如果您看到这篇blog觉得有所帮助,那就再好不过了,谢谢您的关注!

你可能感兴趣的:(Unity2D开发日志)