ゲームやアプリでは、
UI(ユーザーインターフェース)・UX(ユーザーエクスペリエンス)
のデザインがとても重要です。
ゲーム開発ってシステムやコンピュータが好きな人が、
始めやすいものかな、と思ったりします。
なので、デザインは後回しにしがち!?
(自分がそうだった)
本記事では、ゲームのUIを少しでも改善できる
”ボタン”の作り方を解説します↓
要するに、アニメーションをつけます。
といっても、Animatorなどは使いません。
”DOTween”という、開発者のほとんどが使っていると言える
人気の無料アセットで、超簡単に作っていきます。
そして、DOTweenとEventSystemsをコーディングして作ります。
Inspector上での作業がなくなり、スクリプトをアタッチするだけで
ボタンのクリック、ホバー、選択のときに、アニメーションするようになります。
初心者の場合、Inspectorで設定するほうが視認性があってわかりやすいじゃん、となるかもしれませんが、
ゲームを開発を進めていくと、
スクリプトだけで設計されたモノのほうが圧倒的に、修正を加えるのが楽です。
(何十、何百ものボタンをそれぞれInspector上で修正なんかやってられない!)
このボタンはすぐゲーム開発に使える他、
DOTweenの使い方もわかるので、自分でアレンジもできるようになるはずです。
1.DOTweenをインポート
プロジェクトにDOTweenを入れていない方は、
アセットストアより、ダウンロード→インポートしてください。
DOTween (HOTween v2)(無料版)とDOTween Pro(有料版)がありますが、
主にはTextMeshProに対して、アニメーションを適用するなら、
有料版である必要があります。
インポートしたら、DOTweenのパネルが表示されます。
「Setup DOTween」をクリックしてから、閉じればOKです。
2.ボタン作成
早速ボタン作成に取り掛かります。
Createから、UI_Buttonを作成するだけです。
とりあえず、3つくらい作りましょう。
また、Canvas Groupというコンポーネントをつけます。
これはそのオブジェクトおよびその配下のオブジェクトのアルファ値(不透明度)を
一斉にコントロールするのに便利なコンポーネントです。
そして、ButtonScriptというスクリプトを作成して、アタッチします。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using DG.Tweening; //DOTween使用に必要 using UnityEngine.UI; public class ButtonScript : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler, ISubmitHandler { CanvasGroup canvasGroup; Image image; Text text; Button button; void Start() { canvasGroup = GetComponent<CanvasGroup>(); image = GetComponent<Image>(); text = this.transform.GetChild(0).gameObject.GetComponent<Text>(); button = GetComponent<Button>(); } void IPointerClickHandler.OnPointerClick(PointerEventData eventData) { if(!button.interactable){return;} Debug.Log("クリック!"); } void IPointerDownHandler.OnPointerDown(PointerEventData eventData) { if(!button.interactable){return;} transform.DOScale(0.9f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); canvasGroup.DOFade(0.8f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); } void IPointerUpHandler.OnPointerUp(PointerEventData eventData) { if(!button.interactable){return;} transform.DOScale(1.2f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); canvasGroup.DOFade(1f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); } void IPointerEnterHandler.OnPointerEnter(PointerEventData eventData) { if(!button.interactable){return;} transform.DOScale(1.2f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); image.color = new Color(1f, 0f, 0f); text.color = new Color(1f, 1f, 1f); } void IPointerExitHandler.OnPointerExit(PointerEventData eventData) { if(!button.interactable){return;} transform.DOScale(1f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); image.color = new Color(1f, 1f, 1f); text.color = new Color(0f, 0f, 0f); } void ISelectHandler.OnSelect(BaseEventData data) { if(!button.interactable){return;} transform.DOScale(1.2f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); image.color = new Color(1f, 0f, 0f); text.color = new Color(1f, 1f, 1f); Debug.Log("選択!"); } void IDeselectHandler.OnDeselect(BaseEventData data) { if(!button.interactable){return;} transform.DOScale(1f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); image.color = new Color(1f, 1f, 1f); text.color = new Color(0f, 0f, 0f); Debug.Log("選択解除!"); } void ISubmitHandler.OnSubmit(BaseEventData data) { if(!button.interactable){return;} var sequence = DOTween.Sequence(); sequence .Append(transform.DOScale(0.9f, 0.1f).SetEase(Ease.OutCubic)) .Join(canvasGroup.DOFade(0.8f, 0.1f).SetEase(Ease.OutCubic)) .AppendCallback(() => { Debug.Log("決定!"); }) .Append(transform.DOScale(1.2f, 0.1f).SetEase(Ease.OutCubic)) .Join(canvasGroup.DOFade(1f, 0.1f).SetEase(Ease.OutCubic)).SetLink(gameObject); } }
各Buttonオブジェクトにアタッチすれば、終わりです。
スクリプトが少しボリュームある内容となっていますが、
これはボタンに対して
・クリック(OnPointerClick)
・クリックした時(OnPointerDown)
・クリックやめた時(OnPointerUp)
・マウスカーソルを置いたとき(OnPointerEnter)
・マウスカーソルを離したとき(OnPointerExit)
・選択(OnSelect)
・選択解除(OnDeselect)
・決定(OnSubmit)
の処理をそれぞれ書いているからに過ぎません。
ぶっちゃけ、クリックとマウスカーソルを置く・離すだけで基本十分です。
もし、マウスでボタンをクリックせず、
キーボードなどからボタンを選択していくゲームを考えている場合、
選択、選択解除、入力の処理を書かないとアニメーションしてくれません。
ここでのアニメーションのコードについて説明します。
まず
if(!button.interactable){return;}
については、Buttonコンポーネントのinteractable、
つまりボタンが機能するかどうかというboolがfalseなら、
これらのスクリプトによるボタン機能ははたらかないようにしています。
スクリプトによってボタンの機能を付けている分、
Inspector上でButtonのinteractableをfalseにしても機能してしまうので、
この条件分岐を各関数の冒頭に置いています。
次に、
●クリックした時(OnPointerDown)。
transform.DOScale(0.9f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject); canvasGroup.DOFade(0.8f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject);
これはDOTweenのコードです。
Buttonオブジェクトのtransformに対して、
DOScaleで、Scale(x,y,z)を0.9に、0.24秒かけて変化させるアニメーション処理をしています。
SetEaseは、変化の仕方を設定するもので、OutCubicは初速が早い変化です。
SetLinkは、DOTweenによるその処理を終わらせるために末尾に記述します。
(これがないと、シーン移動時にエラーを吐くことがある)
ButtonオブジェクトのcanvasGroupコンポーネントに対して
DOFadeで、アルファ値を0.8に、0.24秒かけて変化させるアニメーション処理をしています。
初心者の方も、なんとなくDOTweenの使い方わかってきたはずです?
「変化させる値、時間、変化のさせ方」
これらの要素をたった1行で実装できるのがDOTweenの便利なところ。
キーフレームを打つよりも早いので、DOTweenでできるアニメーションは極力コードに任せましょう!
クリックをやめたときは大体その逆の変化です。
それではクリックしてない、単なるホバー時の処理をみていきます。
●マウスカーソルを置いた時(OnPointerEnter)
transform.DOScale(1.2f, 0.24f).SetEase(Ease.OutCubic).SetLink(gameObject);
image.color = new Color(1f, 0f, 0f); //赤色へ
text.color = new Color(1f, 1f, 1f); //白色へ
DOScaleで、Scale(x,y,z)を1.2に、0.24秒かけて、拡大させるアニメーション処理です。
と同時に、ボタンの色、Buttonというテキストの色も変化させています。
new Color(■,△,▲)は「RGB 0-1.0」で表される色の値です。
※色もDOTweenのDOColorという機能でアニメーションさせても良かったですが、
これは単なる処理で済ませました^^;
マウスカーソルを離した時は大体その逆の処理となっています。
さて、キーボードなどでボタンを選択させる人のみ対象の
選択・選択解除・決定についてですが、
選択は、マウスカーソル置いた時と同じ処理です。
そして、選択解除もマウスカーソルを離した時と同じ処理です。
ボタンが赤くなって大きくなってもらえば、選択中であることは十分わかりますよね!
●決定(OnSubmit)は、ボタン選択時にEnterキーを入力することです。
(ButtonでいえばPressed Colorになること)
クリックしたとき→クリック→クリックをやめたときの3つの処理を
DOTweenのSequenceによって順番に行っています。
.Join(canvasGroup.DOFade(0.8f, 0.1f).SetEase(Ease.OutCubic))
簡単に言うと、Append(次の処理)、Join(上と同時に処理)という意味合いです。
AppendCallbackは、アニメーションの後に通常の処理を入れたいときに使います。
その後、クリックをやめた時の処理が行われていきます。
通常、マウスカーソルを置いたときや選択時の処理は
Inspector上でEventTriggerというコンポーネントを追加し、設定するものですが、
このスクリプトなら、Buttonにアタッチするだけで、全て簡潔します。
便利ですね!
ボタンによる実際の処理もスクリプト記載するだけで、
同スクリプトをもつボタンに一斉に適用できます。
ぜひ皆さんも
このボタンのスクリプトを使って、
秒でアニメーションするボタンを作ってUIを改善してみてください^^