簡體   English   中英

2D彈道預測(unity 2D)

[英]2D Projectile Trajectory Prediction(unity 2D)

使用(統一 2019.3.7f1)2d。 我有一個玩家使用回撤機制四處移動並且具有最大功率(例如在憤怒的小鳥中)。 我正在嘗試繪制一條線(使用線渲染器),以顯示玩家將 go 的確切路徑。 我試圖讓線條曲線就像玩家的路徑一樣。 到目前為止,我只設法以一種非常磨損的方式制作一條直線。 已知變量為 Jump Power 和玩家的 position,沒有摩擦。 我相信重力是一個常數(-9.81)。 另外,我想要一個變量來控制線條的長度。 而且,如果可能的話,這條線不會 go 穿過物體,而是會像有一個對撞機一樣工作。

// 編輯

這是我當前的代碼。 我更改了 function 所以它會返回列表的點,因為我希望能夠在 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;
}

}

這基本上是 2 個向量的總和。

您會同時添加初始 position (x0, y0)、初始速度矢量 (x, y) 和重力矢量 (0, -9.81)。 您可以構建一個 function,隨着時間的推移為您提供 position:

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 ),然后讓你的線渲染器一個接一個地覆蓋。

線渲染器具有寬度、隨時間變化的寬度、顏色等屬性。這取決於您。

這是一種可視化的簡單方法。

要創建你的線,你需要一堆點。

  • 這些點代表玩家在 X 時間后被解雇后的位置。
  • 每個點的 position 將是: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;
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM