【Unity有料アセット】サイコロの3Dモデルと出目の判定システム2

[Inner Drive Studios] Dice (Creator) Packのデモのスクリーンショット

Dice (Creator) Pack (ストアへの外部リンク)

サイコロの3Dモデルと、出目の判定システムが含まれた、アセット[Inner Drive Studios] Dice (Creator) Packの使い方。

2018年に20%OFFセールがあったらしいが、ここ最近は無し。

やや粗いが無料のアセットをまとめた記事は↓。

以下、デモ動画。

サイコロの種類

  • D2
  • D4:一面に複数の値があるように見えるが、角に出目が振られているだけ。
  • D6
  • D6Pips:ドット(ドットの数で出目を表現するタイプ)。
  • D6R:ラウンド(角が丸められているタイプ)。
  • D6RPips:ラウンド&ドット。
  • D8
  • D10-00:10の位。
  • D10-0:1の位。
  • D10-X:1の位だが0がX。
  • D12
  • D20

以下の2種類は、別フォルダに取り分けられている、「1つの面に複数の目(記号)がある特殊なサイコロ」。

  • D6_A
  • D6_B

【使用準備】サイコロプレハブの設置と設定

  1. Projectウィンドウ -> Assets -> InnerDriveStudios -> DiceCreator -> Prefabs -> PhysicsDice_SingleValueを開く。
  2. 各種サイコロのプレハブをヒエラルキーに設置。

「サイコロをタッチした時にロールする機能」を消すには、サイコロ本体にアタッチされたMouseClickDieRollerコンポーネントをデタッチ。

複数のサイコロを扱う

複数のサイコロの値や、ロールを纏めて管理する場合は、DieCollectionを使用する。

  1. Assets -> InnerDriveStudios -> DiceCreator -> Prefabs
    のDieCollectionをヒエラルキーに設置。
  2. DieCollectionコンポーネントのRollablesリストに、インスペクターからサイコロを紐付け。

「キーを押した時にロールする機能」を消すには、DieCollectionにアタッチされたKeyPressCollectionRollerコンポーネントをデタッチ。

1つの面に複数の目がある特殊なサイコロ

メインの数値 + 雷やハートのマークが刻まれた、独特なサイコロのプレハブ。

  • 6面ダイスのみ。
  • マーク違いで2種類ある。

Assets -> InnerDriveStudios -> DiceCreator -> Prefabs -> PhysicsDice_SampleMultiValue
の各種サイコロのプレハブをヒエラルキーに設置。

複数のサイコロを扱う場合にDieCollectionを使用するのは共通。

「サイコロをタッチした時にロールする機能」を消すには、サイコロ本体にアタッチされたMouseClickDieRollerコンポーネントをデタッチ。

サイコロ台

サイコロを振る為の台のプレハブもある。

  1. Projectウィンドウ -> Assets -> InnerDriveStudios -> DiceCreator -> Prefabsを開く。
  2. RollingAreaをヒエラルキーに設置。

既にColliderは設定されているので、そのまま使える。

ダイスロールの実行

プレハブには既にColliderや、Rigidbodyがアタッチされている為、特段弄る事なくダイスロールが出来る。

【コード】単数

  1. 各種サイコロのプレハブにアタッチされた、「PhysicsDieコンポーネント」をインスペクター等から紐付けし、保持しておく。
  2. PhysicsDie.Rollを呼ぶ。


//名前空間が設定されているのでusing宣言。
using InnerDriveStudios.DiceCreator;


public class Test : MonoBehaviour
{

//インスペクターから紐付けしておく。
	[SerializeField]
	PhysicsDie physicsDie;

	void Roll()
	{
		physicsDie.Roll();
	}

}

【コード】複数

  1. DieCollectionプレハブにアタッチされた、「DieCollectionコンポーネント」をインスペクター等から紐付けし、保持しておく。
  2. DieCollection.Rollを呼ぶ。


//名前空間が設定されているのでusing宣言。
using InnerDriveStudios.DiceCreator;


public class Test : MonoBehaviour
{

//インスペクターから紐付けしておく。
    [SerializeField]
    DieCollection dieCollection;

    void Roll()
    {
        dieCollection.Roll();

//結果が出ていない(Sleep状態でない)物を全てロール。
        dieCollection.RollNonExact();
    }

}

ダイスロールの設定

各種サイコロのプレハブにアタッチされた、「PhysicsDieコンポーネント」の各種値をインスペクターから変更する事で、ダイスロール時の挙動を設定出来る。

  • ThrowVector:投げるベクトル。
  • MaxAngleDeviation:投げるベクトルにランダムに加えられる角度。
  • MinVelocity:最低速度
  • MaxVelocity:最高速度
  • MinAngularVelocity:最低回転速度
  • MaxAngularVelocity:最高回転速度
  • NudgeAlongForce:角が下の状態で安定してしまった時に加える力

