[Unity][RoboCup] CrossView開発日記 #3

# CrossViewとは
こちらの記事をご覧ください。

https://qiita.com/suzuki_nene/items/cbdb701622a738f1b2ee

# いよいよ
[前回](https://qiita.com/suzuki_nene/items/8e3f6f5c83c1cdda5687)までで、RoboCupのログファイルを再生する際に必要な「ボールの移動」とか「プレーヤーのKickアニメーション」だとかは、実装方法を確認することができました。

# Football_3
次は、いよいよ「ログファイルを読み込んで、定期タイマーを利用してシミュレーションを再生」する段階です。

具体的には、
- ログファイルを指定する。（どんな指定方法を採用するか？）
- ログファイルを読み込む。（どうやってファイルを入手するか？）
- ログファイルのパース処理。（内容を解釈して、再生用の内部データを構築する）
- タイマー実行。（定期タイマーを開始して、内部データに従い、ボールやプレーヤーを操作する）
といった感じです。

## ログファイルを指定する
RoboCupの開発者の方々は、公式戦だけでなく開発中にも試合のログを記録して、自分のAgentプログラムが想定通り動作してくれているか、確認するのだと思われます。

そのような時に本アプリを活用してもらうことを考えるのであれば、
- ローカルPC上に保存されたログファイルを、読み込ませる。

といった利用方法が、まずは考えられます。

また、RoboCup開発者以外の人にも本アプリで楽しんでもらいたいので、
- 公式アーカイブのサイトからログファイルをダウンロードして、読み込ませる。

という方法も用意したいと考えました。

そうすると、
- 前者の場合は、いわゆる「ファイル選択ダイアログ」が必要になります。
- 後者の場合は、公式アーカイブサイトを参照して「URLを入手する」必要があります。

まず、前者を実現するために以下のOSSを採用することにしました。

https://github.com/gkngkc/UnityStandaloneFileBrowser

ちなみに、将来的にiOSやAndroidのタブレット上でも動作させられたらなぁ、と考えています。その場合は、次のOSSの導入が選択肢として考えられます。

https://github.com/keiwando/nativefileso

次に、後者の方は、自分でURLの文字列をキー入力するか、ブラウザなどからURLの文字列をCopy＆Pasteすることで実現することにします。

## ログファイルを読み込む
UnityWebRequestクラスを使うと、ローカルファイルもWeb上のファイルも、どちらも読み込み可能であることがわかりましたので、これを採用することにしました。

https://docs.unity3d.com/ja/2020.3/Manual/UnityWebRequest.html

読み込むログファイルのURIとして、ローカルファイルなら"file://C:\～"のように、Web上のURLであれば"https：//～"といった感じで指定します。

また、RoboCupのログファイルは、テキストベースであることもあってか、だいたい１ファイルあたり「20MB」近くあります。

なので、ファイル全体をメモリに読み込んでから内容をパースしようとすると、大きなメモリ領域を消費することになります。
タブレットのようなモバイル系デバイスでも動かすことを考えるならば、なるべくメモリを使わない実装方法にしたいところです。

そこで、DownloadHandlerScriptの派生クラスを自分で実装することで、「データを読み込む度に、ログのパース処理を逐次的に行っていく」形式を採用することにしました。

https://docs.unity3d.com/ja/2020.3/Manual/UnityWebRequest-CreatingDownloadHandlers.html

- データがある程度読み込まれると、コールバック関数(派生クラスのoverrideメソッド)に受信バッファが渡されてくるので、ログのパース処理を実行する。
- 受信バッファの終端で、ログの行データが途中で終わっている場合がありうるので、その際は、パースが終わっていない残りのデータを内部バッファに一旦保存しておき、次のコールバック時に渡されてきた受信バッファを、保存しておいた内部バッファの後ろに連結して、再度パース処理を継続します。

ちょっと実装に手間がかかりますが、致し方ありません。ここはチャレンジです。笑)

## ログファイルのパース処理
前述の通り、メモリ上に格納されたログデータをパース処理するので、MemoryStreamを利用します。

