この記事はパズルゲームの作り方講座の第6回です。第5回では、マウスの入力処理とクリックしたゲームオブジェクトを検知する処理を実装しました。
前回の記事↓
第6回では、このゲームの中心部でもある、同じ色のボールをなぞると消える処理を作成していきます。
ただし、この処理を一気に作ろうとするととても難しいです。なので、次の3部構成で作成していきます。
- タッチしたボールの消去
- なぞったボールの判定
- なぞったボールを配列に入れる
タッチしたボールを消去・色を変える処理をUnityで実装する
まずは、タッチしたボールを消去する処理を作っていきましょう。
UnityのDestroy関数を使ってクリックしたオブジェクトを消す
TouchManager.csのUpdate関数を次のように書いてみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void Update() { var mousePos = Input.mousePosition; if(Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(mousePos); var h = Physics.RaycastAll(ray, 100.0f); if(h.Length > 0) { if(h[0].collider.tag=="Ball") { Destroy(h[0].collider.gameObject); } } } } |
ここで出てきたDestory関数は名前の通り、第一引数のゲームオブジェクトをシーン上から消去する関数です。
第4回目で行ったようにTagを使って衝突したゲームオブジェクトがBallかどうか判定。Ballであればオブジェクトを消去しています。
それでは実行してみましょう。クリックしたボールが消えていることが確認できます。
今回は選択したら消えるのではなく色が変わるようにしたいため、マテリアルの色を変えていきます。
Unity RendererとEmissionColorを使ってボールの色を変える方法
まずは、おさらいも兼ねて、BallマテリアルのAlbedoを変更してマテリアルの色を次のような水色に変えてみましょう。ここで注意ですが、Ballの編集はプレハブ内のBallで行ってください。
そして、このインスペクタをよく見てみると、Emissionというチェック項目があることが分かります。これは、物体が発光するようなエフェクトをかけたいときにチェックを入れる項目です。
また、Emissionの下のColorから発光色も変えることができます。今回の記事では、Emissionを使用してボールを選択している状態を表示していくことにします。Emissionにチェックを入れておきましょう。
そして、BallObject.csを次のようなコードに書き換えてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BallObject : MonoBehaviour { [SerializeField] public Renderer renderer; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } void OnCollisionEnter(Collision other) { //省略 } } |
追加したRendererとは、マテリアルやメッシュを描画するためのクラスです。
ゲームオブジェクトのマテリアルをスクリプト上で編集したい場合はRendererを参照できるようにします。
さらに、TouchManager.csのUpdate関数を次のように書き換えてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void Update() { var mousePos = Input.mousePosition; if(Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(mousePos); var h = Physics.RaycastAll(ray, 100.0f); if(h.Length > 0) { if(h[0].collider.tag=="Ball") { h[0].collider.GetComponent<BallObject>().renderer.material.SetColor("_EmissionColor",new Color(1f,1f,0,0.5f)); } } } } |
このコードは一見わかりにくいので詳細に解説します。
1 |
h[0].collider.GetComponent<BallObject>().renderer.material.SetColor("_EmissionColor", new Color(1f,1f,0,0.5f)); |
処理内容を理解するときは細かく分けてみるとわかりやすくなります。
- h[0].collider:触れたゲームオブジェクトのコライダー
- GetComponent().renderer:BallObjectコンポーネント中の変数renderer
- renderer.material:rendererにあるマテリアル
- material.SetColor関数:マテリアルの色を設定する関数
- SetColor(“_EmissionColor”,new Color(1f,1f,0,0.5f)):Emissionのカラーを黄色に設定
SetColor関数は、指定した色を変える関数です。例えば、第一引数を”_Color”にすればAlbedoの色を変更できます。
今回は”_EmissionColor”を指定しているためEmissionの色が変わるようになります。
まとめると、触れたゲームオブジェクトのマテリアルのEmissionのカラーを黄色に設定する処理を作っていることがわかります。
ちなみに、この第一引数に入れる文字列は正しい文字列を入れないとうまく起動しません。
この文字列の場所を探すためには、マテリアルのインスペクタ右上の詳細ボタンをクリックしてDebugを選ぶ必要があります。
すると、表示が切り替わったインスペクタ上のSaved PropertiesのColorsに「_Color」と「_EmissionColor」があることがわかります。
コードを書き終えたら、BallObjectのインスペクタ上のRendererにプレハブのBallをドラッグ&ドロップしましょう。
この状態で実行してみてください。クリックしたボールの色が変化する様子が確認できます。
なぞったボールの判定をUnityで実装する方法
次に、同じ種類のボールをなぞっていく処理を作成していきます。なぞる動作は、マウスボタンをクリックしている状態の時に行う動作であるため、GetMouseButton関数を使用していきます。
TouchManager.csのUpdate関数を下のコードに書き換えてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
void Update() { var mousePos = Input.mousePosition; if(Input.GetMouseButtonDown(0)) { Ray ray = Camera.main.ScreenPointToRay(mousePos); var h = Physics.RaycastAll(ray, 100.0f); if(h.Length > 0) { if(h[0].collider.tag=="Ball") { h[0].collider.GetComponent<BallObject>().renderer.material.SetColor("_EmissionColor", new Color(1f,1f,0,0.5f)); } } } if(Input.GetMouseButton(0)) { Ray ray = Camera.main.ScreenPointToRay(mousePos); var h = Physics.RaycastAll(ray, 100.0f); if(h.Length > 0) { if(h[0].collider.tag=="Ball") { h[0].collider.GetComponent<BallObject>().renderer.material.SetColor("_EmissionColor", new Color(1f,1f,0,0.5f)); } } } if(Input.GetMouseButtonUp(0)) { } } |
この状態で実行してみましょう。なぞったボールの色が変化する様子が確認できると思います。
なぞったボールを配列に入れる 手を離したら消える処理を実装する
次は、タッチしていったボールを配列に入れて選択されたボールを扱いやすくします。
TouchManager.csを下のように書き換えてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
[SerializeField] List<GameObject> touchBallList; void Start() { //省略 } void Update() { var mousePos = Input.mousePosition; if(Input.GetMouseButtonDown(0)) { touchBallList = new List<GameObject>(); Ray ray = Camera.main.ScreenPointToRay(mousePos); var h = Physics.RaycastAll(ray, 100.0f); if(h.Length > 0) { if(h[0].collider.tag=="Ball") { h[0].collider.GetComponent<BallObject>().renderer.material.SetColor("_EmissionColor", new Color(1f,1f,0,0.5f)); touchBallList.Add(h[0].collider.gameObject); } } } if(Input.GetMouseButton(0)) { if(touchBallList.Count!=0) { Ray ray = Camera.main.ScreenPointToRay(mousePos); var h = Physics.RaycastAll(ray, 100.0f); if(h.Length > 0) { if(h[0].collider.tag=="Ball") { h[0].collider.GetComponent<BallObject>().renderer.material.SetColor("_EmissionColor", new Color(1f,1f,0,0.5f)); touchBallList.Add(h[0].collider.gameObject); } } } } if(Input.GetMouseButtonUp(0)) { ReleaseObject(); } } public void ReleaseObject() { //離したらマテリアルを消す foreach(GameObject go in touchBallList) { Destroy(go); } touchBallList.Clear(); } |
今回は、ボールを何個なぞっても配列に格納できるようにするため、動的配列であるList型を使用しています。動的配列とは、配列の要素数を後から増やしたり減らしたりすることのできる配列です。基本的には以下の手順で使うことを覚えておけば問題ありません。
- var tmp = new List<T>(); で初期化
- tmp.Add(hoge); でhogeを追加
- tmp.Clear(); で要素を全消去
また、タッチしたゲームオブジェクトをすべて削除する関数であるReleaseObject関数を作成し、GetMouseButtonUp関数内に追加しています。
関連記事:UnityC# Listの使い方
この状態で実行してみましょう。ボタンを離すとなぞったボールが消えることが確認できます。
今回はこれで以上です。
おさらいと次回予告
今回は、同じ色のボールをなぞると消える処理を作成していきました。
次回は、応用編になります。ボールを増やす処理と3つ以上揃ったときにボールを消す処理を書いていきます。
次回の記事↓
パズルゲーム講座が動画になりました。
動画も合わせてチェック!
コメント
すごく丁寧な解説です。
勉強させていただいてます。
コードで誤字がありましたので、コメントさせて頂きました。
Destroy(h[0]・・・・・・
コメントありがとうございます!^^
誤字修正させていただきました。
最近unityを始めた初心者で参考にさせてもらいいています。質問なのですがBallObjectのスクリプト内で使用したChangeColorという単語にエラーが発生してしまいます…原因がわかりません、最新バージョンに対応していないのかなんなのか、
その質問文だとこちらも正直よくわからないです。
この講座を作成した際のバージョンは2019.3.3LTSですがサポート期間内ですしバージョン問題ではないと思います。
警告が出る可能性はありますが。
試しに2020の最新版LTSにアップグレードしましたがちゃんと動いてます。
ご参考になれば幸いです。
Unityの学習に利用させていただいています。非常にわかりやすく説明があり,助かっています。
ところで、先の質問にあるChangeColor()で私もエラーが発生しています。
エラーメッセージは
Assets\Scripts\BallObject.cs(14,14): error CS8112: 'ChangeColor()' is a local function and
must therefore always have a body.
です。
いろいろ調べましたが原因がわかりません。
いかがでしょうか?
この質問文だけだと正直こちらでは全然わからないですが、publicを付け忘れているのではないかなと思います。
改めて今講座の方再追試しながらリライトしていますがChangeColor関係のエラー等は出ませんでした。