ボールが飛ぶ距離を先に計算してだしたかった(妥協あり)

角度 \(\theta\) 、速度 \(v\) で投げ上げた場合を考える。




参考より、空気抵抗をkとして、Unityでの空気抵抗は以下のように計算されているらしいので、

\[v = v * (1 - k*dt); \]

※ 引用元のfはfloatなので省略、\(k\) が空気抵抗(UnityでのDrag)


調査した結果、Unity上で \(dt\) は「Project Settings」「Time」「Fixed Timestep」であった。
物理演算は「Fixed Timestep」ごとに行われ、\(n\) 回かかるものとする。
速度は、前の速度から \(1-kdt\) をかけた等比数列なので、速度の一般項 \(v_{xn}\)は
\[v_{xn} = v_{x0} (1 - kdt)^{n} \]
そして位置\(x_1\)を計測したところ、Unity上では\(v_{x0}\)ではなく、\(v_{x1}\)から使われていた。
\(x_0 = 0\) 、
\(x_1 = v_{x1} dt + x_0\)、
\(x_2 = v_{x2} dt + x_1 \ldots\)
よって位置の一般項 \(x_n\) \(\left(n \geq 1\right)\)は、
\begin{eqnarray} x_n &=& v_{xn} dt + x_{n-1} \\ &=& v_{xn} dt + v_{xn-1} dt + v_{xn-2} dt \ldots \\ &=& \left(v_{xn} + v_{xn-1} + v_{xn-2} \ldots + v_{x1} \right) dt \\ &=& dt\sum_{i=1}^{n}v_{xi} \\ \end{eqnarray}
初項 \(a = v_1\)、公比 \(r = 1-kdt\) の等比数列の和より、
\begin{eqnarray} x_n &=& v_{x1}dt\frac{1- {\left(1 - kdt \right)}^n}{1 - (1 - kdt)} \\ &=& v_{x1}dt\frac{1- {\left(1 - kdt \right)}^n}{1 - 1 + kdt} \\ &=& v_{x1}dt\frac{1- {\left(1 - kdt \right)}^n}{kdt} \\ &=& v_{x1}\frac{1- {\left(1 - kdt \right)}^n}{k} \tag{x}\label{x} \\ \end{eqnarray}

