Unityで簡単な2D脱出ゲームを作ってウェブサイトで公開してみよう 〜カーソルの変更〜

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
カーソルの変更

この記事を三行にまとめると

処理自体はたった一行
ね、簡単でしょう?
この設定はどっちでも良いんじゃね?
今回はクリックポイントの上にカーソルが来た時にカーソルを別の画像に変えるという処理を実装します。ここで言うクリックポイントとはクリックイベントがついている画像オブジェクトを指します。

カーソルの変更は「オブジェクトの上に乗ったらカーソルを別の画像に変える」「オブジェクトから離れたらカーソルを元に戻す」という二つの処理が必要になるので順番に作っていきましょう。いずれの処理もスクリプトで行います。

動画はこちらです。





スクリプトをセット

カーソルを変更させる処理自体はたった一行のコードで済むので、先にスクリプトの方から作成しちゃいましょう。

必要になるのはカーソル変更用の画像と、先ほど言った二つの処理を行うためのそれぞれの関数です。

public class Mouse : MonoBehaviour {
  public Texture2D cursor;

  pubilc void OnMouseEnter() {
    Cursor.SetCursor(cursor, Vector2.zero, CursorMode.ForceSoftware);
  }

  public void OnMouseExit() {
    Cursor.SetCursor(null, Vector2.zero, CursorMode.ForceSoftware);
  }
}

実際にコードを書くとこんな感じになります。これでカーソル変更用のスクリプトは完成です。ね、簡単でしょう?

cursor変数はカーソル変更用の画像です。「Texture2D」という型を使用します。これは2D用のテクスチャの型で、テクスチャってのは……なんすかね。物質の質感とか薄っぺらな嘘とかそんな感じの何かですが、とりあえずこの変数で画像を扱うことができます。

そして「OnMouseEnter」がカーソルを画像に変えるための関数で「OnMouseExit」がカーソルを元の矢印に戻すための関数です。やっていることはどちらも同じで「SetCursor」というカーソル変更用の関数を呼び出しているだけです。このSetCursor関数の引数に画像を渡せばカーソルがその画像に変化するし、何の値も渡さなければデフォルトの状態(元の矢印)に変化することになります。上記のように何の値も渡さないことを明示的に書く場合は「null」という、何のデータも含んでいない値みたいな意味を持つ値を渡します。本作ではあまり出番がないですが、プログラムの世界ではたびたび世話になる単語です。

「Vector2.zero」と「CursorMode.ForceSoftware」は後で説明します。

スクリプトを作成したら適当なオブジェクトのインスペクターに追加して、変数のところに変更したい画像をプロジェクトからドラッグ&ドロップすればOKです。

画像をセット



カーソルが乗った時のイベント

スクリプトができたところで、まずはクリックポイント上でカーソルを画像に変更させるためのイベントを作ります。

クリックイベントはEvent Triggerの「Pointer Click」というイベントで実装しました。あれと同じ要領で「Pointer Enter」というイベントでマウスオーバーのイベントを実装できます。

PointerEnter

あとはクリックイベントのようにスクリプトを追加したオブジェクトをドラッグ&ドロップしてきてOnMouseEnter関数をセットすれば、このオブジェクトの上にカーソルが乗った時にカーソルが画像に変化します。



カーソルが離れた時のイベント

カーソルがクリックポイントから離れた時の設定もやり方は一緒です。

Event Triggerの中に「Pointer Exit」というイベントがあるので、それを追加してOnMouseExit関数をセットしてレンジでチンしてオシマイだ。

PointerExit



画像の設定について

必須というわけではないのですが、個人的に一応気にしといた方が良いと思う点を二つほど。

カーソルに使用する画像はTexture Typeを「Cursor」にした方が良いです。画像のインスペクターで設定を変更できます。変更しなくても動くは動くんですが、コンソール画面に「いつまでTexture TypeをCursor以外にしてるの?」という警告が出ます。

