【问题标题】:2D Projectile Trajectory Prediction(unity 2D)2D弹道预测(unity 2D)
【发布时间】:2020-04-09 15:57:23
【问题描述】:

使用 (unity 2019.3.7f1) 2d。 我有一个玩家使用回撤机制四处移动并且具有最大功率(例如在愤怒的小鸟中)。 我正在尝试绘制一条线(使用线渲染器),以显示玩家将要走的确切路径。我试图让线条曲线就像玩家的路径一样。到目前为止,我只设法以非常磨损的方式制作一条直线。 已知的变量是跳跃力和球员的位置,没有摩擦。我相信重力是一个常数(-9.81)。另外,我想要一个变量来控制线条的长度。而且,如果可能的话,这条线不会穿过物体,并且会像有一个对撞机一样工作。

// 编辑

这是我当前的代码。我更改了函数,所以它会返回列表的点,因为我希望能够在 Update() 中访问它,所以它只会在我按住鼠标按钮时绘制。

我的问题是轨迹线似乎没有弯曲,它成直角但它是直的。线条以正确的方向和角度绘制,但我最初的线条不弯曲问题保持不变。如果你能请回来给我一个答案,我将不胜感激。

enter code here

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

public class TrajectoryShower : MonoBehaviour
{
LineRenderer lr;
public int Points;


public GameObject Player;

private float collisionCheckRadius = 0.1f;

public float TimeOfSimulation;

private void Awake()
{
    lr = GetComponent<LineRenderer>();
    lr.startColor = Color.white;
}

// Update is called once per frame
void Update()
{
    if (Input.GetButton("Fire1"))
    {
        lr.positionCount = SimulateArc().Count;

        for (int a = 0; a < lr.positionCount;a++)
        {
            lr.SetPosition(a, SimulateArc()[a]);
        }
    }
    if (Input.GetButtonUp("Fire1"))
    {
        lr.positionCount = 0;
    }
}

private List<Vector2> SimulateArc()
{
    float simulateForDuration = TimeOfSimulation;
    float simulationStep = 0.1f;//Will add a point every 0.1 secs.

    int steps = (int)(simulateForDuration / simulationStep);
    List<Vector2> lineRendererPoints = new List<Vector2>();
    Vector2 calculatedPosition;
    Vector2 directionVector = Player.GetComponent<DragAndShoot>().Direction;// The direction it should go
    Vector2 launchPosition = transform.position;//Position where you launch from
    float launchSpeed = 5f;//The initial power applied on the player

    for (int i = 0; i < steps; ++i)
    {
        calculatedPosition = launchPosition + (directionVector * ( launchSpeed * i * simulationStep));
        //Calculate gravity
        calculatedPosition.y += Physics2D.gravity.y * (i * simulationStep);
        lineRendererPoints.Add(calculatedPosition);
        if (CheckForCollision(calculatedPosition))//if you hit something
        {
            break;//stop adding positions
        }

    }

    return lineRendererPoints;



}
private bool CheckForCollision(Vector2 position)
{
    Collider2D[] hits = Physics2D.OverlapCircleAll(position, collisionCheckRadius);
    if (hits.Length > 0)
    {
        for (int x = 0;x < hits.Length;x++)
        {
            if (hits[x].tag != "Player" && hits[x].tag != "Floor")
            {
                return true;
            }
        }

    }
    return false;
}

}

