NGUIでDragDrop

ayumegu(プログラマー)
よろしくお願いします。

なかなかまとまった時間が取れずにかけなかったブログを連休中にたくさんまとめて書いているあゆめぐです。
さてさて次はNGUIでシンプルな機能のDragDrop
早速行ってみよう!
今回作ったのはこんなの

機能としては シンプルにドラッグドロップできるだけです。
iTweenも使用しています

シーンの構成

  • UI Root:NGUI2Dのrootです。
    • Camera:NGUI用のカメラです
    • DeckScrollView:上段のデッキにあたる部分のスクロールビューです
    • ItemScrollView:下段のアイテムにあたる部分のスクロールビューです

UI Root


通常のrootに自分で作成したDeck Manager.csをアタッチ
これに二つのScrollViewを設定しています

DeckScrollView ItemScrollView

通常のScroll ViewにUICenter On ChildとUIGridをアタッチ

PrefabのUnit


Unitが一つのユニットにあたるPrefabです
Banner Lightは前の記事で作成したものなのでおきになさらず


UnitにはcolliderとUIDrag Scroll Viewをアタッチ
そしてドラッグドロップ用のUIDragDropItemを継承した独自で作ったクラスDragDropUnit.csをアタッチ
RistrictionにVerticalを指定して縦移動のみに制限しています。
(横移動はScrollViewの動作をするため)
Unitの下のSpriteが実際のアイコン画像です

ソース

作成したファイルは二つ

  • DeckManager.cs:UIRootにアタッチしたもの。チップを動的にScrollViewに入れるためのスクリプト
  • DragDropUnit.cs:UnitのprefabにアタッチしたUIDragDropItemを継承したスクリプト

DeckManager.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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using UnityEngine;
using System.Collections;

public class DeckManager : MonoBehaviour {

  public GameObject deckScrollViewObj;
  public GameObject itemScrollViewObj;
  private const int DECK_COUNT = 3;
  private const int DECK_UNIT_COUNT = 5;
  private const int ITEM_UNIT_COUNT = 10;
  private int itemUnitCount = 20;
  private const string PREFAB_UNIT = "Prefabs/Unit";

  private string[] unitSpriteList = new string[]
  {
      "Icon_Arrows",
      "Icon_BlindingLight",
      "Icon_Book",
      "Icon_Fireball",
      "Icon_Fireball2",
      "Icon_Leafs",
      "Icon_Shield",
      "Icon_Sword"
  };

  void Awake()
  {
      GameObject obj = null;
      for(int i = 0; i < DECK_COUNT; i++)
      {
          obj = new GameObject("Deck" + i);
          obj.transform.parent = deckScrollViewObj.transform;
          obj.transform.localScale = Vector3.one;
          UIGrid grid = obj.AddComponent<UIGrid>();
          grid.cellWidth = 100;
          grid.cellHeight = 100;
          grid.maxPerLine = 5;
          grid.pivot = UIWidget.Pivot.Center;
          for(int j = 0; j < DECK_UNIT_COUNT; j++)
          {
              GameObject unit = Instantiate(Resources.Load(PREFAB_UNIT)) as GameObject;
              unit.name = "DeckUnit" + (i * DECK_UNIT_COUNT + j);
              unit.transform.parent = obj.transform;
              unit.transform.localScale = Vector3.one;
              UISprite sprite = unit.transform.FindChild("Sprite").gameObject.GetComponent<UISprite>();
              sprite.spriteName = unitSpriteList[Random.Range(0, unitSpriteList.Length)];
          }
      }

      for(int i = 0; i < itemUnitCount; i++)
      {
          if(i % ITEM_UNIT_COUNT == 0)
          {
              obj = new GameObject("Item" + i);
              obj.transform.parent = itemScrollViewObj.transform;
              obj.transform.localScale = Vector3.one;
              UIGrid grid = obj.AddComponent<UIGrid>();
              grid.cellWidth = 100;
              grid.cellHeight = 100;
              grid.maxPerLine = 5;
              grid.pivot = UIWidget.Pivot.Center;
          }

          GameObject unit = Instantiate(Resources.Load(PREFAB_UNIT)) as GameObject;
          unit.name = "ItemUnit" + i;
          unit.transform.parent = obj.transform;
          unit.transform.localScale = Vector3.one;

          UISprite sprite = unit.transform.FindChild("Sprite").gameObject.GetComponent<UISprite>();
          sprite.spriteName = unitSpriteList[Random.Range(0, unitSpriteList.Length)];


      }
  }
}

