Physics - Projectile

[TOC]

등가속도

\[\begin{gather*} \begin{array}{ c c c } t & : & 경과\ 시간\\ a & : & 가속도\\ v_{0} & : & 처음\ 속도\\ v & : & 나중\ 속도 \end{array}\\ a=\frac{v-v_{0}}{t} \end{gather*}\]

속도

\[\begin{gather*} \begin{array}{ c c c } t & : & 경과\ 시간\\ a & : & 가속도\\ v_{0} & : & 처음\ 속도\\ v & : & 나중\ 속도 \end{array}\\ v=v_{0} +at \end{gather*}\]

물체의 변위(이동 거리)

0t \[\begin{gather*} \begin{array}{ c c c } s & : & 변위 \end{array}\\ s=v_{0} t+\frac{1}{2} at^{2} \end{gather*}\]

시간이 주어지지 않았을 때 물체의 변위

\[\begin{gather*} v=v_{0} +at를\ t로\ 정리\\ t=\frac{v-v_{0}}{a}\\ \\ 물체의\ 변위식의\ t에\ 대입\\ \begin{array}{ c c c } s & = & v_{0} t+\frac{1}{2} at^{2}\\ & = & v_{0}\left(\frac{v-v_{0}}{a}\right) +\frac{1}{2} a\left(\frac{v-v_{0}}{a}\right)^{2}\\ & = & \frac{vv_{0} -v^{2}_{0}}{a} +\frac{v^{2} -2vv_{0} +v^{2}_{0}}{2a}\\ & = & \frac{2vv_{0} -2v^{2}_{0} +v^{2} -2vv_{0} +v^{2}_{0}}{2a}\\ & = & \frac{v^{2} -v^{2}_{0}}{2a} \end{array}\\ \\ \therefore 2as=v^{2} -v^{2}_{0} \end{gather*}\]

포물선 운동

최고점높이 : 수평 도달 거리 \[\begin{equation*} \begin{array}{ c c c } t & : & 경과\ 시간\\ a & : & 가속도\\ g & : & 중력\ 가속도\\ \theta & : & 초기\ 각도\\ v_{x} & : & 나중\ x축\ 속도\\ v_{y} & : & 나중\ y축\ 속도\\ h & : & 최고점\ 높이\\ r & : & 수평\ 도달\ 거리 \end{array} \end{equation*}\]

포물선 - t초 후 속도

\[\begin{equation*} \begin{array}{ c c c } v_{x} & = & v_{0}\cos \theta \ ( 수평은\ 등속운동)\\ v_{y} & = & v_{0}\sin \theta -gt \end{array} \end{equation*}\]

포물선 - t초 후 위치

\[\begin{equation*} \begin{array}{ c c c } x & = & v_{0}\cos \theta \times t\\ y & = & v_{0}\sin \theta \times t-\frac{1}{2} gt^{2} \end{array} \end{equation*}\]

포물선 - 최고점 높이

\[\begin{gather*} 최고점에서\ y속도가\ 0이\ 되는\ 것을\ 이용\\ \\ \begin{array}{ c c c c } 2as & = & v^{2} -v^{2}_{0} & \\ -2gs & = & 0-v^{2}_{0} & ( g는\ 반대방향이므로\ -,\ 최고점\ 속력은\ 0)\\ 2gs & = & v^{2}_{0} & \\ 2gs & = & v^{2}_{0y} & ( y의\ 변위를\ 구하므로\ v_{0y} 로\ 변경)\\ 2gs & = & ( v_{0}\sin \theta )^{2} & \\ s & = & \frac{( v_{0}\sin \theta )^{2}}{2g} & \\ s & = & \frac{v^{2}_{0}\sin^{2} \theta }{2g} & \end{array}\\ \therefore h( 최고점\ 높이) =\frac{v^{2}_{0}\sin^{2} \theta }{2g} \end{gather*}\]

포물선 - 최고점 도달 시간

최고점에서 y속도는 0, 등가속도는 중력가속도 g를 시간을 구하는 공식에 대입

\[\begin{gather*} \begin{array}{ c c c c } t & = & \frac{v-v_{0}}{a} & \\ & = & \frac{0-v_{0}}{g} & \\ & = & \frac{v_{0}\sin \theta }{g} & ( y축에\ 대한\ 식으로\ 변경) \end{array}\\ \therefore h_{t}( 최고점\ 도달\ 시간) =\frac{v_{0}\sin \theta }{g} \end{gather*}\]

포물선 - 수평 도달 거리

이동 거리 공식에 최고점 도달시간 공식의 2배를 대입