速度\(v_y\)を計測したところ、Unity上での式は以下のようになっていた。
\[v_{y} = \left(v_y + g * dt \right) * \left(1 - k*dt \right); \]
\(v_x\)と違い、一般項が複雑になるので求めると、
\begin{eqnarray} v_{y2} &=& \left(v_{y1} + gdt \right)\left(1 - kdt \right) \\ &=& v_{y1}\left(1 - kdt \right) + gdt \left(1 - kdt \right) \\ &=& \left(v_{y0} + gdt \right)\left(1 - kdt \right) \left(1 - kdt \right) + gdt \left(1 - kdt \right) \\ &=& \left(v_{y0} + gdt \right)\left(1 - kdt \right)^2 + gdt \left(1 - kdt \right) \\ &=& v_{y0}\left(1 - kdt \right)^2 + gdt\left(1 - kdt \right)^2 + gdt \left(1 - kdt \right) \\ &=& v_{y0}\left(1 - kdt \right)^2 + gdt\left( \left(1 - kdt \right)^2 + \left(1 - kdt \right) + \ldots \right) \\ &=& v_{y0}\left(1 - kdt \right)^2 + gdt\sum_{i=1}^{2} \left(1 - kdt \right)^i \\ \end{eqnarray}
\(\sum\)の部分は初項 \(a = 1-kdt\)、公比 \(r = 1-kdt\) の等比数列の和より、
\begin{eqnarray} v_{y2} &=& v_{y0}\left(1 - kdt \right)^2 + gdt\left(1-kdt\right) \frac{1-\left(1-kdt\right)^2}{1-\left(1-kdt\right)} \\ &=& v_{y0}\left(1 - kdt \right)^2 + gdt\left(1-kdt\right) \frac{1-\left(1-kdt\right)^2}{1-1+kdt} \\ &=& v_{y0}\left(1 - kdt \right)^2 + gdt\left(1-kdt\right) \frac{1-\left(1-kdt\right)^2}{kdt} \\ &=& v_{y0}\left(1 - kdt \right)^2 + g\left(1-kdt\right) \frac{1-\left(1-kdt\right)^2}{k} \\ &=& v_{y0}\left(1 - kdt \right)^2 + \frac{g\left(1-kdt\right)}{k} - \frac{g\left(1-kdt\right)\left(1-kdt\right)^2}{k} \\ &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right)^2 + \frac{g\left(1-kdt\right)}{k} \\ \end{eqnarray}
よって速度の一般項 \(v_{yn}\) は、
\[v_{yn} = \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right)^n + \frac{g\left(1-kdt\right)}{k} \]
位置の一般項\(y_n\) \(\left(n \geq 1\right)\)も、 \(x_n\)と同様に \(\displaystyle dt\sum_{i=1}^{n}v_i\) なので、
\begin{eqnarray} y_n &=& dt\sum_{i=1}^{n}v_{yi} \\ &=& dt\sum_{i=1}^{n} \left( \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right)^n + \frac{g\left(1-kdt\right)}{k} \right) \\ &=& dt\left( \sum_{i=1}^{n}\left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right)^n + \sum_{i=1}^{n}\frac{g\left(1-kdt\right)}{k} \right) \\ \end{eqnarray}
初項 \(a = \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right)\)、公比 \(r = 1-kdt\) の等比数列の和より、
\begin{eqnarray} y_n &=& dt\left( \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right) \frac{1-\left(1-kdt\right)^n}{1- \left(1-kdt\right)} + \frac{ng\left(1 - kdt\right)}{k} \right) \\ y_n &=& dt\left( \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right) \frac{1-\left(1-kdt\right)^n}{kdt} + \frac{ng\left(1 - kdt\right)}{k} \right) \\ y_n &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right) \frac{1-\left(1-kdt\right)^n}{k} + \frac{ngdt\left(1 - kdt\right)}{k} \\ \end{eqnarray}

