view Paper/chapter/4-WorkingInUnity.tex @ 31:4cb0634a79ff

update Unity chapter
author riono <e165729@ie.u-ryukyu.ac.jp>
date Fri, 04 Feb 2022 22:17:44 +0900
parents 2a9f335e45bd
children f6120b4d214a
line wrap: on
line source

\chapter{Christie SharpのUnity上での動作}

\section{Unity API}
Unityでは、ゲーム開発を行うためのライブラリとしてUnity APIが公開されている。
ソースコード\ref{src:UnityExample}はUnity APIを使用したスクリプトの例である。
Spaceキーを押し続けている間、playerObjectは物理演算に従って、毎フレーム$\vec{A} = (10, 5, 10)$だけ力を加えられ移動する例である。
4行目では変数が初期化されていないまま使用されているように見えるが、Unityではpublic修飾子を使用するとUnityのエディタ上で事前に変数に代入することが可能になる。

\lstinputlisting[label=src:UnityExample, caption=Unity APIを使用した記述例]{src/Unity/UnityScriptExample.cs}

Unity APIではC\#にはないVector3やGameObject、Rigidbodyなどの特別な型があり、これらはUnityEngineをusingすることで使用可能である。
またMonoBehaviourを継承することによって、StartメソッドやUpdateメソッドなどのUnity上で決められた、あるタイミングで呼び出される関数を使用することが可能である。


Startメソッドはゲームの開始時、1フレーム目が始まる前に1回だけ実行され、主に初期化に使用されることが多い。
今回はplayerObjectに付与されている物理演算のComponentであるRigidbodyを取得している。


UpdateメソッドはStartメソットの実行後に毎フレーム呼び出される関数であり、ゲームのメインロジックで使用されることが多い。
15行目ではキー入力の有無を確認しており、Spaceキーの入力を監視している。
続く16行目では、Startメソッドにて取得したRigidbodyに対して、3次元ベクトルを力として与えている。
これを行うことによって、Spaceキーを押している間$\vec{A} = (10, 5, 10)$がplayerObjectに与えられ、playerObjectは物理演算に従って移動する。


UnityではStartメソッドやUpdateメソッドがある代わりに、C\#の一般的な実行メソッドであるMainメソッドによる処理の開始ができない。
そのため、Unityで処理を行うためには、MonoBehaviourにより提供されているメソッドを通して処理を実行する必要がある。


\section{StartCodeGearを使用しないChristie Sharpの実行}
% 例題など
% やったこと全部書いたほうがいい/できたこと
% 多重継承の話

Chrisite SharpではStartCGにMainメソッドを記述してChrisite Sharpを実行したが、Unityで動作させるためにはStartメソッドやUpdeteメソッドを使用す必要がある。
そのため、Chrisite Sharpの実行にStartCGを使用せずに実行できるよう変更を行った。

\lstinputlisting[label=src:CountUpScript, caption=Unit上でのChrisite Sharpの実行Script]{src/Unity/CountUpScript.cs}

ソースコード\ref{src:CountUpScript}はソースコード\ref{src:CSStartCGExample}をUnityで動作するように書き換えたものであり、StartCGを使用せずに、Unity APIであるStartメソッドよりChrisite Sharpを実行している。
StartCGは、CGMの初期化や処理の開始位置を明確化させるためのクラスであるため、Christie Sharpの実行に必須ではない。
また、C\#では多重継承が禁止されている。そのため、StartCGを継承しつつ、MonoBehaviourを継承してStartメソッドを使用する、と言うことはできない。
そのため可読性が下がってしまう可能性はあるが、CGMの初期化やSetupメソッドを直接Startメソッド内に記述できる。


\section{Unity上での動作確認}
% RemoteDG使ったやつ
% 2台で通信した場合
% LateUpdateの話
% UniRXのDispatcherとUnity APIの仕様の話

Christie Sharptの動作確認を行うため、以下の3点の確認を行った。
LocalDGMに関してはソースコード\ref{src:CountUpScript}で正しく動作することを確認している。

\begin{itemize}
  \item CodeGearを使用した、GameObjectの位置の操作
  \item 同一プロセスでの、RemoteDGMを使用したGameObjectの位置の同期
  \item PC2台を使用した、LAN上でのGameObjectの位置の同期
\end{itemize}


\lstinputlisting[label=src:TransformMoveTest, caption=GameObjectの位置の操作の準備を行うScript]{src/Unity/TransformMoveTest.cs}
\lstinputlisting[label=src:PositionAssignCodeGear, caption=GameObjectの位置の操作を行うCodeGear]{src/Unity/PositionAssignCodeGear.cs}

ソースコード\ref{src:TransformMoveTest}、\ref{src:PositionAssignCodeGear}は、CodeGearを使用した、GameObjectの位置の操作を行う処理である。
ソースコード\ref{src:TransformMoveTest}を付与したGameObjectの位置より、常にx軸に+3、z軸に+3離れた位置に他のGameObjectであるotherTransfromが移動をする。
19行目のLateUpdateメソッドはMonoBehaviourから継承している関数であり、全てのUpdateメソッドが実行された後、次のフレームに移行する直前に実行される関数である。

UnityでChrisite Sharpを使用する際に一つ問題が起きた。
Unity APIでサポートされている関数や型はMain Threadで動作時のみ処理が行われるという仕様がある。
これはUnityの根本的な考え方であり、Unityでは基本的にシングルスレッドでの動作を想定してる。
非同期処理を行うための機能として、CoroutineやInvoceなどの機能が提供されており、擬似的にMulti Threadのように処理を行うことが可能である。
しかしChrisite SharpではCodeGearをTaskで処理させている。
このためCGに直接Transformを操作しても処理が実行されない。


この問題を解決するために、UniRxを導入することで使用可能なMainThreadDispatcher.Postメソッドを使用した(ソースコード\ref{src:PositionAssignCodeGear} 6行目)。
UniRxとはUnity向けに作成された非同期処理の外部ライブラリである。
MainThreadDispatcher.Postを使用することで、Main ThreadでないThreadで行っている処理をMain Threadに移譲することが可能となる。
Postメソッドは第一引数にデリゲートの一種であるAction$<$T$>$を渡すため、ラムダ式での記述が可能である。