鉄は熱いうちに打て、こんにちは、ぬいぐるみです。
前回、「Unityの教科書」に出てきたルーレットアプリを魔改造するという記事で「ルーレットの動き出しと停止を別クリックで実装する」という内容を書きました。今回はその続きになります。
目次
どうやって実装する?
やりたいことを図でまとめるとこんな感じ。(3以降は省略)
実装
本に書いてある素材の再配布はよろしくないと思ったのでルーレットの素材を作りました。
前回と同じく「再配布」「直リンク」のみ禁止でお願いします。それ以外の利用は常識の範囲内でどうぞ。
ソースコード
44行目でtransform.Rotateを使用していますが、51行目ではtransformlocalEulerAngelsを使用してます。
Unityの内部では角度はクォータニアンで処理されるのですが、人間の目からみて直感的に分かりづらいため、オイラー角で角度を操作しています。
(Unity上のインスペクターで操作できるTransformもオイラー角で描写されています)
switch ~ case文は範囲指定ができなかったのでif ~ else文を使ってます。(算数苦手だから条件合ってるか確信が持てないので間違えていたらこっそり教えてください)
疑惑の判定(線の上ぴったり)はif~else文の条件を変更することで、いい感じで調整できるかと思います。
プログラミング初心者が書いているので、もっときれいに書けるはず…。修正する箇所があったら優しくコメントで教えてください。
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class RouletteController : MonoBehaviour
- {
- float rotSpeed = 0;
- int countClick = 0;
- // Start is called before the first frame update
- void Start()
- {
- Application.targetFrameRate = 60;
- }
- // Update is called once per frame
- void Update()
- {
- if (Input.GetMouseButtonDown(0))
- {
- switch(countClick)
- {
- case 0:
- //初回クリック(ルーレット動き出し時の判定)
- this.rotSpeed = 10;
- countClick += 1;
- break;
- case 1:
- //2回目クリック(ルーレットを止めるときの判定)
- countClick += 1;
- break;
- default:
- break;
- }
- }
- if(countClick >= 2)
- {
- //クリックされた後減速する処理
- this.rotSpeed *= 0.96f;
- }
- transform.Rotate(0, 0, this.rotSpeed);
- //止まった場合の処理
- if (rotSpeed < 0.1 && countClick >= 2)
- {
- this.rotSpeed = 0;
- //Transform myTransform = this.transform;
- Vector3 tmp = this.transform.localEulerAngles;
- if(tmp.z < 45)
- {
- Debug.Log("結果は1");
- }else if(tmp.z > 45 && tmp.z < 90)
- {
- Debug.Log("結果は2");
- }else if (tmp.z > 90 && tmp.z < 135)
- {
- Debug.Log("結果は3");
- }else if (tmp.z > 135 && tmp.z < 180)
- {
- Debug.Log("結果は4");
- }else if (tmp.z > 180 && tmp.z < 225)
- {
- Debug.Log("結果は5");
- }else if (tmp.z > 225 && tmp.z < 270)
- {
- Debug.Log("結果は6");
- }else if (tmp.z > 270 && tmp.z < 315)
- {
- Debug.Log("結果は7");
- }else if (tmp.z > 315 && tmp.z < 360)
- {
- Debug.Log("結果は8");
- }
- }
- }
- }
次回の野望
- リザルト画面の実装
- もう一度回すボタンの設置
- 結果が出たときに楽しげな音を鳴らす。
終わり
たぶん一番簡単なのは、Roulette.pngは回すだけにして、内部のスクリプトでランダムに1~8を出力させてそれによって結果を分岐、とかだと思います。
今回はせっかくだし目押ししたいよねってことで今回は角度で結果を分岐させました。
でももっと簡単なやり方があるはず…。
「ルーレットアプリを魔改造しよう!」と思いつくきっかけになった本、Unityの教科書ですが、シンプルなゲーム作りを通してC#やUnityについての理解を深めることができて、解説もわかりやすいので、Unityでのゲームづくりをしたい方が購入する初めての1冊におすすめです。
今までプロダクトを完成に持って行けず、プログラミングに挫折し続けてきた人こそ読んでほしい一冊です。
おまけ
LocalEulerAngelesは「0~360」までの数値で角度を表しますが、Unityのインスペクター→TransformのZ軸を見ていると「0~179」「-1~-180」で表されていることに気が付きます。
tmp.zの中身を出力してみてもマイナスの数値が出てこず、直感に反していると思ったので、検証するために簡単なスクリプトを書きました。
・Roulette.pngをクリックするたびに10度ずつ回転させる(tmp.z+=10)
・今のtmp.zの値をDebug.Logでコンソール上に出力する。
以下の動画はクリックした時に10ずつtmp.zを増加させて回転させるRouletteControllerを実行した結果ですが、これを実行するとUnityのインスペクター上では170の次に180にならずに-180になり、そのあとは-170,-160と下がっていきます。
ですが、Debug.Logで出力したtmp.zは170,180,190とあがり、360を超えたところ9.6(実質10)に戻っていきます。面白いですね。
Unityのインスペクター上の数値はEulerAngelesで取れる角度とは違う。インスペクターと同じ値が取れる関数が別にあったりするのかな…?このあたりの細かい仕様が知りたいけれど、探しても見つからない…。どなたかご存じの方いらっしゃったら教えてください。
※Unityリファレンス上では以下のように記載されているので、localEulerAnglesでインクリメントする数値を入れるのは本当はよろしくないです。
この変数は、角度を読み込んで絶対値に設定する場合にのみ使用する。角度が360度を超えると失敗するので、インクリメントしないでください。代わりにTransform.Rotateを使用してください。