(땅에 떨어질 때까지의 시간은 최고점 도달 시간의 2배)

\[\begin{gather*} \begin{array}{ c c c c } s & = & vt & ( 이동거리\ 공식)\\ & = & v_{0}\cos \theta \times t & ( x에\ 대한\ 식으로\ 변경)\\ & = & v_{0}\cos \theta \times \left( 2\times \frac{v_{0}\sin \theta }{g}\right) & ( 최고점\ 도달시간\ 공식\ 대입)\\ & = & \frac{v_{0}\cos \theta \times 2v_{0}\sin \theta }{g} & \\ & = & \frac{v^{2}_{0} \times 2\cos \theta \sin \theta }{g} & \\ & = & \frac{v^{2}_{0} \times \sin 2\theta }{g} & (\sin 2\theta =2\cos \theta \sin \theta ) \end{array}\\ \therefore r( 수평\ 도달\ 거리) =\frac{v^{2}_{0} \times \sin 2\theta }{g} \end{gather*}\]

포물선 - 경로 방정식

처음 속도와 발사 각도 및 x값을 아는 경우 y값을 계산할 수 있다.

x의 변위식을 y의 변위식에 대입하여 방정식 도출

\[\begin{gather*} \begin{array}{ c c c c } s & = & v_{0} t-\frac{1}{2} gt^{2} & ( 거리\ 기본식)\\ x & = & v_{0}\cos \theta t & \\ y & = & v_{0}\sin \theta t-\frac{1}{2} gt^{2} & \end{array}\\ \\ x식을\ t에\ 대해\ 정리\ 후\ y식에\ 대입\\ \\ \begin{array}{ c c c c } t & = & \frac{x}{v_{0}\cos \theta } & \\ y & = & v_{0}\sin \theta \frac{x}{v_{0}\cos \theta } -\frac{1}{2} g\left(\frac{x}{v_{0}\cos \theta }\right)^{2} & ( t를\ 대입)\\ & = & \frac{v_{0}\sin \theta }{v_{0}\cos \theta } x-\frac{1}{2} g\frac{x^{2}}{v^{2}_{0}\cos^{2} \theta } & \\ & = & \tan \theta x-\frac{g}{2v^{2}_{0}\cos^{2} \theta } x^{2} & \left(\frac{\sin \theta }{\cos \theta } =\tan \theta \right) \end{array} \end{gather*}\]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ProjectileMotionTest : MonoBehaviour
{
    [Range(0, 360)]
    public float Angle;
    public float Velocity;
    public float Gravity = 9.8f;

    public float XRange = 10f;
    public float DrawLineResolution = 50;
    
    private void OnDrawGizmos()
    {
        // 각도와 속도 그리기
        float radian = Angle * Mathf.Deg2Rad;
        Gizmos.color = Color.blue;
        Gizmos.DrawLine(transform.position, transform.position + new Vector3(Velocity * Mathf.Cos(radian), Velocity * Mathf.Sin(radian), 0));

        // 포물선 그리기
        Gizmos.color = Color.red;
        float xUnit = XRange / DrawLineResolution;
        Vector3 prevPosition = transform.position;
        for (int i = 0; i < DrawLineResolution; i++)
        {
            float x = xUnit * i;
            float y = GetProjectileMotionY(x);
            Vector3 curPosition = transform.position + new Vector3(x, y, 0);

            Gizmos.DrawLine(prevPosition, curPosition);

            prevPosition = curPosition;
        }
    }

    private float GetProjectileMotionY(float x)
    {
        float radian = Angle * Mathf.Deg2Rad;
        float y = Mathf.Tan(radian) * x;
        y -= Gravity / (2 * Velocity * Velocity * Mathf.Cos(radian) * Mathf.Cos(radian)) * (x * x);
        return y;
    }
}

포물선 - (역)경로 방정식

최고점 높이(h), 최고점 도달 시간(ht), 마지막 위치(y) 및 경과 시간(t)을 아는 경우 y값을 계산할 수 있다.

1. g(등가속도)값 구하기

최고점에서 지면으로 떨어질 때 최초 속도는 0이고 이동 거리(최고점 높이), 도달 시간을 알고 있으므로 기본공식을 이용하여 g값을 계산할 수 있다.

최고점에서 떨어지는 운동은 중력가속도에 의해 가속되는 운동이므로 등가속도값 빼지 않고 더해준다.

\[\begin{equation*} \begin{array}{ c c c c } y & = & v_{0}\sin \theta \times t+\frac{1}{2} gt^{2} & \\ h & = & 0\times \sin \theta \times t+\frac{1}{2} gt^{2} & \\ & = & \frac{1}{2} gt^{2} & \\ g & = & \frac{2h}{t^{2}} & \end{array} \end{equation*}\]

