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);
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity Mega-Fiers是一款强大的Unity插件,它为开发者提供了许多功能和工具,以帮助他们创建优秀的游戏体验。 首先,Unity Mega-Fiers具有强大的形变功能。开发者可以通过该插件实现各种形状的变换,包括弯曲、挤压、拉伸等。这为游戏中的人物、物体和环境提供了更多的自由度和个性化选项,使其更具动态和真实感。 其次,Unity Mega-Fiers还提供了高度的粒子系统控制能力。开发者可以使用该插件来创建更加逼真的粒子效果,并具有更准确的控制。这包括粒子的大小、颜色、速度等方面,使游戏中的特效更加出色。 另外,Unity Mega-Fiers还支持可编程网格。这意味着开发者可以通过脚本来控制网格的生成和变形,从而实现各种复杂的效果。无论是地形生成、水体模拟还是其他物体的变形,都可以通过该插件实现,并使游戏更加逼真和具有个性化。 除了以上功能,Unity Mega-Fiers还提供了其他诸多辅助工具,如动画控制、特效编辑等,为开发者提供了更丰富的开发选项和提升游戏质量的手段。 总结而言,Unity Mega-Fiers是一款功能强大的Unity插件,为开发者提供了丰富的形变、粒子系统控制和可编程网格等功能。它能够大幅提升游戏的真实感和品质,并为开发者提供更多的创作空间和个性化选项。无论是初学者还是有经验的开发者,都能够从中受益,并创造出出色的游戏作品。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值