また、ログデータは改行コードで区切られた「行データ」ごとに「S式」で表記されているので、StreamReaderのReadLine()メソッドで読み出します。

S式(S-Expression)は、Lisp言語で採用されている「ネストしたツリー構造を括弧で表記したもの」だそうです。

https://ja.wikipedia.org/wiki/S%E5%BC%8F

ReadLine()メソッドの注意点は、受信バッファの終端まで読み込むと、改行コードがなくても読み込み成功として「行データ」を返してくる点です。

よって、実際にパース処理を実行してみて、「不正なS式」と判定された場合は、一旦次の受信処理まで待って、行の残りのデータが連結されてから再度パース処理を実行する、という流れになります。
それでもパースエラーが発生する場合は、本当に「不正なS式」となります。

S式の解釈は、S式用のパーサーを実装するのは手間だったので、正規表現(RegEx)で「書式チェック」を行うことで代用することにしました。

ちなみに、実際のログデータのS式は、例えばこんな感じで記述されています。
```
(show 3512 ((b) 51.3686 -0.9763 1.1592 -1.2179) ((l 1) 0 0x9 -33.9375 -0.5704 0.0005 -0 4.688 -5 (v h 180) (fp 0 0) (s 8000 1 1 124368) (f l 3) (c 0 354 3913 1 3 4271 327 210 0 0 2852 0)) ((l 2) 15 0x1 0.8892 -14.3954 0.1047 -0.0683 -70.256 89 (v h 60) (fp 0 0) (s 8000 0.887456 1 118387) (f l 3) (c 8 1499 2743 0 2 4252 1906 610 0 2 2896 0)) ((l 3) 7 0x1 0.2174 14.5585 0 0 74.338 -90 (v h 60) (fp 0 0) (s 8000 0.890715 1 119869) (c 5 1474 2751 0 2 4232 1482 722 0 2 2855 0)) ((l 4) 17 0x1 12.9398 -21.192 0.0772 0.0831 20.858 10 (v h 60) (fp 0 0) (s 7808.93 0.930527 1 117912) (f l 3) (c 19 1735 2456 0 2 4212 1011 465 0 2 2898 0)) ((l 5) 5 0x801 11.9241 21.7094 -0.0041 0.0034 -39.911 -61 (v h 60) (fp 0 0) (s 8000 0.860854 1 116515) (f l 3) (c 21 1803 2356 0 2 4193 534 623 2 0 2669 0)) ((l 6) 14 0x1 -0.7888 -1.2519 -0 0.0001 0.99 10 (v h 60) (fp 0 0) (s 8000 0.858335 1 120466) (f l 3) (c 15 1313 2819 0 2 4173 1580 721 2 2 2865 0)) ((l 7) 13 0x1 26.1318 -5.8621 0.0043 0.0031 -0.193 -1 (v h 120) (fp 0 0) (s 7454.23 0.886257 1 114867) (f l 3) (c 17 1891 2243 0 2 4153 374 609 0 2 2898 0)) ((l 8) 8 0x40001 23.5286 8.8147 0.1676 -0.2268 -58.248 -41 (v h 180) (fp 0 0) (s 7431.63 0.972688 1 111910) (f l 3) (c 33 2043 2031 0 2 4133 251 698 5 3 2732 0)) ((l 9) 4 0x1 35.9878 -6.7333 0.019 0.0103 -13.07 -84 (v h 120) (fp 0 0) (s 5798.79 0.862795 1 116363) (f l 3) (c 27 1808 2277 0 2 4114 320 693 0 69 2895 0)) ((l 10) 9 0x1 44.7182 6.9598 0.3101 -0.2891 -41.006 -27 (v h 60) (fp 0 0) (s 6744.54 0.975495 1 114111) (f l 3) (c 39 2080 1953 0 2 4094 483 810 2 73 2854 0)) ((l 11) 10 0x1 37.8121 2.877 0.3631 -0.0687 -12.339 -23 42.0004 1.9073 (v h 60) (fp 0 0) (s 5514.81 0.906389 1 113699) (f l 3) (c 43 2099 1913 0 2 4074 406 731 3 93 2854 0)) ((r 1) 0 0x9 49.6075 6.0411 0.0037 0.0089 113.331 90 0.407 15.0518 (v h 180) (fp 0 0) (s 7610.08 1 1 124401) (f r 4) (c 7 587 3417 1 4 4026 212 327 1 726 1935 0)) ((r 2) 4 0x1 38.5431 -0.5393 0.1079 -0.1523 -33.376 -90 -12.6941 6.482 (v h 120) (fp 0 0) (s 7336.26 0.862795 1 117391) (f r 8) (c 21 1507 2467 0 2 4007 315 800 0 717 1504 0)) ((r 3) 15 0x1 42.2198 7.0455 -0.0322 -0.0843 -155.441 0 -6.1233 20.6692 (v h 120) (fp 0 0) (s 7425.32 0.887456 1 116117) (f r 6) (c 39 1593 2354 0 2 3986 315 774 0 720 1311 0)) ((r 4) 7 0x1 45.8249 -15.7848 0.0196 -0.24 -90.503 90 -4.1837 -10.8332 (v h 180) (fp 0 0) (s 7563.94 0.890715 1 120525) (f r 6) (c 4 1213 2749 0 2 3968 211 542 0 726 1528 0)) ((r 5) 10 0x1 42.7956 5.6791 0.2194 -0.2151 -53.846 74 -4.4058 26.6587 (v h 120) (fp 0 0) (s 6935.29 0.906389 1 115244) (f r 1) (c 64 1851 2031 0 2 3945 373 1105 0 716 1330 0)) ((r 6) 16 0x1 38.6212 -2.7368 0.0254 -0.3242 -85.116 74 -10.138 9.2171 (v h 120) (fp 0 0) (s 7436.44 0.80939 1 114732) (f r 1) (c 26 1731 2168 0 2 3928 329 1073 1 722 1361 0)) ((r 7) 17 0x1 31.4226 9.7214 -0.1683 -0.2131 -126.305 -55 -8.511 39.7775 (v h 120) (fp 0 0) (s 6371.14 0.930527 1 114126) (f r 5) (c 45 1920 1942 0 2 3906 344 995 0 718 1321 0)) ((r 8) 5 0x1 27.6027 -7.0343 0.1813 0.2645 65.598 -89 -20.9882 10.9646 (v h 120) (fp 0 0) (s 6830.41 0.860854 1 111682) (f r 3) (c 15 1738 2124 0 2 3889 288 911 1 721 1422 0)) ((r 9) 13 0x801 11.5687 22.1928 -0.0091 0.0106 -52.163 -35 -38.7612 24.9278 (v h 180) (fp 0 0) (s 7547.5 0.886257 1 115560) (f r 8) (c 98 1768 1995 0 2 3869 334 1030 0 694 1504 0)) ((r 10) 9 0x1 14.3819 0.3853 0.0502 -0.1812 -80.603 -8 -30.779 24.4547 (v h 180) (fp 0 0) (s 6760.04 0.975495 1 113883) (f r 3) (c 85 1792 1960 0 2 3850 401 1029 2 705 1379 0)) ((r 11) 14 0x1 16.3473 9.9257 -0.1495 -0.2349 -119.165 42 -33.0399 16.6784 (v h 180) (fp 0 0) (s 7708.44 0.858335 1 115577) (f r 4) (c 86 1772 1948 0 2 3830 374 1080 2 706 1311 0)))
(show 3513 ((b) 52.5296 -2.2323 1.0913 -1.1807) ((l 1) 0 0x9 -33.937 -0.5705 0.0002 -0 4.688 -5 (v h 180) (fp 0 0) (s 8000 1 1 124368) (f l 4) (c 0 354 3914 1 3 4272 327 210 0 0 2853 0)) ((l 2) 15 0x1 0.9893 -14.4624 0.0497 -0.0332 -74.71 88 (v h 60) (fp 0 0) (s 8000 0.887456 1 118387) (f l 4) (c 8 1499 2744 0 2 4253 1907 610 0 2 2897 0)) ((l 3) 7 0x1 0.2174 14.5585 0 0 73.328 -90 (v h 60) (fp 0 0) (s 8000 0.890715 1 119869) (f l 4) (c 5 1474 2752 0 2 4233 1483 722 0 2 2856 0)) ((l 4) 17 0x1 13.1461 -21.0793 0.0862 0.0471 20.858 85 (v h 60) (fp 0 0) (s 7832.15 0.930527 1 117866) (c 19 1736 2456 0 2 4213 1011 466 0 2 2899 0)) ((l 5) 5 0x801 12.0861 21.5385 -0.0041 0.0032 -39.911 -6 (v h 60) (fp 0 0) (s 8000 0.860854 1 116491) (f l 4) (c 21 1804 2356 0 2 4194 534 623 2 0 2670 0)) ((l 6) 14 0x1 -0.7888 -1.2518 -0 0.0001 -1 12 (v h 60) (fp 0 0) (s 8000 0.858335 1 120466) (f l 4) (c 15 1313 2820 0 2 4174 1581 721 2 2 2866 0)) ((l 7) 13 0x1 26.1358 -5.8586 0.0014 0.0013 0.866 -90 (v h 120) (fp 0 0) (s 7496.52 0.886257 1 114825) (f l 4) (c 17 1891 2244 0 2 4154 374 609 0 2 2899 0)) ((l 8) 8 0x40001 23.8458 8.2179 0.1376 -0.259 -58.248 -90 (v h 180) (fp 0 0) (s 7396.5 0.972688 1 111860) (f l 4) (c 33 2044 2031 0 2 4134 251 698 5 3 2733 0)) ((l 9) 4 0x1 36.5826 -6.8629 0.2566 -0.0559 -13.07 -22 (v h 120) (fp 0 0) (s 5739.21 0.862795 1 116323) (f l 4) (c 27 1809 2277 0 2 4115 320 693 0 69 2896 0)) ((l 10) 9 0x1 45.0163 6.6992 0.1236 -0.1081 -79.506 -80 (v h 120) (fp 0 0) (s 6788.39 0.975495 1 114067) (f l 4) (c 39 2080 1954 0 2 4095 484 810 2 73 2855 0)) ((l 11) 10 0x1 38.1931 2.8276 0.1711 -0.0222 -55.023 75 42.0004 1.9073 (v h 120) (fp 0 0) (s 5560.06 0.906389 1 113653) (f l 4) (c 43 2099 1914 0 2 4075 407 731 3 93 2855 0)) ((r 1) 0 0x9 49.6111 6.0505 0.0015 0.0037 113.331 90 0.407 15.0518 (v h 180) (fp 0 0) (s 7655.08 1 1 124356) (f r 2) (c 7 588 3417 1 4 4027 212 327 1 726 1936 0)) ((r 2) 4 0x1 39.1468 -1.008 0.2605 -0.2022 -33.376 -90 -12.6941 6.482 (v h 120) (fp 0 0) (s 7276.67 0.862795 1 117350) (f r 1) (c 21 1508 2467 0 2 4008 315 800 0 717 1505 0)) ((r 3) 15 0x1 42.1946 6.9576 -0.0125 -0.0436 146.977 55 -6.9118 16.3237 (v h 120) (fp 0 0) (s 7473.87 0.887456 1 116068) (f r 5) (c 39 1593 2355 0 2 3987 315 774 0 721 1312 0)) ((r 4) 7 0x1 45.8354 -16.435 0.0049 -0.3014 -90.503 -90 -4.1837 -10.8332 (v h 180) (fp 0 0) (s 7531.04 0.890715 1 120478) (f r 3) (c 4 1214 2749 0 2 3969 211 543 0 726 1529 0)) ((r 5) 10 0x1 43.3305 4.9534 0.2402 -0.3258 -53.846 -90 -4.4058 26.6587 (v h 120) (fp 0 0) (s 6880.54 0.906389 1 115199) (f r 1) (c 64 1852 2031 0 2 3946 373 1105 0 716 1330 0)) ((r 6) 16 0x1 38.6459 -3.4341 0.0122 -0.343 -85.116 -90 -10.138 9.2171 (v h 120) (fp 0 0) (s 7403.51 0.80939 1 114685) (f r 4) (c 26 1732 2168 0 2 3929 329 1074 1 722 1362 0)) ((r 7) 17 0x1 30.9558 9.1431 -0.1951 -0.2417 -126.305 68 -8.511 39.7775 (v h 120) (fp 0 0) (s 6338.64 0.930527 1 114079) (f r 6) (c 45 1921 1942 0 2 3907 344 995 0 718 1322 0)) ((r 8) 5 0x1 27.7964 -6.7801 0.0962 0.1262 15.932 -90 -17.059 15.4453 (v h 120) (fp 0 0) (s 6879.47 0.860854 1 111632) (f r 5) (c 15 1738 2125 0 2 3890 288 912 1 722 1423 0)) ((r 9) 13 0x801 11.728 22.02 -0.0085 0.0099 -52.163 -9 -38.7612 24.9278 (v h 180) (fp 0 0) (s 7517.9 0.886257 1 115518) (f r 4) (c 98 1769 1995 0 2 3870 334 1030 0 694 1505 0)) ((r 10) 9 0x1 14.5417 -0.24 0.0663 -0.2594 -80.603 -9 -30.779 24.4547 (v h 180) (fp 0 0) (s 6729.35 0.975495 1 113839) (f r 1) (c 85 1793 1960 0 2 3851 401 1029 2 705 1380 0)) ((r 11) 14 0x1 16.0023 9.3888 -0.1664 -0.2591 -119.165 -90 -33.0399 16.6784 (v h 180) (fp 0 0) (s 7677.64 0.858335 1 115533) (f r 1) (c 86 1773 1948 0 2 3831 374 1080 2 706 1312 0)))
(playmode 3514 goal_l)
(team 3514 HELIOS2023 CYRUS 1 0)
(show 3514 ((b) 53.5858 -3.3844 0 0) ((l 1) 0 0x9 -33.9368 -0.5705 0.0001 -0 4.688 -5 (v h 180) (fp 0 0) (s 8000 1 1 124368) (f l 5) (c 0 354 3915 1 3 4273 327 210 0 0 2854 0)) ((l 2) 15 0x1 1.0361 -14.4973 0.0233 -0.0173 -76.804 71 (v h 60) (fp 0 0) (s 8000 0.887456 1 118387) (f l 5) (c 8 1499 2745 0 2 4254 1908 610 0 2 2898 0)) ((l 3) 7 0x1 0.2174 14.5585 0 0 72.299 -90 (v h 60) (fp 0 0) (s 8000 0.890715 1 119869) (f l 5) (c 5 1474 2753 0 2 4234 1484 722 0 2 2857 0)) ((l 4) 17 0x1 13.3419 -20.9901 0.0818 0.0373 20.858 24 (v h 60) (fp 0 0) (s 7855.36 0.930527 1 117820) (f l 5) (c 19 1737 2456 0 2 4214 1011 466 0 2 2900 0)) ((l 5) 5 0x801 12.2595 21.3628 -0.0041 0.0034 -39.911 -90 (v h 60) (fp 0 0) (s 8000 0.860854 1 116466) (c 21 1805 2356 0 2 4195 534 624 2 0 2671 0)) ((l 6) 14 0x1 -0.7888 -1.2518 -0 0 -1.921 12 (v h 60) (fp 0 0) (s 8000 0.858335 1 120466) (f l 5) (c 15 1313 2821 0 2 4175 1582 721 2 2 2867 0)) ((l 7) 13 0x1 26.716 -5.8403 0.2058 0.0065 0.866 55 (v h 120) (fp 0 0) (s 7438.81 0.886257 1 114783) (f l 5) (c 17 1892 2244 0 2 4155 374 609 0 2 2900 0)) ((l 8) 8 0x40001 24.029 7.6309 0.0795 -0.2547 -58.248 35 (v h 180) (fp 0 0) (s 7361.37 0.972688 1 111810) (f l 5) (c 33 2045 2031 0 2 4135 251 698 5 3 2734 0)) ((l 9) 4 0x1 37.3722 -7.0501 0.3407 -0.0807 -13.07 -85 (v h 120) (fp 0 0) (s 5679.62 0.862795 1 116282) (f l 5) (c 27 1810 2277 0 2 4116 320 693 0 69 2897 0)) ((l 10) 9 0x1 45.1981 6.0401 0.0754 -0.2734 -79.506 -15 (v h 120) (fp 0 0) (s 6732.24 0.975495 1 114023) (f l 5) (c 39 2081 1954 0 2 4096 484 810 2 73 2856 0)) ((l 11) 10 0x1 38.6699 2.3148 0.2141 -0.2303 -55.023 79 42.0004 1.9073 (v h 120) (fp 0 0) (s 5505.31 0.906389 1 113608) (f l 5) (c 43 2100 1914 0 2 4076 407 731 3 93 2856 0)) ((r 1) 0 0x9 49.6126 6.0545 0.0006 0.0016 113.331 90 0.407 15.0518 (v h 180) (fp 0 0) (s 7700.08 1 1 124311) (f r 6) (c 7 589 3417 1 4 4028 212 327 1 726 1937 0)) ((r 2) 4 0x1 39.8824 -1.5343 0.3174 -0.2271 -33.376 65 -8.7566 13.3193 (v h 120) (fp 0 0) (s 7217.09 0.862795 1 117310) (c 21 1509 2467 0 2 4009 315 801 0 718 1506 0)) ((r 3) 15 0x1 42.1814 6.9139 -0.0066 -0.0217 4.516 -70 -6.9118 16.3237 (v h 120) (fp 0 0) (s 7522.42 0.887456 1 116020) (f r 2) (c 39 1593 2356 0 2 3988 315 774 0 721 1313 0)) ((r 4) 7 0x1 45.7969 -17.1185 -0.0179 -0.3169 -90.503 90 -4.1837 -10.8332 (v h 180) (fp 0 0) (s 7498.14 0.890715 1 120431) (f r 5) (c 4 1215 2749 0 2 3970 211 543 0 726 1530 0)) ((r 5) 10 0x1 43.8877 4.1972 0.2502 -0.3395 -53.846 -85 -4.4058 26.6587 (v h 120) (fp 0 0) (s 6825.79 0.906389 1 115154) (f r 2) (c 64 1853 2031 0 2 3947 373 1105 0 716 1331 0)) ((r 6) 16 0x1 38.635 -4.2366 -0.0054 -0.3947 -85.116 77 -10.138 9.2171 (v h 120) (fp 0 0) (s 7350.56 0.80939 1 114638) (f r 2) (c 26 1733 2168 0 2 3930 329 1074 1 722 1363 0)) ((r 7) 17 0x1 30.757 8.9025 -0.0831 -0.1006 -65.698 -90 -8.511 39.7775 (v h 180) (fp 0 0) (s 6385.07 0.930527 1 114033) (f r 2) (c 45 1921 1943 0 2 3908 345 996 0 718 1323 0)) ((r 8) 5 0x1 27.9009 -6.6665 0.0519 0.0564 -66.714 29 -17.059 15.4453 (v h 120) (fp 0 0) (s 6928.54 0.860854 1 111583) (f r 4) (c 15 1738 2126 0 2 3891 288 912 1 722 1424 0)) ((r 9) 13 0x801 11.8703 21.8195 -0.0083 0.0109 -52.163 -9 -38.7612 24.9278 (v h 180) (fp 0 0) (s 7488.3 0.886257 1 115476) (f r 1) (c 98 1770 1995 0 2 3871 334 1030 0 694 1506 0)) ((r 10) 9 0x1 14.6382 -0.9972 0.04 -0.3141 -80.603 -90 -29.5263 23.3824 (v h 180) (fp 0 0) (s 6698.65 0.975495 1 113795) (f r 4) (c 85 1794 1960 0 2 3852 401 1029 2 706 1381 0)) ((r 11) 14 0x1 15.829 9.148 -0.0836 -0.1162 -61.782 90 -33.5793 15.844 (v h 180) (fp 0 0) (s 7721.64 0.858335 1 115489) (f r 2) (c 86 1773 1949 0 2 3832 374 1080 2 707 1313 0)))
```