備考

  • 【ロールの仕様】最低加速度~最高加速度間の力が、ランダムにThrowVectorに掛けられる。
  • ThrowVectorは、ノーマライズされるので、大きい値を設定してもOK(内部的には1に収まる)。
  • MaxAngleDeviationを、0に設定した場合、ほぼThrowVector通りの挙動になる。
  • Rigidbody.MaxAngularVelocityを変更していないので、一定以上の回転速度にはならない(高い回転速度が必要なら、初期化時にRigidbody.MaxAngularVelocityの値を高く設定する)。

結果、状態の取得

DieSidesの状態


DieSides.GetDieSideMatchInfo()で取得したDieSideMatchInfoからの結果の取得。

  • DieSides.dieSideCount
    :intでダイスタイプが返される(10面ダイスなら10)。
  • DieSideMatchInfo.closestMatch.values[0]
    :出目の値をintで返す(1つの面に複数の出目がある場合、引数でindexを渡す(通常は0))。
  • DieSideMatchInfo.closestMatch.ValuesAsString()
    :出目の値をstringで返す(1つの面に複数の出目がある場合、コンマで区切った全てを返す)。

PhysicsDieの状態


PhysicsDie.GetRollResult()で取得したIRollResult。

  • PhysicsDie.isRolling
    :現在ロール中か否かをboolで返す。
  • IRollResult.Value()
    :出目の値をintで返す(valueCountが1以上の場合、引数でindexを渡す)。
  • IRollResult.valuesAsString
    :出目の値をstringで返す(1つの面に複数の出目がある場合、コンマで区切った全てを返す)
  • IRollResult.valueCount
    :1つの面に幾つの出目があるかをintで返す(通常は1)
  • IRollResult.isExact
    :結果が正確か否かをboolで返す?

DieCollectionの状態


DieCollection.GetRollResult()で取得したIRollResult。
前項と同じ型だが、やや違う挙動。

  • DieCollection.isRolling
    :全サイコロが、現在ロール中か否かをboolで返す。
  • IRollResult.Value()
    :出目の合計の値をintで返す(valueCountが1以上の場合、引数でindexを渡す。
    0はメインの出目の合計値、1~2は記号の出目の合計値)。
  • IRollResult.valuesAsString
    :出目の合計の値をstringで返す(1つの面に複数の出目がある場合、コンマで区切った全てを返す)。
  • IRollResult.valueCount
    :1つの面に幾つの出目があるか(DieCollectionに登録したサイコロの最大値)をintで返す(通常は1)。
  • IRollResult.isExact
    :結果が正確か否かをboolで返す?

【コード】単数

以下のテストコードで、各種変数をコンソールに表示する。


//名前空間が設定されているのでusing宣言。
using InnerDriveStudios.DiceCreator;


public class Test : MonoBehaviour
{

//サイコロのプレハブをインスペクターから紐付け。
	[SerializeField]
	PhysicsDie physicsDie;

//サイコロのプレハブをインスペクターから紐付け。
  	[SerializeField]
	DieSides dieSides;


	IRollResult result;
	DieSideMatchInfo dieSideMatchInfo;


	void Awake()
    	{
//Awakeのタイミングで実行したらエラーが出るので、適当に遅延処理。
		Invoke("Roll", 0.1f);
 		Invoke("PrintResult", 5);
    	}


//適当にロール。
	void Roll()
	{
		physicsDie.Roll();
	}

	void PrintResult()
	{


       		dieSideMatchInfo = dieSides.GetDieSideMatchInfo();


      		print("ダイスタイプ:" + dieSides.dieSideCount + "面ダイス");

		print("出目の値をintで返す:" + dieSideMatchInfo.closestMatch.values[0]);
  		print("出目の値をstringで返す:" + dieSideMatchInfo.closestMatch.ValuesAsString());
		print("結果が正確か否かをboolで返す? " + dieSideMatchInfo.isExactMatch);


 		result = physicsDie.GetRollResult();


		print("現在ロール中か否かをboolで返す:" + physicsDie.isRolling);

    		print("出目の値をintで返す:" + result.Value());
  		print("出目の値をstringで返す:" + result.valuesAsString);
 		print("1つの面に幾つの出目があるかをintで返す:" + result.valueCount);
		print("結果が正確か否かをboolで返す?:" + result.isExact);

 	}
}

【コード】複数

以下のテストコードで、各種変数をコンソールに表示する。