ここから距離を求めたいので、\(y_0 \neq 0 \) から、 \(y = 0 \) となる\(x \) を求める。
※Unityで確認したところ、\(1 - kdt = 0 \)の場合は空気抵抗が釣り合ってしまい、ボールが動かなかったので、\(1 - kdt \neq 0 \)とする
\begin{eqnarray} 0 &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \left(1 - kdt \right) \frac{1-\left(1-kdt\right)^n}{k} + \frac{ngdt\left(1 - kdt\right)}{k} + y_0 \\ 0 &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{1-\left(1-kdt\right)^n}{k} + \frac{ngdt}{k} + \frac{y_0}{1 - kdt} \\ \end{eqnarray}
\eqref{x}より、\( \frac{x_n}{v_{x1}} = \frac{1-\left(1-kdt\right)^n}{k} \) なので、
\begin{eqnarray} 0 &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{x_n}{v_{x1}} + \frac{ngdt}{k} + \frac{y_0}{1 - kdt} \\ \end{eqnarray}
\eqref{x}より、
\begin{eqnarray} x_n &=& v_{x1}\frac{1- {\left(1 - kdt \right)}^n}{k} \\ \frac{kx_n}{v_{x1}} &=& 1- \left(1 - kdt \right)^n \\ \frac{kx_n}{v_{x1}} - 1 &=& - \left(1 - kdt \right)^n \\ 1 - \frac{kx_n}{v_{x1}} &=& \left(1 - kdt \right)^n \\ \log_{\left(1 - kdt \right)}\left(1 - \frac{kx_n}{v_{x1}}\right) &=& n \\ n &=& \log_{\left(1 - kdt \right)}\left(1 - \frac{kx_n}{v_{x1}}\right) \\ \end{eqnarray}
よって、
\begin{eqnarray} 0 &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{x_n}{v_{x1}} + \frac{gdt}{k} \log_{\left(1 - kdt \right)}\left(1 - \frac{kx_n}{v_{x1}} \right) + \frac{y_0}{1 - kdt} \\ \end{eqnarray}
\(v_{x1} = v_{x0}(1 - kdt) \) より、
\begin{eqnarray} 0 &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{x_n}{v_{x0}(1 - kdt)} + \frac{gdt}{k} \log_{\left(1 - kdt \right)}\left(1 - \frac{kx_n}{v_{x0}(1 - kdt)}\right) + \frac{y_0}{1 - kdt} \\ 0 &=& \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{kx_n}{gdtv_{x0}(1 - kdt)} + \log_{\left(1 - kdt \right)}\left(1 - \frac{kx_n}{v_{x0}(1 - kdt)}\right) + \frac{ky_0}{gdt\left(1 - kdt\right)} \\ \left(1-kdt \right)^0 &=& \left(1-kdt \right)^{\left( \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{kx_n}{gdtv_{x0}(1 - kdt)} + \log_{\left(1 - kdt \right)}\left(1 - \frac{kx_n}{v_{x0}(1 - kdt)}\right) + \frac{ky_0}{gdt\left(1 - kdt\right)} \right)} \\ 1 &=& \left(1-kdt \right)^{ \log_{\left(1 - kdt \right)}\left(1 - \frac{kx_n}{v_{x0}(1 - kdt)}\right) } \left(1-kdt \right)^{\left( \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{kx_n}{gdtv_{x0}(1 - kdt)} + \frac{ky_0}{gdt\left(1 - kdt\right)} \right)} \\ 1 &=& \left(1 - \frac{kx_n}{v_{x0}(1 - kdt)}\right) \left(1-kdt \right)^{\left( \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{kx_n}{gdtv_{x0}(1 - kdt)} + \frac{ky_0}{gdt\left(1 - kdt\right)} \right)} \\ 0 &=& -1 + \left(1 - \frac{kx_n}{v_{x0}(1 - kdt)}\right) \left(1-kdt \right)^{\left( \left(v_{y0} - \frac{g\left(1-kdt\right)}{k} \right) \frac{kx_n}{gdtv_{x0}(1 - kdt)} + \frac{ky_0}{gdt\left(1 - kdt\right)} \right)} \\ \end{eqnarray}
これを解けば飛距離\(x_n \) をだせるが、どうやらこの式は解けないようなので、近似値を求めることにした。 既存のライブラリ で対処したかったが、式のグラフの形が想定されていないのか、\(v_0 \)が400ほどですでに解がだせなかったので、 禁断の自作実装で対処した。

飛距離の最低値は当然0であり、最大値は\eqref{x}の\(n = \infty \)で求められるので、
\begin{eqnarray} x_{max} &=& v_{x1}\frac{1- {\left(1 - kdt \right)}^\infty}{k} \\ \end{eqnarray}
\(1-kdt \lt 1 \)より、
\begin{eqnarray} x_{max} &=& v_{x1}\frac{1- \frac{1}{\infty}}{k} \\ x_{max} &=& v_{x1}\frac{1- 0}{k} \\ x_{max} &=& \frac{v_{x1}}{k} \\ x_{max} &=& \frac{v_{x0}(1 - kdt)}{k} \\ \end{eqnarray}

飛距離の計算を実現するクラスは以下の通り。
 ※2025/3/6追記 lowerBoundがupperBound/2だと解が含まれない場合があったので、0に修正

残念ながら飛距離はUnity上でも正確に測れないためか、それとも浮動小数点の計算誤差なのか、値が大きくなると精度の範囲を超えた誤差がでる。(以下の図は精度0.1を指定している)

 

しかし、これ以上精度をよくする方法が思いつかないため、ここで妥協する。

最大値がかなり飛距離に近い値なので、これを上手く活用して計算できそうだが、不明。

コメント