## ログデータ
S式をパースした結果は、CycleObjectクラスの派生クラスとして、SimLogDataクラスに格納しました。

```
CycleObject
 +-- PlayModeCycleObject
 +-- TeamCycleObject
 +-- MsgCycleObject
 +-- ShowCycleObject
 +-- BallCycleObject
 +-- PlayerCycleObject
```

RoboCupのログファイルは、主に、(playmode),(team),(msg),(show)の４つのセルが定義されています。

例えば、(playmode)は「試合中に発生したイベント、ファウルやゴールなど」を表す文字列を保持しています。
また、(team)は得点に変化があった時に「左右のチームごとの、チーム名と得点」を表します。

(show)は、「ボールやプレーヤーの座標や属性値」が100msecごとに記録されています。1個のボールと合計22人分のプレーヤーの情報が内包されているので、パース時にはこれを分解して、それぞれBallCycleObjectやPlayerCycleObjectとして扱えるようにしました。

これは、ボールや特定のプレーヤーだけに注目して、移動軌跡を分析したりといった使い方ができるようにしたかったからです。

ログの再生処理では、ShowCycleObjectは扱わず、分解したBallCycleObjectやPlayerCycleObjectのみを扱います。

## 再生用データ
前述のCycleObjectの内容を元に、画面上に再現する時の処理を実装したのが、CycleActionクラスで、SimLogTimelineクラスの中に格納されます。