それから同じくインスペクターの設定で「Max Size」というのがありますが、使用する画像が大きい場合はこのMax Sizeを小さい数値にすると画面で表示されるサイズも小さくできます。オブジェクトのWidthやHeightの設定みたいなもんですかね。



ホットスポット

先ほどSetCursor関数の中に「Vector2.zero」という表記がありましたが、これはホットスポットを設定しています。Vector2.zeroってのは「Vector2(0, 0)」と同じです。

これに関しては動画を見てもらった方が良いと思うんですけど(4:45あたりからホットスポットについて触れてます)、カーソルは矢印全体が当たり判定になっているわけではなく、矢印の先端部分に当たり判定があります。つまりクリックポイントの上に矢印のお尻の部分だけが乗っていても、それはまだカーソルがクリックポイントの上に乗ったことにはなりません。先端部分が乗って初めてクリック可能な状態になります。

この先端部分が画像のどの部分になるのかというのがホットスポットです。「Vector2(0, 0)」とした場合はホットスポットが画像の左上になります。だからカーソルが矢印から画像に変わる時、矢印の先端部分が画像の左上部分になります。画像のサイズが「24 × 24」だった場合にホットスポットを「Vector(24, 24)」とすると、矢印の先端部分が画像の右下部分と対応します。

本作はカーソルとしてはよくある人差し指がピーンってなってる画像を使っているので、ちょうど人差し指のところが矢印の先端部分に来るようにホットスポットを設定しています。

public class Mouse : MonoBehaviour {
  public Texture2D cursor;
  private Vector2 hotspot = new Vector2(10, 4);

  pubilc void OnMouseEnter() {
    Cursor.SetCursor(cursor, hotspot, CursorMode.ForceSoftware);
  }

  public void OnMouseExit() {
    Cursor.SetCursor(null, Vector2.zero, CursorMode.ForceSoftware);
  }
}



CursorMode

カーソルモードってのは実は僕もあまりよく分かってなくてですね……とりあえず「CursorMode.ForceSoftware」と「CursorMode.Auto」の二つがあるんですが、僕が自分で試した限りではどちらの設定にしてもあまり違いがなかったんですよね。違いとしてはForceSoftwareがソフトウェアのカーソル、Autoがハードウェアのカーソルを使用するという設定らしいです。

僕の認識ではソフトウェアはUnityのカーソル、ハードウェアはゲームをプレイしている端末(PCやスマホ)のカーソルということなんですが、でも今言ったように違いがあまりないので本当にそうなのかどうかもよく分からんってのが正直なところです。

あまり違いがない以上、この設定はどっちでも良いんじゃね?って気もしますが、僕自身が検証した限りでは、MicrosoftのEdgeで検証した時だけ、設定がAutoだとカーソルが画像に変化しないという状態になりました。

ブラウザによる挙動の違いはいつの時代もプログラマを泣かせるのだ

じゃあとりあえずForceSoftwareにしとけば問題ねーじゃんって言いたいところなんですけど、EdgeだとForceSoftwareでも矢印と画像の両方が同時に出ちゃうという現象が起きたりして、期待通りの動きにはなりませんでした。ウェブ制作をしているとブラウザによる挙動の違いに悩まされることはよくあるんですが、ゲーム制作でもその辺は変わらないようです。しかもこっちの方が直し方がよく分からない分、手強いっていうね……。






今回はここまでです。説明は相変わらず長くて申し訳ないですが、設定自体は簡単です。画像もね、カーソルの画像はフリー素材も結構ありますので、探すのも大変ではないかなと思います。

まあカーソルの変更ができないとゲームが作れないわけではないので、一通りゲームを作り終えた後に「ついでだからカーソルも変更しとくかな」くらいでも良いとは思います。そん時にこの記事や動画が参考になれば幸いです。

次回はヒント画面の表示を実装します。再びアクティブ状態の操作が活躍します。よろしくお願いしんめとりー。



本シリーズの記事の一覧はこちら
Unityで簡単な2D脱出ゲームを作ってウェブサイトで公開してみよう 〜エピローグ〜
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください