特定のUIのみドラッグ&ドロップする。
ゲーム内では、プレイヤーはアイテムの装備やUI要素のカスタマイズ、
他にも建設やレベルデザインでオブジェクトを配置する際に、ドラッグ&ドロップ機能を利用します。
ドラッグ&ドロップの実装はゲーム開発の幅が広がり、
主にトランプやカードゲームなどで使用できるので習得したい機能の一つです。
本記事では、ゲームオブジェクトをドラッグ&ドロップを実装します。
- Unityでドラッグ&ドロップを使用したい。
- UIを画面に表示したい。
Canvas(UI全体)をドラッグ&ドロップで移動
Canvasは、ボタンやテキストなどUIを使用するときに表示されます。
ユーザーのマウス入力から稼働できるようにします。
Hierarchyウィンドウから「UI」で1つ選択します。
本製作では、Imageを例とします。
ソースコード
using UnityEngine;
using UnityEngine.EventSystems;
public class CanvasDragAndDrop : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
private RectTransform canvasRectTransform;
private bool isDragging = false;
private Vector2 offset;
private RectTransform draggedObject;
void Start()
{
canvasRectTransform = GetComponentInParent<Canvas>().GetComponent<RectTransform>();
}
public void OnPointerDown(PointerEventData eventData)
{
draggedObject = eventData.pointerCurrentRaycast.gameObject.GetComponent<RectTransform>();
if (draggedObject != null)
{
Vector2 localPointerPosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, eventData.position, eventData.pressEventCamera, out localPointerPosition))
{
offset = draggedObject.anchoredPosition - localPointerPosition;
isDragging = true;
}
}
}
public void OnDrag(PointerEventData eventData)
{
if (isDragging && draggedObject != null)
{
Vector2 localPointerPosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, eventData.position, eventData.pressEventCamera, out localPointerPosition))
{
draggedObject.anchoredPosition = localPointerPosition + offset;
}
Debug.Log(localPointerPosition);
}
}
public void OnPointerUp(PointerEventData eventData)
{
isDragging = false;
draggedObject = null;
}
}
思い通りのゲームが作れない
Unityでゲーム開発しているけど完成しない。
技術的な壁や知識不足が原因で、思い描いたゲームを実現するのは難しいです。
しかし、Udemyは動画で実践的なゲーム開発を解説していて、
購入した講座は再生・停止・スキップなどが可能なオンデマンド形式なので、
専門的な内容を自分のペースで学習できます。
Unityの機能を網羅したいや作りたいゲームがある人はUdemy学習を取り入れましょう。
数多くある講座の中から特におすすめな講座を3つ紹介します。
ビックセール開催中(10月11日まで)
対象のコースが1500円から(最大95%OFF)
Unityのはじめの一歩としておすすめ。開発例に物理挙動やアニメーションを使用しているので、今後の開発が円滑になる。
トランプを題材にした講座。カードゲームやボードゲーム開発に応用可能
UnityエンジンのインストールやC#の文法に加えて、App StoreとGoogle Playにゲームをリリース方法を解説。
容量不足を解消
Unityのプロジェクトは1.5GB~3.5GBと大きく、クリエイターはHDD・SSD増設が必要です。
価格 | 耐久性 | 静音性 | 読み書き | サイズ | |
HDD | 低 | 低 | 低 | 遅 | 大 |
SSD | 高 | 高 | 高 | 速 | 小 |
注目点は、HDDは安価だけど壊れやすい。SSDは丈夫だけど高価。
したがって、データの持ち運びをしない場合はHDD、持ち運びする場合はSSDがおすすめです。
- 据え置きHDD
- 外付けSDD
- 内蔵SSD
ぜひ、あなたのクリエイティブな作業環境に兼ね備えたストレージをお役立てください。
解説
- 名前空間
「UnityEngine」:Unityエンジンの基本機能にアクセスするために必要です。RectTransform、Canvasなど、UI要素を操作するために使用されます。
「UnityEngine.EventSystems」:UnityのUIイベントシステムを構成するインターフェースやクラスが含まれていて、ユーザーの操作(ドラッグ、クリックなど)に応答するためのインターフェース(IPointerDownHandler, IDragHandler, IPointerUpHandler)が対象です。
インターフェースを実装しており、UI要素のドラッグ&ドロップ機能を実現しています。
- フィールド(メンバ変数)
「canvasRectTransform」:このスクリプトがアタッチされているCanvasのRectTransformを保持します。UI要素の位置計算に使用されます。
「isDragging」:現在オブジェクトがドラッグされているかどうかを示すフラグです。
「offset」:ドラッグ開始時のオブジェクトのローカル座標とマウスの位置との差分を保持します。これにより、オブジェクトが正確にマウスの移動に追従します。
「draggedObject」:現在ドラッグされているUI要素のRectTransformを保持します。
- Startメソッド
親のCanvasからRectTransformを取得して、canvasRectTransformに保存します。
- OnPointerDownメソッド
マウスボタンが押されたときに呼び出されるメソッド(IPointerDownHandlerインターフェースの実装)。
ドラッグされたUI要素のRectTransformを取得し、ドラッグ開始時のオフセットを計算して保存します。
- OnDragメソッド
マウスがドラッグされている間に呼び出されるメソッド(IDragHandlerインターフェースの実装)。
現在のマウスの位置をCanvas内のローカル座標に変換し、オフセットを加算してUI要素を移動させます。
- OnPointerUpメソッド
マウスボタンが離されたときに呼び出されるメソッド(IPointerUpHandlerインターフェースの実装)。
ドラッグフラグをfalseに設定し、ドラッグされているUI要素の参照をクリアします。
実装
スクリプトをCanvasにアタッチします。
これにより、子オブジェクトのUIはドラッグ&ドロップの対象になります。
各UIをドラッグ&ドロップで移動
Canvas(UI全体)を動かせるようにしてしまうと、UIボタンやテキストなど全てのオブジェクトが対象になってしまいます。
したがって、動かしたいオブジェクトのみ処理できるようにします。
ソースコード
using UnityEngine;
using UnityEngine.EventSystems;
public class UIDragAndDrop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
private RectTransform rectTransform;
private Canvas canvas;
private CanvasGroup canvasGroup;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
canvas = GetComponentInParent<Canvas>();
canvasGroup = GetComponent<CanvasGroup>();
}
public void OnBeginDrag(PointerEventData eventData)
{
if (canvasGroup != null)
{
canvasGroup.alpha = 0.6f; // 半透明にする
canvasGroup.blocksRaycasts = false; // ドラッグ中にレイキャストを無効にする
}
}
public void OnDrag(PointerEventData eventData)
{
if (canvas != null)
{
rectTransform.anchoredPosition += eventData.delta / canvas.scaleFactor;
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (canvasGroup != null)
{
canvasGroup.alpha = 1f; // 元に戻す
canvasGroup.blocksRaycasts = true; // レイキャストを有効に戻す
}
}
}
解説
- フィールド(メンバ変数)
「rectTransform」:UI要素のRectTransformを保持します。RectTransformは、UI要素の位置やサイズを管理するために使用されます。
「canvas」:UI要素が含まれているCanvasを保持します。
CanvasはUI要素の表示とレイアウトを管理するためのコンテナです。
「canvasGroup」:UI要素にアタッチされているCanvasGroupを保持します。
CanvasGroupは、UI要素の透明度やレイキャストのブロックなどの設定を管理します。
- OnBeginDragメソッド
ドラッグ操作が開始されたときに呼び出されます(IBeginDragHandlerインターフェースの実装)。
もしCanvasGroupがアタッチされている場合、そのCanvasGroupの透明度を0.6に設定して半透明にし、レイキャストを無効にします。
ドラッグ中に他のUI要素によるクリックなどが干渉しないようにします。
- OnDragメソッド
ドラッグ中に毎フレーム呼び出されます(IDragHandlerインターフェースの実装)。
ドラッグされているUI要素のRectTransformの位置を、マウスの移動に追従させます。
canvasのscaleFactorを使って、UIの拡大縮小に対応させています。
- OnEndDragメソッド
ドラッグ操作が終了したときに呼び出されます(IEndDragHandlerインターフェースの実装)。
CanvasGroupがアタッチされている場合、そのCanvasGroupの透明度を元に戻して(1に設定)、レイキャストを再度有効にします。
ドラッグが終了した後のUI要素の挙動を正常に戻します。
実装
動かしたいUI「Image」にスクリプトをアタッチします。
冒頭で紹介したように、正方形のオブジェクトはマウスで稼働しますが、テキストは操作されません。
まとめ
ドラッグ&ドロップにはIPointerDownHandler, IDragHandler, IPointerUpHandlerなどを使用すると、マウスを入力しているとき、離したときなどの処理を実装できます。