UI上でクリックしても、同時に画面クリックを判定しない。
Unityで作るノベルゲーム第4回は、UIボタンを押しても同時に画面クリック判定されない方法を紹介します。
- 第0回:「画面サイズ変更、ボタンとテキスト作成、UIの操作 」
- 第1回:「ExcelでCSVを作成して読み込む」
- 第2回:「画面クリックした回数だけCSVのテキストを表示する」
- 第3回:「csvのテキストを画面上に表示する」
- 第4回: 【本記事】
- 第5回:「CSVでテキスト、画像、音をパスで認識して呼び起こす方法」
- 第6回:「Auto機能の実装」
- 第7回:「クイックセーブ・ロードの実装」
- 第8回:「改造されないセーブ・ロード実装」
前回「第3回」では、UIボタンを使って、CSVのデータをConsoleウィンドウではなく、画面上にテキストを表示しました。
ノベルゲームでは、セーブやロード、オート機能、システムメニューを選択するためにUIボタンを押します。
しかし、前回の製作では、UIボタンを押すと、「Input.GetMouseButton」メソッドの「Input.GetMouseButtonDown()」の処理が実行されて、画面クリックも同時に判定されてしまいます。
ノベルゲーム以外でも、「Input.GetMouseButtonDown()」とUIボタンを同時に使うゲームを開発する機会が多く、UIボタンを画面に配置しても、画面クリックとUIボタンクリックを使い分けたい場面は多いかと思います。
本記事では、画面とUIボタンのクリック判定を別々にするコードを紹介します。
- UIボタンをクリックしても画面クリックが反応しない方法を知りたい。
- ノベルゲームを作りたい。
EventSystem.current.IsPointerOverGameObject()
「EventSystem.current.IsPointerOverGameObject()」は、ゲーム内のUI(ユーザーインターフェース)にポインタ(マウスやタッチ)が重なっているかどうかを確認します。つまり、UI上をクリックしていると、処理をキャンセルするコードです。
※ポインタにて、タッチはスマホやタブレットでタッチスクリーンを使う場合はコードが少し異なります。詳細は後述しています。
本メソッドを使うには、名前空間に「using UnityEngine.EventSystems;」を追加しなければエラーが発生するので、注意してください。
「EventSystem.current.IsPointerOverGameObject()」は「EventSystem.current」と「IsPointerOverGameObject()」に分けることができます。
現在のイベントシステムを取得します。イベントシステムは、UnityのUIイベントの制御するシステムです。
これは、現在のポインタがUI要素上にあるかどうかを判定するメソッドです。もしポインタがUI要素上にある場合、このメソッドはtrueを返します。UI要素の例としては、ボタン、テキストフィールド、パネルなどがあります。
if (EventSystem.current.IsPointerOverGameObject()) return; //マウス入力
また、スマホ向けのゲームの場合はマウス入力では正常に処理されず、UI上の入力しても画面クリックが判定されてしまいます。したがって、以下のようにコードを変更します。
if(EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) //スマホ入力
処理の一例
ここで、「EventSystem.current.IsPointerOverGameObject()」を使った簡単な処理を紹介します。
using UnityEngine;
using UnityEngine.EventSystems;
public class Script : MonoBehaviour
{
void Update()
{
// マウスカーソルがUI要素上にあるかどうかを確認
if (EventSystem.current.IsPointerOverGameObject())
{
Debug.Log("マウスカーソルはUI要素上にあります。");
}
}
}
マウスカーソルがUI上にある場合はconsoleウィンドウで処理が実行されます。
画面上に、UIテキストとUIボタンを追加して、スクリプトをアタッチして、再生ボタンを押します。
UIボタンを押しても画面が反応せずに、処理を実行する
ここからは、前述したメソッド「EventSystem.current.IsPointerOverGameObject()」を使用して、第2回のソースコードを修正と追加をして、目標であるUIボタンをクリックしても画面クリックが反応しない処理をします。
ソースコード
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.UI; // 「Unity」の標準UIを使用するために必要
using UnityEngine.EventSystems; // 追加(UI上の動作稼働)
public class csvReader : MonoBehaviour
{
private TextAsset csvFile;
private List<string[]> csvData = new List<string[]>();
int i = 0;
public Text NameText; // 名前を表示
public Text LogText; // セリフ・地の文を表示
void Start()
{
csvFile = Resources.Load("Data") as TextAsset;
StringReader reader = new StringReader(csvFile.text);
while (reader.Peek() != -1)
{
string line = reader.ReadLine();
csvData.Add(line.Split(','));
}
}
void Update()
{
// ボタンを押したときは画面クリック無効
if (EventSystem.current.IsPointerOverGameObject())
return;
if (Input.GetMouseButtonDown(0)) // マウス左ボタンが押されたとき
{
NameText.text = csvData[i][0]; // 名前を表示
LogText.text = csvData[i][1]; // セリフ・地の文を表示
if (i < csvData.Count - 1) // csvDataを全て読み込むまで1ずつ追加する。
{
i++;
}
}
}
}
思い通りのゲームが作れない
Unityでゲーム開発しているけど完成しない。
技術的な壁や知識不足が原因で、思い描いたゲームを実現するのは難しいです。
しかし、Udemyは動画で実践的なゲーム開発を解説していて、
購入した講座は再生・停止・スキップなどが可能なオンデマンド形式なので、
専門的な内容を自分のペースで学習できます。
Unityの機能を網羅したいや作りたいゲームがある人はUdemy学習を取り入れましょう。
数多くある講座の中から特におすすめな講座を3つ紹介します。
初夏のセール開催中!(5月23日まで)
対象のコースが1300円から。
Unityのはじめの一歩としておすすめ。開発例に物理挙動やアニメーションを使用しているので、今後の開発が円滑になる。
トランプを題材にした講座。カードゲームやボードゲーム開発に応用可能
UnityエンジンのインストールやC#の文法に加えて、App StoreとGoogle Playにゲームをリリース方法を解説。
解説
初めに、名前空間に「using UnityEngine.EventSystems;」を追加します。
前述したように、UI上で実行を処理するために必要なメソッド「EventSystem.current.IsPointerOverGameObject()」を稼働させるためです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.UI; //「Unity」の標準UIを使用するために必要
using UnityEngine.EventSystems; //追加(UI上の動作稼働)
つづいて、変数を定義します。
csvFileとcsvDataは、CSVファイルのテキストアセットとCSVデータのリストを保持するための変数です。
iは、int型変数で、CSVデータをどこを読み込んでいるか指定します。
「NameText」と「LogText」はUIテキストで画面にそれぞれ名前とセリフ・地の文を表示します。
private TextAsset csvFile;
private List<string[]> csvData = new List<string[]>();
int i = 0;
public Text NameText; // 名前を表示
public Text LogText; // セリフ・地の文を表示
Start()メソッドでは、Resources.Load() メソッドを使用して “Data.csv” を csvFile 変数に読み込んでいます。
このとき、 Resourcesフォルダ内にCSVファイルが配置されている必要があります。
StringReader reader で、csvFile のテキストデータを文字列として読み込むための StringReader オブジェクトを作成しています。これにより、CSVファイルの内容を行単位で読み込むことができます。
while 文で、reader に読み込む行が残っているかどうかをチェックするループです。reader.Peek() メソッドは、次の文字があるかどうかを確認します。-1 は行がなくなったことを示します。
string line は、reader から1行分の文字列を読み込みます。ReadLine() メソッドは、テキストの次の行を読み込み、文字列として返します。
csvData.Add(line.Split(‘,’)); は、読み込んだ行をカンマで区切り、各要素を配列に変換して csvData リストに追加します。これにより、CSVファイルの各行がリストの要素として格納されます。
void Start()
{
csvFile = Resources.Load("Data") as TextAsset;
StringReader reader = new StringReader(csvFile.text);
while (reader.Peek() != -1)
{
string line = reader.ReadLine();
csvData.Add(line.Split(','));
}
}
Update()メソッドでは、if文「EventSystem.current.IsPointerOverGameObject()」を使って、UI要素上にある時はtrue。
つまり、UI要素上でマウスがクリックされた場合に、他の処理をスキップして直ちに Update() メソッドを終了します。
これにより、ボタンなどのUI要素がクリックされた場合にはCSVデータの表示が行われないようになります。
if文「Input.GetMouseButtonDown(0)」はユーザーがマウス左ボタンをクリックしたときに実行を処理します。
UIテキスト「NameText.text」 は、A行、「LogText.text」はB行に相当します。
csvData.Count は、現在のインデックス i が csvData の要素数よりも小さい場合に、インデックス i をインクリメントで1ずつ増やします。
csvData.Count – 1 としているのは、csvData の最後の要素まで表示した後には増やさないようにするためです。
void Update()
{
//ボタンを押したときは画面クリック無効
if (EventSystem.current.IsPointerOverGameObject()) return;
if (Input.GetMouseButtonDown(0)) //マウス左押下
{
NameText.text = csvData[i][0]; //名前を表示
LogText.text = csvData[i][1]; //セリフ・地の文を表示
if (i <= csvData.Count -1) //csvDataを全て読み込むまで1ずつ追加する。
{
i++;
}
}
}
実演
ソースコードが完成しましたら、再生ボタンを押してください。
前回のコードに「EventSystem.current.IsPointerOverGameObject()」メソッドを追加しただけなので、特に操作は不要です。
実行をして、冒頭のような操作ができましたら、成功です。
まとめ
今回は、ボタンクリックで画面クリック判定しない方法を紹介しました。
UI上の処理をTrueにするには「EventSystem.current.IsPointerOverGameObject()」を使います。ただし、名前空間に「using UnityEngine.EventSystems;」を入れないとエラーが発生するので、注意が必要です。
スマホやタブレットでのゲームを開発する場合は、「EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)」とする必要があります。
第5回は、パスを利用してCSVからテキスト、画像、音を呼び起こす方法を解説しています。