Mercurial > hg > Papers > 2022 > riono-master
annotate Paper/chapter/3-WorkingInUnity.tex @ 51:9d71ffda7d97
update
author | riono <e165729@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 10 Feb 2022 19:08:25 +0900 |
parents | 67306bcc605a |
children | ea7e856b50e8 |
rev | line source |
---|---|
51 | 1 \chapter{Christie Sharpの実装の詳細} |
26 | 2 |
30
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
3 \section{Unity API} |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
4 Unityでは、ゲーム開発を行うためのライブラリとしてUnity APIが公開されている。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
5 ソースコード\ref{src:UnityExample}はUnity APIを使用したスクリプトの例である。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
6 Spaceキーを押し続けている間、playerObjectは物理演算に従って、毎フレーム$\vec{A} = (10, 5, 10)$だけ力を加えられ移動する例である。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
7 4行目では変数が初期化されていないまま使用されているように見えるが、Unityではpublic修飾子を使用するとUnityのエディタ上で事前に変数に代入することが可能になる。 |
26 | 8 |
31 | 9 \lstinputlisting[label=src:UnityExample, caption=Unity APIを使用した記述例]{src/Unity/UnityScriptExample.cs} |
30
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
10 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
11 Unity APIではC\#にはないVector3やGameObject、Rigidbodyなどの特別な型があり、これらはUnityEngineをusingすることで使用可能である。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
12 またMonoBehaviourを継承することによって、StartメソッドやUpdateメソッドなどのUnity上で決められた、あるタイミングで呼び出される関数を使用することが可能である。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
13 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
14 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
15 Startメソッドはゲームの開始時、1フレーム目が始まる前に1回だけ実行され、主に初期化に使用されることが多い。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
16 今回はplayerObjectに付与されている物理演算のComponentであるRigidbodyを取得している。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
17 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
18 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
19 UpdateメソッドはStartメソットの実行後に毎フレーム呼び出される関数であり、ゲームのメインロジックで使用されることが多い。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
20 15行目ではキー入力の有無を確認しており、Spaceキーの入力を監視している。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
21 続く16行目では、Startメソッドにて取得したRigidbodyに対して、3次元ベクトルを力として与えている。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
22 これを行うことによって、Spaceキーを押している間$\vec{A} = (10, 5, 10)$がplayerObjectに与えられ、playerObjectは物理演算に従って移動する。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
23 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
24 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
25 UnityではStartメソッドやUpdateメソッドがある代わりに、C\#の一般的な実行メソッドであるMainメソッドによる処理の開始ができない。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
26 そのため、Unityで処理を行うためには、MonoBehaviourにより提供されているメソッドを通して処理を実行する必要がある。 |
26 | 27 |
28 | |
29 \section{StartCodeGearを使用しないChristie Sharpの実行} | |
29 | 30 % 例題など |
30
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
31 % やったこと全部書いたほうがいい/できたこと |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
32 % 多重継承の話 |
31 | 33 |
30
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
34 Chrisite SharpではStartCGにMainメソッドを記述してChrisite Sharpを実行したが、Unityで動作させるためにはStartメソッドやUpdeteメソッドを使用す必要がある。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
35 そのため、Chrisite Sharpの実行にStartCGを使用せずに実行できるよう変更を行った。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
36 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
37 \lstinputlisting[label=src:CountUpScript, caption=Unit上でのChrisite Sharpの実行Script]{src/Unity/CountUpScript.cs} |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
38 |
31 | 39 ソースコード\ref{src:CountUpScript}はソースコード\ref{src:CSStartCGExample}をUnityで動作するように書き換えたものであり、StartCGを使用せずに、Unity APIであるStartメソッドよりChrisite Sharpを実行している。 |
30
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
40 StartCGは、CGMの初期化や処理の開始位置を明確化させるためのクラスであるため、Christie Sharpの実行に必須ではない。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
41 また、C\#では多重継承が禁止されている。そのため、StartCGを継承しつつ、MonoBehaviourを継承してStartメソッドを使用する、と言うことはできない。 |
2a9f335e45bd
add source code and update Unity chapter
riono <e165729@ie.u-ryukyu.ac.jp>
parents:
29
diff
changeset
|
42 そのため可読性が下がってしまう可能性はあるが、CGMの初期化やSetupメソッドを直接Startメソッド内に記述できる。 |
26 | 43 |
44 | |
31 | 45 \section{Unity上での動作確認} |
46 % RemoteDG使ったやつ | |
47 % 2台で通信した場合 | |
48 % LateUpdateの話 | |
49 % UniRXのDispatcherとUnity APIの仕様の話 | |
50 | |
51 Christie Sharptの動作確認を行うため、以下の3点の確認を行った。 | |
52 LocalDGMに関してはソースコード\ref{src:CountUpScript}で正しく動作することを確認している。 | |
53 | |
54 \begin{itemize} | |
55 \item CodeGearを使用した、GameObjectの位置の操作 | |
32 | 56 \item 同一プロセスでの、複数DGMを使用したGameObjectの位置の同期 |
31 | 57 \item PC2台を使用した、LAN上でのGameObjectの位置の同期 |
58 \end{itemize} | |
59 | |
60 | |
61 \lstinputlisting[label=src:TransformMoveTest, caption=GameObjectの位置の操作の準備を行うScript]{src/Unity/TransformMoveTest.cs} | |
62 \lstinputlisting[label=src:PositionAssignCodeGear, caption=GameObjectの位置の操作を行うCodeGear]{src/Unity/PositionAssignCodeGear.cs} | |
63 | |
64 ソースコード\ref{src:TransformMoveTest}、\ref{src:PositionAssignCodeGear}は、CodeGearを使用した、GameObjectの位置の操作を行う処理である。 | |
65 ソースコード\ref{src:TransformMoveTest}を付与したGameObjectの位置より、常にx軸に+3、z軸に+3離れた位置に他のGameObjectであるotherTransfromが移動をする。 | |
66 19行目のLateUpdateメソッドはMonoBehaviourから継承している関数であり、全てのUpdateメソッドが実行された後、次のフレームに移行する直前に実行される関数である。 | |
67 | |
68 UnityでChrisite Sharpを使用する際に一つ問題が起きた。 | |
69 Unity APIでサポートされている関数や型はMain Threadで動作時のみ処理が行われるという仕様がある。 | |
70 これはUnityの根本的な考え方であり、Unityでは基本的にシングルスレッドでの動作を想定してる。 | |
71 非同期処理を行うための機能として、CoroutineやInvoceなどの機能が提供されており、擬似的にMulti Threadのように処理を行うことが可能である。 | |
72 しかしChrisite SharpではCodeGearをTaskで処理させている。 | |
73 このためCGに直接Transformを操作しても処理が実行されない。 | |
74 | |
75 | |
51 | 76 この問題を解決するために、UniRx\cite{unirx}を導入することで使用可能なMainThreadDispatcher.Postメソッドを使用した(ソースコード\ref{src:PositionAssignCodeGear} 6行目)。 |
31 | 77 UniRxとはUnity向けに作成された非同期処理の外部ライブラリである。 |
78 MainThreadDispatcher.Postを使用することで、Main ThreadでないThreadで行っている処理をMain Threadに移譲することが可能となる。 | |
79 Postメソッドは第一引数にデリゲートの一種であるAction$<$T$>$を渡すため、ラムダ式での記述が可能である。 | |
80 | |
81 | |
32 | 82 \lstinputlisting[label=src:RemoteMoveTest, caption=RemoteDGMでGameObjectの位置の操作の準備を行うScript]{src/Unity/RemoteMoveTest.cs} |
83 \lstinputlisting[label=src:ObjectMoveCodeGear, caption=RemoteDGMでGameObjectの位置の操作を行うCodeGear]{src/Unity/ObjectMoveCodeGear.cs} | |
84 \lstinputlisting[label=src:Vector3Cmd, caption=GameObjectの位置データとして送信されるオブジェクトのクラス]{src/Unity/Vector3Cmd.cs} | |
26 | 85 |
32 | 86 ソースコード\ref{src:RemoteMoveTest}、\ref{src:ObjectMoveCodeGear}、\ref{src:Vector3Cmd}は同一プロセスにおいて、 |
87 RemoteDGMを使用しGameObjectの位置を操作するScriptである。 | |
26 | 88 |
32 | 89 ソースコード\ref{src:RemoteMoveTest}のStartメソッドでは、playerCGMとenemyCGMの2つのDGMを用意し、 |
90 playerCGMの方では他方のenemyCGMをRemoteDGMとして指定を行っている。 | |
91 また、enemyCGMではSetupを行い処理の待機状態にしている。 | |
92 Updateメソッドでは、このScriptが付与されたGameObjectの位置を取得し、x軸に+3、z軸に+3離れた位置にotherTransformを移動させるようにし、 | |
93 送信用クラスに変形を行っている。 | |
94 21行目ではotherTransformを持っているenemyCGMではなく、playerCGMからPutを行っている。 | |
26 | 95 |
32 | 96 MessagePack CSharpではUnityにも対応しており、Unity APIが提供している値型のVector3やQuaternionなどもSerialize/Deserialize可能である。 |
97 しかし、Christie SharpではDGでデータを管理する際に全ての型に対応できるようObject型にCastをしている。 | |
98 このObject型のCastが原因によりVector3型を直接送信することができない。 | |
99 そのため、ソースコード\ref{src:Vector3Cmd}のようにデータをプリミティブ型に分割してデータを送信している。 | |
26 | 100 |
32 | 101 ソースコード\ref{src:ObjectMoveCodeGear}はソースコード\ref{src:PositionAssignCodeGear}と同様にMainThreadDispatcher.Postによって、 |
102 処理はMain Threadに移譲されて実行される。 | |
31 | 103 |
104 | |
32 | 105 \lstinputlisting[label=src:ObjectMoveServer, caption=GameObjectの位置をRemoteDGMに送信するScript]{src/Unity/ObjectMoveServer.cs} |
106 \lstinputlisting[label=src:ObjectMoveListener, caption=GameObjectの位置を受信して位置を操作するScript]{src/Unity/ObjectMoveListener.cs} | |
31 | 107 |
108 | |
32 | 109 ソースコード\ref{src:ObjectMoveServer}、\ref{src:ObjectMoveListener}は2台のPCを使用しLAN内でGameObjectの位置を通信して操作するScriptである。 |
110 CGや、送信するDGについては、ソースコード\ref{src:ObjectMoveCodeGear}、\ref{src:Vector3Cmd}を流用している。 | |
31 | 111 |
112 | |
32 | 113 ソースコード\ref{src:ObjectMoveServer}、\ref{src:ObjectMoveListener}それぞれの3行目ではhostNameを指定しており、通信先のLocal IPアドレスを入力することでSocket通信を行っている。 |
114 ソースコード\ref{src:ObjectMoveServer}は位置データの送信元であり、RemoteDGMとして指定したlistenerに向けて、自身のGameObjectの位置をPutしている。 | |
115 ソースコード\ref{src:ObjectMoveListener}は何もデータをPutしておらず、LateUpdateメソッドでSetupを行うことでソースコード\ref{src:ObjectMoveServer}から受け取ったデータを基にGameObjectの位置を変更している。 | |
34 | 116 |
117 | |
118 以上のテストにより、Chrisite Shrapの機能が問題なくUnity上でも機能することが確認できた。 | |
119 | |
120 \section{UnityでのChrisite Sharpの役割} | |
121 UnityでCodeGearを動作させる場合、特にUnity APIを使用して処理を行う際は、MainThreadDispatcher.Postメソッドを利用してMain Threadに処理を以上する必要がある。 | |
122 他方、UnityではUpdateメソッドやFixedUpdateメソッドなどUnityの実装に従って、フレーム単位や時間単位でのメソッド呼び出しが保証されている。 | |
35 | 123 CG内でMainThreadDispatcher.Postメソッドを使用しGameObjectの移動などのUnity APIを利用した処理を行うことで、処理が行われるタイミングが不安定になることがあると考えられる。 |
124 | |
125 そこで、ネットワーク上で通信が必要なものだけをChrisite Sharpで通信を行い、受信データをMonoBehaviourを継承したクラスで処理・動作させるという方法を考えた。 | |
126 Unityには非同期処理としてCoroutineやTaskなどがあるが、シングルスレッドでの動作を前提として利用されている。 | |
127 この手法を取ることにより、Unity上の処理を行うタイミングが保証されると共に、 | |
128 並列処理やデータのやり取りをChristieに一任することができ、Multi Threadによる並列処理が可能となる。 | |
129 | |
34 | 130 |
35 | 131 またUnity上で操作、処理を行っているGameObject自体をDGに継続にする、直接的にはDGにすることによってより並列処理などを意識することなくゲーム開発が可能となる。 |
132 GameObject自体をDGにすることにより、通信に必要なデータを送信するためのコードを書かずに待ち合わせが可能となる。 | |
133 また、待ち合わせを行っていることによりデータがNullのまま処理を開始することがなくなる。 | |
134 位置などの毎フレーム必要なデータや、画面の描画に必要なデータはPeekで取得を行うことで、通信が途中で途切れてしまった場合でもその直前のデータは参照可能であり、 | |
135 接続の復帰も行いやすいと考えられる。 |