【问题讨论】:

    标签: c# unity3d game-physics physics prediction


    【解决方案1】:

    这基本上是 2 个向量的总和。

    您的初始位置 (x0, y0)、初始速度矢量 (x, y) 和重力矢量 (0, -9.81) 会随着时间相加。您可以构建一个函数,随着时间的推移为您提供位置:

    f(t) = (x0 + x*t, y0 + y*t - 9.81t²/2) 
    
    translating to Unity:
    
    Vector2 positionInTime(float time, Vector2 initialPosition, Vector2 initialSpeed){
        return initialPosition + 
               new Vector2(initialSpeed.x * t, initialSpeed.y * time - 4.905 * (time * time);
    }
    

    现在,选择一点增量时间,比如dt = 0.25

       Time |            Position
    0) 0.00 |  f(0.00) = (x0, y0)
    1) 0.25 |  f(0.25) = (x1, y1)
    2) 0.50 |  f(0.50) = (x2, y2)
    3) 0.75 |  f(0.75) = (x3, y3)
    4) 1.00 |  f(1.00) = (x4, y4)
       ...  |         ...
    

    随着时间的推移,您会遇到很多线交叉的点。选择一个时间间隔(比如 3 秒),评估 0 到 3 秒之间的所有点(使用f),然后让你的线渲染器一个一个地覆盖。

    线条渲染器具有宽度、随时间变化的宽度、颜色等属性。这取决于您。

    【讨论】:

    • 我已尝试实施您的答案,但我无法完全弄清楚。我对统一很陌生,不明白你写的方程式。您能否在真实脚本中添加更详细的脚本?谢谢。
    • 完成。这是一个简单的数学/物理函数,可帮助您找到对象随时间推移的位置。你说它像愤怒的小鸟一样工作。当你扔鸟时,有一个初始位置和一个初始速度,那么只有重力作用。这正是函数评估的内容。
    【解决方案2】:

    这是一种可视化的简单方法。

    要创建你的线,你需要一堆点。

    • 分数代表玩家在 X 时间后被开火后的位置。
    • 每个点的位置将是:DirectionVector * (发射速度 * time elapse) + (GravityDirection * time elapse^2)
    • 您可以通过模拟 X 持续时间并选择模拟步骤(每 X 时间计算一个点)提前决定预计算点的距离
    • 要在每次计算一个点时检测碰撞,您可以在该位置做一个小圆圈投射。如果遇到问题,您可以停止添加新点。
    private float collisionCheckRadius = 0.1f;
            private void SimulateArc()
            {
                float simulateForDuration = 5f;//simulate for 5 secs in the furture
                float simulationStep = 0.1f;//Will add a point every 0.1 secs.
    
                int steps = (int)(simulateForDuration/simulationStep);//50 in this example
                List<Vector2> lineRendererPoints = new List<Vector2>();
                Vector2 calculatedPosition;
                Vector2 directionVector = new Vector2(0.5f,0.5f);//You plug you own direction here this is just an example
                Vector2 launchPosition = Vector2.zero;//Position where you launch from
                float launchSpeed = 10f;//Example speed per secs.
    
                for(int i = 0; i < steps; ++i)
                {
                    calculatedPosition = launchPosition + ( directionVector * (launchSpeed * i * simulationStep));
                    //Calculate gravity
                    calculatedPosition.y += Physics2D.gravity.y * ( i * simulationStep) *  ( i * simulationStep);
                    lineRendererPoints.Add(calculatedPosition);
                    if(CheckForCollision(calculatedPosition))//if you hit something
                    {
                        break;//stop adding positions
                    }
                }
    
                //Assign all the positions to the line renderer.
            }
            private bool CheckForCollision(Vector2 position)
            {
                Collider2D[] hits = Physics2D.OverlapCircleAll(position, collisionCheckRadius);
                if(hits.Length > 0)
                {
                    //We hit something 
                    //check if its a wall or seomthing
                    //if its a valid hit then return true
                    return  true;
                }
                return false;
            }
    
    

    【讨论】:

    • 谢谢,这正是我想要的!只有一件事,有没有办法将方向向量更改为浮点类型的角度,因为我不知道方向。或者更好的是,如果我知道两点的位置,你知道如何找到方向吗? (我知道点击点和当前鼠标的位置)。回调机制基本上是从您的点击位置到当前鼠标位置画一条线,并增加力量,让玩家向另一个方向移动。哦,轨迹线似乎并没有弯曲。还是非常感谢
    • 您可以使用 (endPosition - startposition).normalize 获取方向。对于曲线,你可以玩你的重力(在很多 2d 游戏中,重力会增加很多以获得更好的感觉)。将 Physics2D.gravity.y 替换为您在检查器中设置的浮点数,以便更轻松地进行调整。
    • 是的,我弄清楚了方向,但无论重力大小(我什至尝试将其提高到 100),这条线都不会弯曲,我认为方程可能不正确。我将当前代码添加到原始问题中,可能是其他问题,但“calculatedPosition”方程可能有问题。
    • 我非常需要计算重力时间:P。我编辑了上面的代码。
    猜你喜欢
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多