unity算法-斜抛运动(变种)

转载链接:https://www.cnblogs.com/lyh916/p/10415954.html
[Unity算法]斜抛运动(变种)
之前的斜抛运动,如果运动到游戏中,显然是太呆板了,那么可以试着加入一些效果,让它看起来更生动一些,类似游戏中的击飞或者掉落效果:
1.在达到最高点的时间点±X的时间段内,会有“减速”效果,形成一种在空中停留的感觉
2.落地后,反弹一次,再落地,就像是与地面发生了碰撞
相关公式:在这里插入图片描述


```csharp
using System;
using UnityEngine;

public class ObliqueThrow : MonoBehaviour {

    private float gravity;                      //重力加速度(当前)
    private float gravityValue = -9.8f;         //重力加速度值1
    private Vector2 horizontalDir;              //水平方向
    private float startSpeed;                   //初速度
    private float sinValue;                     //sin值
    private float cosValue;                     //cos值
    private Vector3 startPos;                   //开始位置
    private float endY;                         //结束高度(地面高度)
    private float timer;                        //运动消耗时间
    private Action<GameObject> finishCallBack;  //落地后的回调
    private bool canMove = false;               //能否运动

    private float timeScale = 1;                //时间系数
    private float reboundTimes = 1;             //反弹次数
    private bool isInRebound = false;           //是否在反弹中
    private float lastX;                        //落地点x
    private float lastZ;                        //落地点z
    private float hightestPointTime;            //到达最高点所用的时间
    private float hightestPointStayTime = 0.1f; //最高点减速范围的时间段

    void Update()
    {
        if (!canMove)
        {
            return;
        }

        //移动过程
        timer = timer + Time.deltaTime * timeScale;

        float xOffset = startSpeed * timer * cosValue * horizontalDir.x;
        float zOffset = startSpeed * timer * cosValue * horizontalDir.y;
        float yOffset = startSpeed * timer * sinValue + 0.5f * gravity * timer * timer;

        Vector3 endPos;
        if (!isInRebound) //非反弹过程
        {
            endPos = startPos + new Vector3(xOffset, yOffset, zOffset);
            if (Mathf.Abs(timer - hightestPointTime) < hightestPointStayTime)
            {
                timeScale = 0.5f;
            }
            else
            {
                timeScale = 1f;
            }
        }
        else //反弹过程
        {
            endPos = new Vector3(lastX, yOffset, lastZ);
        }

        //落地
        if (endPos.y < endY)
        {
            endPos.y = endY;

            reboundTimes = reboundTimes - 1;
            if (reboundTimes < 0) //移动结束
            {
                canMove = false;
            }
            else //落地反弹
            {
                gravity = gravityValue * 2;
                horizontalDir = Vector2.zero;
                startSpeed = startSpeed * 0.8f;
                sinValue = 1;
                cosValue = 0;
                timer = 0;

                isInRebound = true;
                lastX = endPos.x;
                lastZ = endPos.z;
            }
        }
        transform.position = endPos;

        //移动结束
        if (!canMove)
        {
            finishCallBack(gameObject);
            Destroy(this);
        }
    }

    public void StartMove(Vector2 horizontalDir, float startSpeed, float angle, float endY, Action<GameObject> finishCallBack)
    {
        gravity = gravityValue;
        this.horizontalDir = horizontalDir;
        this.startSpeed = startSpeed;
        sinValue = Mathf.Sin(Mathf.Deg2Rad * angle);
        cosValue = Mathf.Cos(Mathf.Deg2Rad * angle);
        startPos = transform.position;
        this.endY = endY;
        timer = 0;
        this.finishCallBack = finishCallBack;
        canMove = true;

        hightestPointTime = Mathf.Abs(startSpeed * sinValue / gravity);
    }
}
using UnityEngine;
using System.Collections.Generic;

public class TestThrow : MonoBehaviour {

    public GameObject testGo;
    private bool isDebug = false;
    private List<GameObject> drawGoList = new List<GameObject>();

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            //半径为1的方向圆
            float randomNum = Random.Range(0f, 1f);//[0, 1]
            float x = randomNum * 2 - 1;//[-1, 1]
            float z = Mathf.Sqrt(1 - x * x);
            if (Random.Range(0f, 1f) > 0.5f)
            {
                z = -z;
            }

            isDebug = true;
            ObliqueThrow obliqueThrow = testGo.AddComponent<ObliqueThrow>();
            obliqueThrow.StartMove(new Vector2(1, 0), 5f, 45f, 0f, (go) => {
                isDebug = false;
                Debug.Log("移动结束");
            });
        }
        else if(Input.GetKeyDown(KeyCode.W))
        {
            testGo.transform.position = new Vector3(0f, 5f, 0f);
            for (int i = 0; i < drawGoList.Count; i++)
            {
                Destroy(drawGoList[i]);
            }
            drawGoList.Clear();
        }

        if (isDebug)
        {
            GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            go.transform.position = testGo.transform.position;
            go.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            drawGoList.Add(go);
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值