今回はリール停止時の角度の取得方法について記事にしていきます。
今回の記事はPart6です。
自作パチスロについて記事のまとめはこちらです。
パチスロのリールを止めて、小役を枠内に収めるとか。
停止位置から何コマ滑らせるとか。
入賞小役を判定するとか。
様々なことにリールの停止角度が必要となってきます。
リール停止時の角度を取得する手順
角度取得までの流れ
- リールを回転させる( Quaternion .AngleAxis を使用)
- リール停止
- リールオブジェクトのTansformからオイラー角を取得します。
- リールオブジェクトのTansformからZ軸のQuaternion(クォータニオン)を取得
- 手順2と3をもとにリールの停止角度を360°表示に変換
ちなみに今回の記事は、1と2は飛ばします。
Unityにおける回転の考え方(前提知識)
まずはUnityについて知る必要があります。
退屈だとしても、最低限ここの理解は必要です。
Unityの角度の仕様については様々な記事がありますが、公式のスクリプトリファレンスが一番わかりやすいです。
3D アプリケーションの回転は、たいていクォータ二オンかオイラー角のどちらかによって表されています。
「Unityの回転と向き」Unityスクリプトリファレンス
そう、Unityにおける「角度」にはオイラー角とQuaternion(クォータニオン)というものが存在し、それらが混在しています。
オイラー角について
オイラー角は0度〜360度で表現されるため「人間が直感的に理解できる」角度です。
Inspectorに表示されている角度はオイラー角です。
Quaternion(クォータニオン)について
Quaternionでは、180 度より大きな回転を表現することができません。
Quaternionは複雑なので、 3D 空間の回転を表しているのだということを知っているだけで十分です。とスクリプトリファレンスでも言っています。
以下は公式からの引用です。
Unity では、ゲームオブジェクトのすべての回転は、内部ではクォータ二オンで保存します。
「Unityの回転と向き」Unityスクリプトリファレンス
回転からオイラー角を取得、変更、再適用することは、意図しない作用の原因になることがあります。
「Unityの回転と向き」Unityスクリプトリファレンス
この事から、リール停止時のTransformから単純に角度を取得しても必要としている角度は表示されません。
それではリールの停止角度を取得してみましょう
説明には以下のようなイラストを利用していきます。
円はリールを横向きにしたものだと思ってください。角度0の場所が0コマ目になります。
0コマ目が正面を向いている状態が初期値となり、基準です。
リールのオイラー角を取得
Unityでは .eulerAngles を使ってオイラー角を取得できます。
私の作成しているパチスロでは、リールがX軸方向に回転しますのでX軸の角度のみ取得します。
float f = transform.eulerAngles.x;
停止したリールから.eulerAngles を使用してオイラー角を取得すると以下のようになります。
このままでは使用できませんので後ほど変換します。
リールのQuaternionを取得
Unityでは、transform.forwardで向いている方向のベクトルを取得できます。
返り値はVector3型となり、今回はZ軸を利用します。
Vector3 quaAngle = new Vector3();
quaAngle = this.transform.forward;
transform.forwardでZ軸のベクトルを取得してみると以下の通りとなります。
正の値の範囲
負の値の範囲
ご覧の通り停止位置の判定に使えそうです。
Quaternionが「正の値」か「負の値」かでリールの位置を特定したいと思います。
オイラー角とQuaternionの関係図
今までの説明をまとめたものが以下の図になります。
停止したリールのTransformから単純に角度を取得してもデタラメになります。
しかし、オイラー角とQuaternionの二つを利用すると360°表示の角度を求める事ができます。
実装した関数
リール停止時に以下の関数を呼び出す事で、停止角度をfloat型で返してくれます。
/// <summary>
/// クォータニオンをオイラー角に変換
/// </summary>
float convertQuaternionToEuler()
{
float stopAngle;
Vector3 quaAngle = new Vector3();
quaAngle = _ReelTransform.forward; // クォータニオンを取得
if(quaAngle.z >= 0) // 正の値の範囲なら
{
float f = _ReelTransform.eulerAngles.x; // オイラー角を取得
if(f >= 270 && f < 360) // 270以上 360未満
{
// Aの範囲
stopAngle = 360 - f;
}
else if(f >= 0 && f < 90) // 0以上 90未満
{
// Dの範囲
stopAngle = 270 + (90 - f);
}
else
{
Debug.LogError("停止位置判定エラー オイラー角 " + f );
}
}
else if (quaAngle.z < 0) // 負の値の範囲なら
{
float f = _ReelTransform.eulerAngles.x; // オイラー角を取得
if (f >= 270 && f < 360) // 270以上 360未満
{
// Bの範囲
stopAngle = 90 + (f - 270);
}
else if (f >= 0 && f < 90) // 0以上 90未満
{
// Cの範囲
stopAngle = 180 + f;
}
else
{
Debug.LogError("停止位置判定エラー オイラー角がif範囲外 " + f);
}
}
else
{
Debug.LogError("停止位置判定エラー クォータニオンがif範囲外 " + quaAngle);
}
return stopAngle = Mathf.Round(stopAngle); // 偶数丸め
}
この関数で360度の表現に変換してしまえば、リール制御を作るのに利用できます。
とりあえず今回の記事はこれで完成です!
以下はおまけです。
リールの設計について(自分のメモ用)
リールの設計や諸々のことについて自分の備忘用に残しておきます。
かなり雑多な内容になりますので飛ばして結構です。
リールを回転させる方法について
当初はAddTorqueという関数でリールに力を与える方法を考えました。
しかしリール速度を計算するにあたって、Update内で回転の命令を出した方が圧倒的に計算しやすかったため、Updateで回転を加える設計にしました。
リールは何秒で1回転するのか?
1分間でリールが回る回数は80回以内と規定で決まっています。
そのため、ほぼ全ての機種が1分間に79.5〜79.9回転となっています。
79.5回転 ÷ 60秒 = 1.325回転。
1秒間に1.325回転回ります。
つまり、1回転は0.754秒という事が計算できます。
360度を0.754秒で回る。
360 / 0.754 = 477.45度
さらに、1秒に477.45度回転するという事も計算できます。
コメント
投稿お疲れ様です!
今回も目から鱗な情報がいっぱいでとても勉強になりました。
リール停止を角度で表現出来るんですね。
次回も楽しみに待っています!
完成をとても楽しみにしています!
そう言って頂けると素直に嬉しいです。
更新がスローで申し訳ありません。
完成したら僕の考えた最強のパチスロ(クソ台)をぜひ触ってみてください!