![[Inner Drive Studios] Dice (Creator) Packのデモのスクリーンショット](https://www.zkn0hr.com/wp-content/uploads/2021/03/inner-drive-studios-dice-creator-pack.jpg)
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
【使用準備】サイコロプレハブの設置と設定
- Projectウィンドウ -> Assets -> InnerDriveStudios -> DiceCreator -> Prefabs -> PhysicsDice_SingleValueを開く。
- 各種サイコロのプレハブをヒエラルキーに設置。
「サイコロをタッチした時にロールする機能」を消すには、サイコロ本体にアタッチされたMouseClickDieRollerコンポーネントをデタッチ。
複数のサイコロを扱う
複数のサイコロの値や、ロールを纏めて管理する場合は、DieCollectionを使用する。
- Assets -> InnerDriveStudios -> DiceCreator -> Prefabs
 のDieCollectionをヒエラルキーに設置。
- DieCollectionコンポーネントのRollablesリストに、インスペクターからサイコロを紐付け。
「キーを押した時にロールする機能」を消すには、DieCollectionにアタッチされたKeyPressCollectionRollerコンポーネントをデタッチ。
1つの面に複数の目がある特殊なサイコロ
メインの数値 + 雷やハートのマークが刻まれた、独特なサイコロのプレハブ。
- 6面ダイスのみ。
- マーク違いで2種類ある。
Assets -> InnerDriveStudios -> DiceCreator -> Prefabs -> PhysicsDice_SampleMultiValue
の各種サイコロのプレハブをヒエラルキーに設置。
複数のサイコロを扱う場合にDieCollectionを使用するのは共通。
「サイコロをタッチした時にロールする機能」を消すには、サイコロ本体にアタッチされたMouseClickDieRollerコンポーネントをデタッチ。
サイコロ台
サイコロを振る為の台のプレハブもある。
- Projectウィンドウ -> Assets -> InnerDriveStudios -> DiceCreator -> Prefabsを開く。
- RollingAreaをヒエラルキーに設置。
既にColliderは設定されているので、そのまま使える。
ダイスロールの実行
プレハブには既にColliderや、Rigidbodyがアタッチされている為、特段弄る事なくダイスロールが出来る。
【コード】単数
- 各種サイコロのプレハブにアタッチされた、「PhysicsDieコンポーネント」をインスペクター等から紐付けし、保持しておく。
- PhysicsDie.Rollを呼ぶ。
//名前空間が設定されているのでusing宣言。
using InnerDriveStudios.DiceCreator;
public class Test : MonoBehaviour
{
//インスペクターから紐付けしておく。
	[SerializeField]
	PhysicsDie physicsDie;
	void Roll()
	{
		physicsDie.Roll();
	}
}
【コード】複数
- DieCollectionプレハブにアタッチされた、「DieCollectionコンポーネント」をインスペクター等から紐付けし、保持しておく。
- 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)
	{
	}
}
まとめ
名前空間の設定や、参照の保持もキッチリ行われており、最適化も十分。
また、非アクティブなサイコロは、ロールや結果の表示から除外してくれる(エラーも出ない)。
文句の付け所はないです。



