unity画线之模拟小球抛物线运动轨迹

模拟小球的抛物线运动,如图所示:
这里写图片描述
这里有点像打台球游戏,模拟在发射之前模拟其轨迹。
划线用的是LineRenderer,不清楚的童鞋可以自行查阅咯。其实也很简单就是挂个LineRenderer脚本,设置它的坐标点就行了,关键是这坐标点如何计算的问题了。
高中物理知识,科普一波 首先位移公式,S = V0t+1/2at^2。此次位移的分解,物体在Y轴方向做加速度为重力加速度g的加速运动,在X轴方向匀速运动。则物体在X轴的位移为:Sx=Vxt ,Y轴位移Sy = Vyt+1/2gt^2。
知道公式之后,我们就可以按时间点计算物体的位移了,而unity中都是用坐标表示那么这种公式转换为代码的逻辑就更加简单了:

int posCount = 50;
List<Vector3> posList = new List<Vector3>();
for (int i = 1; i < posCount ; i++)
    {
        float x = Vec0.x * deltaTime*i;
        float y = 1f / 2f * Physics.gravity.y * Mathf.Pow(deltaTime, 2) + Vec0.y * deltaTime*i;
        posList.Add(oldPos + new Vector2(x, y));
    }

这样就计算了出来了50个点,将这50个点全部赋值给LineRenderer就基本模拟完成了。

 public void SetPoint(List<Vector2> posList)
    {
        lineRenderer.positionCount = posList.Count;
        for (int i = 0; i < posList.Count; i++)
        {
            lineRenderer.SetPosition(i, posList[i]);
        }
    }

为什么要说基本完成呢,这种模拟只是模拟球的最开始的轨迹,在游戏中球会发生碰撞,碰撞之后会反弹,那么这种反弹的轨迹如何实现呢?如图:
这里写图片描述
首先要知道球在什么时候发生碰撞,碰撞的面法向量是啥?如果知道面的法向量,入射角那么就可以求出线的反射角了。如何知道在什么时候发生碰撞呢?
这里我用的方法是计算每一段时间球的位移,将这一段时间的位移看作是直线,然后利用unity提供的射线来检测是否碰撞,这种方法由于每一段是直线所以检测出来碰撞值也是近似值,当然也没有考虑球碰撞时的摩擦力对球的影响,总之算是一个粗略的解决方法,如果大家有什么更好的方法,希望评论告知,在下感激不尽,首先抛砖迎玉,实现的具体代码如下:

  public List<Vector2> CalculateTrajectory(Vector2 startVel)
    {
        List<Vector2> posList = new List<Vector2>();

        Vector2 curPos = Vector2.zero;
        Vector2 changePos = Vector2.zero;

    float detlaTime =0.01f;
        Vector2 vel0 = startVel;
        Vector2 nextPos = Vector2.zero;
        int timeCount = 0;
        Vector2 direction = startVel.normalized; //速度的实时方向

        for (int i = 0; i < 100; i++)
        {
            //总的时间
            float time = detlaTime * timeCount;

            float x = vel0.x * time;
            float y = 1f / 2f * Physics.gravity.y * Mathf.Pow(time, 2) + vel0.y * time;
            nextPos = changePos + new Vector2(x, y);

            // Ray ray = new Ray(curPos + (Vector2)OriginalPos, curSpeedVec);
            direction = new Vector2(vel0.x, Physics.gravity.y * time + vel0.y).normalized;
            RaycastHit hit;
            if (Physics.SphereCast(curPos + (Vector2)OriginalPos, ballCollider.radius, direction, out hit, Vector2.Distance(curPos, nextPos), ~LayerMask.GetMask("Ball")))
            {
                Vector2 N = hit.normal;
                changePos = nextPos;// hit.point - OriginalPos + hit.normal * ballCollider.radius;

                vel0 = new Vector2(vel0.x, Physics.gravity.y * time + vel0.y);

                vel0 = vel0 - 2 * (Vector2.Dot(vel0, N)) * N;//改变初始度
                timeCount = 0;
            }
            timeCount++;
            posList.Add(curPos + (Vector2)OriginalPos);
            curPos = nextPos;
        }
        return posList;
    }

猜你喜欢

转载自blog.csdn.net/qwsx789/article/details/80678294