トップ画像
MyCrane制作記2

執筆者: しげ

最終更新: 2023/02/26

MyCrane制作記2


こんにちは.しげです.
前回から1年くらいあいてしまいましたが,続きを書きましたのでよければ見ていってください.
*MyCraneは,C#とUnityで制作しているクレーンゲームです.自分でクレーンゲームの設定を作りたい!遊びたい!を形にするために,このプロジェクトは始動しました.

プログラム構成

まず,MyCraneのスクリプト(プログラム)構成はどのようになっているのでしょうか.
大きく分けると筐体全体をコントロールするメインプログラムと,筐体の各部をコントロールするサブプログラムで構成されています.
例としてMyCrane Type3を見てみると
メインプログラム

  • Type3Manager.cs


サブプログラム

  • Type3ArmController.cs
  • ArmControllerSupport.cs
  • CraneBox.cs
  • GetPoint.cs
  • RopeManager.cs
  • RopePoint.cs
  • CreditSystem.cs
  • ProbabilitySystem.cs(CreditSystem.csから分離)
  • BGMPlayer.cs
  • SEPlayer.cs
  • MachineHost.cs

となっています.
メインプログラムはサブプログラムの呼び出しを行って,所定の動作を実行します.基本的にはメインプログラム→サブプログラムの方向でメッセージを送りますが,例外的にサブプログラムからメインプログラムにメッセージを送ることもあります.

メインプログラム

メインプログラムは,筐体の動作の流れをコントロールします.具体的には,

  1. 待機状態
  2. 横へ移動する
  3. 縦に移動する
  4. アームが開く
  5. 下降する
  6. アームが閉じる
  7. 上昇する
  8. ホームポジションに戻る
  9. アームが開く
  10. アームが閉じる

の繰り返しが実現できるようなプログラムになっています.
簡単に言えば,メインプログラムはサブプログラムにメッセージを送ることで,筐体の動作を実現し,実際の動作についてはサブプログラム側に記述されているということになります.もし,アームユニットを右に動かしたい場合は,メインプログラムからcraneBox.Right()と関数を呼び出すことになります(正確にはCraneBoxクラスのインスタンスをメインプログラムが持っていなければならないのですが,今回は割愛します).
以下はメインプログラムからの呼び出し例です.craneStatusは筐体の現在の状態(横移動中,待機中など)を管理している変数です(今思えば列挙型の方が良かったかもしれない).

if (craneStatus == 2) craneBox.Right();


サブプログラム

サブプログラムには実際の動作が記述されています.内部的な処理はサブプログラムが行います.ほとんどの筐体で同じ処理を使うことになります.例としてCraneBox.csを見てみると次のような記述があります(一部簡略化してあります).

public void Right()
{
	if (!rightRefusedFlag) // 右移動制限に到達していない場合
	{
		// x座標をmoveSpeed分だけ増加させる(moveSpeedは常に正の値)
		transform.localPosition += new Vector3(moveSpeed, 0, 0);
	}
}

このRight()関数には,座標を上書きすることでx座標を増やすという処理が書いてあります.この処理はゲーム内において,右に移動する動作として還元されます.ただし,筐体を回転させると座標系が変わってしまうため,筐体の向きに依存しないローカル座標の値を変更するプログラムになっています.
メインプログラム→サブプログラム呼び出し→実際の処理という流れの例です.メインプログラムでは実際の処理内容を気にする必要はなく,ただプログラムの呼び出しをすれば良いという形です.

開発の流れ

まずはサブプログラムを作成することになります.メインプログラムはサブプログラムを呼び出すことで所定の処理を行うので,呼び出し先の関数や処理を用意しなければ書くことができません.MyCraneでは,BGMPlayer・SEPlayer・CreditSystemを初めに制作しました.これらの処理は物理演算が関係しないので,比較的取り組みやすいです.

CreditSystemでは,クレジットサービスの実装に苦労しました.500円連続で入れると1プレイのおまけが付くという機能ですが,100円1プレイ,500円6プレイに設定していると,1000円で12プレイできるが,1100円入れてしまうと11プレイになってしまったり,加速度的にサービス回数が増えていったり…

柔軟に設定できるという仕様にかなり悩まされた覚えがあります.

次に開発に着手したのはCraneBoxです.物理演算が絡んでいそうな部分ですが,MyCraneでは座標書き換えにより移動を実現しているので,物理演算は関係していません.
そして,ArmController・ArmControllerSupportの開発に着手しました.ここではUnityのMotorを使用して,アームの駆動制御やパワー制御を行いました.


最難関だったのは,RopePointとRopeManagerです.紐を模擬するためのプログラムですが,部分的に物理演算が混じっているプログラムのため,巻取りに失敗する事故が多発して,バグもまだ残っています.まだ理想には程遠いですね.


最後はGetPointです.これは,メインプログラムをサブプログラムから呼び出す(逆方向),数少ないサブプログラムです.景品がセンサーを通過すると獲得したことを通知する必要があるのですが,獲得演出はメインプログラムに組まれているため,その関数をGetPointが呼び出すことになります.


3Dモードが実装されてからMachineHostの開発を行いました.MachineHostは3Dモードにおいて,操作対象の筐体を1台に絞るために使用するプログラムです.MachineHostを実装する前は,全筐体が連動して動作してカオスでした.オートプレイ対応のためのAutoContollerも後に開発しました.

実は課題解決型プログラミング

MyCraneは筐体の種類をType1,2,3と振ってはいますが,開発の順序は3,2,1,4から後ろに向かって,という順序になっています.MyCraneでは,当初から課題解決型プログラミングを意識しており,課題解決を行いながら規模を拡大していく開発になっています.

筐体開発は次の順序で行いました.

  • Type3:基本動作作成(サブプログラム制作)・確率機能の作成
  • Type2:基本技術成熟・レバー操作の実現・タイマープログラムの制作
  • Type1:2人プレイ筐体の制作
  • Type4:レバー操作の技術成熟・回転機能付き筐体・UnityのVideoPlayerの理解
  • Type5:UnityのAnimatorの理解
  • Type7:レバー操作の技術成熟
  • Type6:同上
  • Type8:複雑な動作フローの設計,プッシャー機構の制作
  • Type9:4人プレイ筐体の制作
  • Type10:ゲームプレイヤーからのリクエスト
  • Type11:ロープ吊り下げ式筐体の制作
  • Type12:回転機能付き筐体・UnityのAnimatorの理解
  • EnarcYm1:実筐体のバグを再現
  • MYPUSH1:プッシャー筐体制作
  • Type13:コルーチン採用新マネージャープログラム作成
  • MYPUSH2:プッシャー筐体(2人プレイ)制作
  • EnarcYm2:8人プレイ筐体の制作・複雑デザイン筐体の制作


機能を一気に開発するのはかなり大変ですし,動く状態に持ってくるまでモチベーションを維持するのも難しいと思います.まずは基本機能から小さく作って,機能を付け足していくのが良さそうですね.また,機能を小さめの状態で開発して,後から拡張するというのも考え方の一つです.僕も初めはBGMPlayerとSEPlayerだけ作って楽しんでいました().

終わりに

次回は,筆者が3回生のときに履修したオブジェクト指向言語の講義の知識を使って,MyCraneのプログラム改良に取り組む話を書く予定です.ここまで読んでいただき,ありがとうございました.
今振り返ってみると,コルーチンを使わずに遅延処理を実現しようとしているなど,苦肉の策が伺えます.

取得に失敗しました

2019年度 入部

Twitter GitHub