DragDropUnit.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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
using UnityEngine;
using System.Collections;

public class DragDropUnit : UIDragDropItem {
  
  //コピーされたオブジェクト
  private GameObject clone;
  //選択されたユニットの種類
  private SelectUnit baseSelectUnitType;
  
  enum SelectUnit
  {
      DECK,
      ITEM
  }
  
  // ドラッグスタートで呼ばれる
  protected override void OnDragDropStart ()
  {
      base.mTrans = transform;
      
      // コピーを作成
      clone = NGUITools.AddChild(transform.parent.gameObject, gameObject);
      clone.transform.localPosition = transform.localPosition;
      clone.transform.localRotation = transform.localRotation;
      clone.transform.localScale = transform.localScale;
      clone.name = transform.gameObject.name;
      clone.layer = 5;       // UIのlayer
      
      // デッキのアイテムが選択されたかアイテムが選択されたかを保持
      if(transform.gameObject.name.IndexOf("DeckUnit") != -1)
      {
          baseSelectUnitType = SelectUnit.DECK;
      }
      else
      {
          baseSelectUnitType = SelectUnit.ITEM;
      }
      
      // クローンの色をグレーに
      clone.transform.FindChild("Sprite").gameObject.GetComponent<UISprite>().color = Color.gray;
      // ドラッグするオブジェクトをUI Root直下に移動
      transform.parent = GameObject.Find ("UI Root").transform;
      
      // ドラッグ中のオブジェクトのあたり判定を停止
      transform.gameObject.GetComponent<BoxCollider>().enabled = false;
      // ドラッグ中のオブジェクトが手前に来るようにUIPanelをアタッチして強制的に前へ
      UIPanel uiPanel = gameObject.AddComponent<UIPanel>();
      uiPanel.depth = 150;
      gameObject.GetComponent<UIDragScrollView>().enabled = false;
      base.OnDragDropStart();
  }
  
  // ドラッグ移動中に呼ばれる 
  // ホバーなどのエフェクトを出したいときにはここでRayを飛ばしてぶつかっていればエフェクト表示などをするとよい
  protected override void OnDragDropMove (Vector3 delta)
  {
      base.OnDragDropMove(delta);
  }
  
  // ドロップされたときに呼ばれる
  protected override void OnDragDropRelease (GameObject surface)
  {
      if(surface != null)
      {
          if(baseSelectUnitType == SelectUnit.DECK && surface.name.IndexOf("ItemUnit") != -1 ||
             baseSelectUnitType == SelectUnit.ITEM && surface.gameObject.name.IndexOf("DeckUnit") != -1)
          {
              UISprite baseUISprite = clone.transform.FindChild("Sprite").gameObject.GetComponent<UISprite>();
              string baseSpriteName = baseUISprite.spriteName;
              UISprite dropUISprite = surface.transform.FindChild("Sprite").gameObject.GetComponent<UISprite>();
              string dropSpriteName = dropUISprite.spriteName;
              baseUISprite.spriteName = dropSpriteName;
              dropUISprite.spriteName = baseSpriteName;
              Destroy(gameObject);
          }
          else
          {
              // 元の位置に戻すアニメーション(iTween)
              iTween.MoveTo(gameObject, iTween.Hash("x", clone.transform.position.x, "y",clone.transform.position.y, "time", 0.5f, "oncomplete", "moveReset", "oncompletetarget", gameObject));
          }
      }
      else
      {
          // 元の位置に戻すアニメーション(iTween)
          iTween.MoveTo(gameObject, iTween.Hash("x", clone.transform.position.x, "y",clone.transform.position.y, "time", 0.5f, "oncomplete", "moveReset", "oncompletetarget", gameObject));
      }

      // 元の色に戻す
      clone.transform.FindChild("Sprite").gameObject.GetComponent<UISprite>().color = Color.white;
      
      base.OnDragDropRelease(surface);
  }
  
  // 元の位置に戻すアニメーション完了イベント
  public void moveReset()
  {
      Destroy(gameObject);
  }
}

今回の感想

NGUIがDragDropをサポートしてくれてるとはいえ、詳細の処理は自分で実装しないといけないのでなれないと時間がかかる
それにしてもNGUIいろいろ用意されていて便利です。

はい、今回はここまで〜