利用加速度转盘的实现

好久没做过2D项目,今天做一个摇奖转盘,没多想做出来发现停下来很生硬。就模拟加速和减速,这里是距离,最后换成改变transform改变角度就好了。

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

//计算转盘的加速度方法
//by thinbug 2019.3
//这里为了直观看到表现,让一个盒子前进和刹车.调试好后可以把距离改成旋转
public class TBTurnAround : MonoBehaviour {

    //
    //加速度 a = (v - v0) / t
    //瞬时速度公式 v = v0 + at;
    //位移公式 x = v0t +½at²;
    //平均速度 v = x / t = (v0 + v) / 2
    //导出公式 v²-v0²=2as
    //(单位均为国际单位,即a的单位为m/s²,x的单位为m,v的单位为m/s)
   
    float v1 = 100f;    //最快时候的速度
    float s1 = 170f;    //需要行进的距离,这个可以替换成转盘的角度localEulerAngles , 角度一直累加(减少),方向不同,不用考虑360的问题,Inspector面板显示的是360,实际值随着转动很大(很小).


    float s2 = 30f;     //开始制动停止的距离

    public int stat;
	void Start () {
        
	}

    Vector3 at = Vector3.zero;
    float btime = 0f;
    float t;
    float a;
    float pass;
    void Update ()
    {
        if (stat == 1)
        {
            Debug.Log("加速开始");
            //状态等于1的时候开始.
            btime = Time.time;
            stat = 2;

            //根据公式v²-v0²=2as计算出启动的加速度
            //a = (v²-v0²)/2s
            a = Mathf.Pow(v1, 2) / (2 * s1);
        }
        if (stat == 2)
        {
            //当前运行了多久,计算当时行走的距离
            t = Time.time - btime;
            pass = v1 * t + 0.5f * a * t * t; //S = 1/2 at^2;
            at.z = pass;

            

            if (pass > s1)
            {
                at.z = s1;
                transform.transform.position = at;
                Debug.Log("减速开始");
                stat = 3;
                btime = Time.time;
                
                //减速也是先计算刹车的加速度
                a = -Mathf.Pow(v1, 2) / (2 * s2);
                
                return;
            }
            transform.transform.position = at;
        }
        if (stat == 3)
        {

            t = Time.time - btime;
            pass = v1 * t + 0.5f * a * t * t;

            //这个计算下当时的速度,判断是否该停下来了.如果是负数.
            float atv = v1 + a * t;

            if (atv < 0f)
            {
                at.z = s1 + s2;
                transform.transform.position = at;
                stat = -1;
                Debug.Log("到了");
                return;
            }

            at.z = pass + s1;
            transform.transform.position = at;
        }
    }
}

在场景中拖动一个球,拖脚本上去,把变量stat改成1就开始了。

补充:
多次使用到这个脚本,又进行了一些修改,改为一个静态函数,方便调用。下面是代码。

using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;


public class MathFunction : MonoBehaviour
{
    //
    //加速度 a = (v - v0) / t
    //瞬时速度公式 v = v0 + at;
    //位移公式 x = v0t +½at²;
    //平均速度 v = x / t = (v0 + v) / 2
    //导出公式 v²-v0²=2as
    //(单位均为国际单位,即a的单位为m/s²,x的单位为m,v的单位为m/s)

    //计算加速度方法
    //by thinbug 2022.9.16
    //这里为了直观看到表现,让一个盒子前进和刹车.
    //物理加速后进行减速
    /// <summary>
    /// 
    /// </summary>
    /// <param name="initSpeed">初速度</param>
    /// <param name="accelerateMaxSpeed">加速到最高时候的速度</param>
    /// <param name="accelerateMaxDis">加速到最高时候到起点的距离</param>
    /// <param name="decelerateMaxDis">减速的最长距离</param>
    /// <param name="action">返回结果{是否结束,距离}</param>
    /// <param name="callbackFrameRate">返回的周期单位毫秒</param>
    /// <returns></returns>
    public static async Task PhysicsAccelerateDecelerate(float initSpeed = 50f, float accelerateMaxSpeed = 100f, float accelerateMaxDis = 100f, float decelerateMaxDis = 100f, UnityAction<bool,float> action = null, int callbackFrameRate = 50)
    {
        int delaytime = (int)(1000f / callbackFrameRate);    //每帧的时间
        int state = 1;
        float btime = Time.time;
        float t;
        float a;
        float pass;
        float nowAt = 0f;
        //加速阶段
        //根据公式v²-v0²=2as计算出启动的加速度
        //a = (v²-v0²)/2s
        a = (Mathf.Pow(accelerateMaxSpeed, 2) - Mathf.Pow(initSpeed, 2)) / (2 * accelerateMaxDis);


        while (state > 0)
        {
            action?.Invoke(false, nowAt);
            await Task.Delay(delaytime);
            if (state == 1)
            {
                //当前运行了多久,计算当时行走的距离
                t = Time.time - btime;
                //瞬时速度公式 v = v0 + at;
                //位移公式 x = vt +½at²;
                
                //pass = accelerateMaxSpeed * t + 0.5f * a * t * t; //S = 1/2 at^2;
                pass = initSpeed * t + 0.5f * a * t * t; //S = 1/2 at^2;
                nowAt = pass;
                if (pass > accelerateMaxDis)
                {
                    nowAt = accelerateMaxDis;
                    state= 2;
                    btime = Time.time;

                    //减速也是先计算刹车的加速度,vt是0
                    a = 0-Mathf.Pow(accelerateMaxSpeed, 2) / (2 * decelerateMaxDis);
                }
            }
            else if (state == 2)
            {
                t = Time.time - btime;
                pass = accelerateMaxSpeed * t + 0.5f * a * t * t;

                //这个计算下当时的速度,判断是否该停下来了.如果是负数.
                float atv = accelerateMaxSpeed + a * t;

                if (atv < 0f)
                {
                    nowAt = accelerateMaxDis + decelerateMaxDis;
                    state = -1;
                }
                else
                {
                    nowAt = pass + accelerateMaxDis;
                }
            }
        }

        action?.Invoke(true, nowAt);
    }

    //下面的是演示如何使用

    private async void OnEnable()
    {
        await PhysicsAccelerateDecelerate(initspd, addspd, dis1, dis2, test, 50);
    }

    public float initspd = 10f;
    public float addspd = 50f;
    public float dis1 = 100f;
    public float dis2 = 50f;


    void test(bool finish,float dis)
    {
        Debug.Log("Finish:"+finish +" ,dis : "+dis);
        Vector3 at = transform.position;
        at.z = dis;
        transform.position = at;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thinbug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值