```
CycleAction
 +-- PlayModeCycleAction  -> PlayModeCycleObject
 +-- TeamCycleAction      -> TeamCycleObject
 +-- MsgCycleAction       -> MsgCycleObject
 +-- BallCycleAction      -> BallCycleObject
 +-- PlayerCycleAction    -> PlayerCycleObject
```

SimLogPlayerクラスにSimLogDataを食わせると、各CycleActionを格納したSimLogTimelineデータを構築します。

CycleActionクラスは、対応するCycleObjectへの参照を保持しており、画面上に配置した3Dモデルを移動させたり、得点ボードの表示を更新したりといった処理を担当します。

## タイマー実行
定期タイマーの実装は、次のサイトを参考に、MonoBehaviour.InvokeRepeatingを採用することにしました。

https://qiita.com/toRisouP/items/e6d4f114d434ee588044

# スクリーンショット
ここまでの内容を、テストプログラムFootball_3として実装しました。
画面デザインもほぼ最終形に近いものが固まったかなぁ、という感じです。

ただし、CycleActionの中身の実装は、この時点ではまだ、ボールの移動までにとどめています。

![Football_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843818/4048d7d8-a4c2-28de-90b9-486d25ded78c.png)

# ソースコード
- [SelectFileDialog.cs](https://github.com/SuzukiNene/CrossView3D/blob/master/Assets/Scripts/SelectFileDialog.cs)
- [SimLog/SimLogReader.cs](https://github.com/SuzukiNene/CrossView3D/blob/master/Assets/Scripts/SimLog/SimLogReader.cs)
- [SimLog/SimLogParser.cs](https://github.com/SuzukiNene/CrossView3D/blob/master/Assets/Scripts/SimLog/SimLogParser.cs)
- [SimLog/SimLogData.cs](https://github.com/SuzukiNene/CrossView3D/blob/master/Assets/Scripts/SimLog/SimLogData.cs)
- [SimLog/SimLogPlayer.cs](https://github.com/SuzukiNene/CrossView3D/blob/master/Assets/Scripts/SimLog/SimLogPlayer.cs)
- [SimLog/SimLogTimeline.cs](https://github.com/SuzukiNene/CrossView3D/blob/master/Assets/Scripts/SimLog/SimLogTimeline.cs)

# 参考サイト
- https://zenn.dev/plumchang/articles/9187928bcbcf93
- https://namiton.hatenablog.jp/entry/2022/04/20/132255
- https://mogamogatech.com/nativefileso/
- https://qiita.com/nanananakam/items/4541b216c054bd9094bb
- https://developers.cyberagent.co.jp/blog/archives/6649/
- https://smdn.jp/programming/dotnet-samplecodes/stream/3a8012b4024111eb907175842ffbe222/

以上です。