//名前空間が設定されているのでusing宣言。
using InnerDriveStudios.DiceCreator;


public class Test : MonoBehaviour
{

//DieCollectionのプレハブをインスペクターから紐付け。
	[SerializeField]
	DieCollection dieCollection;


	IRollResult collectionResult;


	void Awake()
	{
//Awakeのタイミングで実行したらエラーが出るので、適当に遅延処理。
		Invoke("Roll", 0.1f);
 		Invoke("PrintResult", 5);
    	}


//適当にロール。
	void Roll()
	{
       		dieCollection.Roll();
	}

	void PrintResult()
	{

//1つのみの場合と同一のIRollResultインターフェイスが返される。
//ほぼ同じだが、ValueやvaluesAsStringが出目の合計になっている。
 		collectionResult = dieCollection.GetRollResult();


     		print("現在ロール中か否かをboolで返す:" + dieCollection.isRolling);

    		print("出目の合計の値をintで返す:" + collectionResult.Value());
     		print("出目の合計の値をstringで返す:" + collectionResult.valuesAsString);
 		print("1つの面に幾つの出目があるかをintで返す:" + collectionResult.valueCount);
    		print("結果が正確か否かをboolで返す?:" + collectionResult.isExact);

//出目の結果が蓄積されてしまうので、「結果が出た後、次のロールをする前」にリセットする。
    		dieCollection.ClearEndResult();
 	}
}

イベントリスナー (ロール開始、終了タイミング)

イベントリスナーに登録する事で、

  • ロール開始
  • ロール終了
  • ロール結果のクリア

のタイミングに、任意のメソッドを呼ぶ事が出来る。

【コード】単数


//名前空間が設定されているのでusing宣言。
using InnerDriveStudios.DiceCreator;


public class Test : MonoBehaviour
{

//インスペクターから紐付けしておく。
	[SerializeField]
	PhysicsDie physicsDie;


	void Awake()
	{
//ダイスロール開始時のイベントリスナーにメソッドを登録。
 		physicsDie.OnRollBegin += onRollBegin;
//ダイスロール終了時のイベントリスナーにメソッドを登録。
		physicsDie.OnRollEnd += onRollEnd;
//ダイスロール結果クリア時のイベントリスナーにメソッドを登録。
//一応あるが、単数の場合は使わないっぽい。
		physicsDie.OnEndResultCleared += onEndResultCleared;
	}


//引数は一致させる。
	private void onRollBegin(ARollable die)
	{

 	}

 	private void onRollEnd(ARollable die)
	{

	}

 	private void onEndResultCleared(ARollable die)
	{

	}
}

【コード】複数


//名前空間が設定されているのでusing宣言。
using InnerDriveStudios.DiceCreator;


public class Test : MonoBehaviour
{

//インスペクターから紐付けしておく。
	[SerializeField]
 	DieCollection dieCollection;


	void Awake()
	{
//全体のダイスロール開始時のイベントリスナーにメソッドを登録。
		dieCollection.OnRollBegin += onRollBegin;
//全体のダイスロール終了時のイベントリスナーにメソッドを登録(全ての結果が出た時に呼ばれる)。
 		dieCollection.OnRollEnd += onRollEnd;
//全体のダイスロール結果クリア時のイベントリスナーにメソッドを登録。
 		dieCollection.OnEndResultCleared += onEndResultCleared;

//各ダイスロール開始時のイベントリスナーにメソッドを登録。
		dieCollection.OnChildRollBegin += onRollBegin;
//各ダイスロール終了時のイベントリスナーにメソッドを登録。    
 		dieCollection.OnChildRollEnd += onRollEnd;
//各ダイスロール結果クリア時のイベントリスナーにメソッドを登録。  
 		dieCollection.OnChildEndResultCleared += onEndResultCleared;
	}



//引数は一致させる。
//オーバーロードによって、OnRoll~とOnChildRoll~で同名メソッドの使い回しも可能。
	private void onRollBegin(ARollable die)
	{

 	}

 	private void onRollEnd(ARollable die)
	{

	}

 	private void onEndResultCleared(ARollable die)
	{

	}

//OnChildRoll~用。
	private void onRollBegin(DieCollection dieCollection, ARollable die)
	{

  	}

	private void onRollEnd(DieCollection dieCollection, ARollable die)
	{

	}

	private void onEndResultCleared(DieCollection dieCollection, ARollable die)
	{

	}
}

まとめ

名前空間の設定や、参照の保持もキッチリ行われており、最適化も十分。
また、非アクティブなサイコロは、ロールや結果の表示から除外してくれる(エラーも出ない)。

文句の付け所はないです。

タイトルとURLをコピーしました