Предсказание Траектории Снаряда 2D (Unity 2D) - PullRequest
0 голосов
/ 09 апреля 2020

с использованием (единство 2019.3.7f1) 2d. У меня есть игрок, который передвигается с использованием откатного механизма c и имеет максимальную мощность (как в Angry Birds). Я пытаюсь нарисовать линию (используя средство визуализации линий), которая показывает точный путь, по которому игрок будет go. Я пытаюсь изогнуть линию так же, как путь игрока. до сих пор мне удалось сделать прямую линию довольно потертым способом. Известные переменные - сила прыжка и позиция игрока, трения нет. и я считаю, что гравитация постоянна (-9,81). Кроме того, я хотел бы иметь переменную, которая позволяет мне контролировать длину строки. И, если возможно, линия не будет проходить сквозь объекты и будет действовать так, как если бы она имела коллайдер.

// Редактировать

Это мой текущий код. Я изменил функцию так, чтобы она возвращала точки списка, потому что я хотел иметь возможность доступа к нему в Update (), чтобы он рисовал только тогда, когда я держу кнопку мыши.

Моя проблема в том, что линия траектории не не похоже на изгиб, он идет под прямым углом, но это прямо. линия dr aws в правильном направлении и под углом, но моя первоначальная проблема не искривления линии остается неизменной. Если бы вы могли вернуться ко мне с ответом, я был бы признателен.

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 ]

1 голос
/ 09 апреля 2020

Это в основном сумма 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) и поместите средство визуализации строк на одно за другим.

Средство визуализации линий имеет такие свойства, как ширина, ширина со временем, цвет и т. д. c. Это зависит от вас.

0 голосов
/ 09 апреля 2020

Вот простой способ визуализировать это.

Чтобы создать свою линию, вам нужно множество точек.

  • Точки представляют позиции игрока после выстрела через X раз.
  • Положение каждой точки будет следующим: DirectionVector * (скорость запуска * истечение времени) + (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;
        }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...