2. y의 초기 속도(vy) 구하기

g값을 구했으니 최고점 높이 구하는 공식을 이용해 y의 초기 속도를 계산한다.

\[\begin{equation*} \begin{array}{ c c c } h & = & \frac{v^{2}_{0}\sin^{2} \theta }{2g}\\ & = & \frac{v^{2}_{y}}{2g}\\ v^{2}_{y} & = & 2hg\\ v_{y} & = & \sqrt{2hg} \end{array} \end{equation*}\]

3. 마지막 위치(y)까지 이동 시간(t) 구하기

기본 이동 공식에 알고 있는 값을 대입하면 미지수가 t만 남는데 이는 근의 공식을 사용하여 계산해 낸다.

\[\begin{gather*} y=v_{y} t-\frac{1}{2} gt^{2}\\ \begin{array}{ c c c } -\frac{1}{2} gt^{2} +v_{y} t-y & = & 0\\ gt^{2} -2v_{y} t+2y & = & 0 \end{array}\\ \\ x=\frac{-b+\sqrt{b^{2} -4ac}}{2a}( 근의\ 공식)\\ \\ \begin{array}{ c c c } a & = & g\\ b & = & -2v_{y}\\ c & = & 2y \end{array}\\ \\ \therefore t=\frac{2v_{y} +\sqrt{( -2v_{y})^{2} -8gy}}{2g} \end{gather*}\]

4. x의 초기속도(vx) 구하기

\[\begin{gather*} x( 마지막\ 위치) =v_{x} \times t\\ v_{x} =\frac{x}{t} \end{gather*}\]

5. 경과 시간값을 변화시키며 좌표얻기

t초 후 위치 계산 식에 t값을 변화시키며 좌표를 얻는다.

\[\begin{equation*} \begin{array}{ c c c } x & = & v_{x} t\\ y & = & v_{y} t-\frac{1}{2} gt^{2} \end{array} \end{equation*}\]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class ParabolaAlgorithm
{
    public float HeightLimit { get; private set; }
    public float TimeToTopmostHeight { get; private set; }
    public float TimeToEndPosition { get; private set; }

    private Vector3 _startPosition;
    private Vector3 _endPosition;

    private float _vx;
    private float _vy;
    private float _gravity;

    public Vector3 GetPosition(float elasedTime)
    {
        float x = _vx * elasedTime;
        float y = (_vy * elasedTime) - (0.5f * _gravity * elasedTime * elasedTime);

        return new Vector3(_startPosition.x + x, _startPosition.y + y, 0f);
    }

    public void Init(float heightLimit, float timeToTopmostHeight, Vector3 startPosition, Vector3 endPosition)
    {
        this.HeightLimit = heightLimit;
        this.TimeToTopmostHeight = timeToTopmostHeight;

        _startPosition = startPosition;
        _endPosition = endPosition;

        CalcParabolaTrack();
    }

    private void CalcParabolaTrack()
    {
        float endHeight = _endPosition.y - _startPosition.y;
        float height = HeightLimit;
        //float height = MaxHeight - transform.position.y;
        _gravity = 2 * height / (TimeToTopmostHeight * TimeToTopmostHeight);

        _vy = Mathf.Sqrt(2 * _gravity * height);

        float a = _gravity;
        float b = -2 * _vy;
        float c = 2 * endHeight;

        TimeToEndPosition = (-b + Mathf.Sqrt(b * b - 4 * a * c)) / (2 * a);

        //Debug.Log(TimeToEndPosition.ToString("#.###"));

        _vx = (_endPosition.x - _startPosition.x) / TimeToEndPosition;
    }
} 

참고

http://blog.naver.com/PostView.nhn?blogId=whwodud98&logNo=50103673919

https://www.slideshare.net/semin204/ss-16331290

https://robatokim.tistory.com/entry/%EA%B2%8C%EC%9E%84%EC%88%98%ED%95%99-%EC%97%AD%ED%83%84%EB%8F%84%EA%B3%84%EC%82%B0%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EB%91%90%EC%A0%90-%EC%82%AC%EC%9D%98-%ED%8F%AC%EB%AC%BC%EC%84%A0-%EA%B5%AC%ED%95%98%EA%B8%B0

https://0mind.tistory.com/entry/%ED%8F%AC%EB%AC%BC%EC%84%A0%EC%9A%B4%EB%8F%99-%EA%B3%B5%EC%8B%9D