2016-05-20 3 views
0

私は過去数日間、UIアイテムのドラッグアンドドロップシステムを開発し、できるだけ柔軟なものにしようとしていました。ユニティ3Dは私の問題にはあまり関係ありませんが)。私は正確に説明に入る前にここで問題が何であるかのコードです:ジェネリックと継承:ベースクラスとそのサブクラスでジェネリックを使用する

public class ItemHandler<ItemType> : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IHoverHandler where ItemType : Item { 

    public ItemType item { get; protected set; } 

    ... 
} 

public abstract class SlotHandler<ItemType> : MonoBehaviour, IDropHandler where ItemType : Item { 

    ... 

    public ItemHandler<ItemType> itemHandler { get; protected set; } 

    ... 

    public void OnDrop(PointerEventData eventData) { 

     // Retrieve the slots 
     SlotHandler<Item> originalSlotHandler = ItemManager.draggedItemParent.GetComponent<SlotHandler<Item>>(); 
     SlotHandler<ItemType> destinationSlotHandler = this; 

     // Retrieve the handlers from their items 
     ItemHandler<Item> originalItemHandler = originalSlotHandler.itemObject != null ? originalSlotHandler.itemObject.GetComponent<ItemHandler<Item>>() : null; 
     ItemHandler<ItemType> destinationItemHandler = destinationSlotHandler.itemObject != null ? destinationSlotHandler.itemObject.GetComponent<ItemHandler<ItemType>>() : null; 

     // Add the original item to the destination slot 
     bool canAddToDestination = originalSlotHandler is SlotHandler<ItemType> || originalSlotHandler is SlotHandler<Item>; 
     bool canRemoveFromOrigin = originalSlotHandler is SlotHandler<ItemType> || destinationSlotHandler is SlotHandler<Item>; 

     // Swap the items 
     if(canAddToDestination == true && canRemoveFromOrigin == true) { 

      // Remove the old items 
      originalSlotHandler.RemoveItem(); 
      destinationSlotHandler.RemoveItem(); 

      // Add the new items 
      originalSlotHandler.AddItem(destinationItemHandler); 
      destinationSlotHandler.AddItem(originalItemHandler); 

      ... 
     } 

     ... 
    } 

    public virtual void AddItem(ItemHandler<ItemType> itemHandler) { 

     this.itemHandler = itemHandler; 
    } 
} 
この背後にある考え方は、特定のタイプのItemHandler持つことです

(例えばItemHandler <宝石>、ItemHandler <武器を>など)とのみ同じ基本型の同じ型ORのSlotHandlerにドロップできるようにします。

  • ItemHandler <宝石> SlotHandler <宝石>とSlotHandler <項目>に入ります。
  • ItemHandler <武器> SlotHandlerに移動<武器> SlotHandler <アイテム>。

私は特定のアイテムを削除できるスロットを制限したいので、この方法でやってみました。

問題はSlotHandler < Item>(すべてのアイテムの基本クラスであるコードスニペットに表示されるItemクラス)という特定のタイプのスロットを考慮する必要があるという事実に由来します。インベントリスロットは、あらゆる種類のアイテムを保持できる必要があります。

ここで、ItemHandler < Gem>はItemHandler < Item>(または他の派生型Item)のサブクラスではないため、これは機能しません。今では、なぜItemを格納するのではなく、Generic ItemTypeを格納するだけでいいのでしょうか?私はここではSlotHandlerを派生させ、各サブクラスで異なる動作をする(異なるタイプのスロットにアイテムを落とすことは別々のことを行う)ことを考えています。

これは私がそれをやろうとしている方法ではうまくいかないと思っていますが、私は気持ちの良い解決策を見つけることができません。申し訳ありませんが、私は問題が十分に明確でない場合は、私は何かをクリアする必要があります私にお知らせください。

私の問題を解決しようとするお手伝いをしてくれてありがとうございました!

+0

あなたはUIシステム(Canvas)やメインゲームのシーンでこれをやっていますか? – Fattie

+0

ユニティはECSシステムです。それは決して漠然としていても、OOシステムではありません。 (Unityが現時点でコンポーネントを書くために使っている言語、C#は実際にOO言語ですが、それは無関係で無関係です。いつでも他の言語に変更することができます)あなたがしているようなもの。私がやるべきことは、あなたがそれをドラッグ可能にするコンポーネント(もちろん、ECSシステム)にアタッチできるコンポーネント "Draggable"を書くことです。そして、それはそれの終わりです。物語の終わり。 「スロット」に関して、あなたがそれらを行動させたいと思えば.... – Fattie

+0

...何らかの方法で行動します。すなわち、彼らはそれらにドラッグされたいくつかの項目を拒否することがあります、彼らはいくつかの場合、花火をプレイする可能性があります。その "スロットの振る舞い"、もちろん(それはUnityです)あなたは何かに落とせるはずです。関連する問題に関する最近のエッセイはありますか?http://stackoverflow.com/a/372​​43035/294884 – Fattie

答えて

0

私には、タイプを追跡する必要がありますが、実際に必要なのは、各アイテムの親のタイプ(およびその親)のレコードだけです。プログラミングの意味で型自体を使用するのではなく、単に文字列ラベルを使用して、アイテムの有効なタイプの階層の基本クラスにリストを作成するだけではありません。そうすれば、複雑な接続と組織を持つことができ、単一の文字列をリストと比較して有効かどうかを確認するだけで済みます。

using UnityEngine; 
using System.Collections.Generic; 

public class Item { 

    public List<string> validInvTypes = new List<string>(); 

    //... 
} 

public class Gem : Item { 

    //... 
} 

public class Ruby : Gem { 

    public Ruby() 
    { 
    validInvTypes.Add("Ruby"); 
    validInvTypes.Add("Gem"); 
    validInvTypes.Add("Item"); 
    } 

    //... 
} 

public abstract class SlotHandler<ItemType> : MonoBehaviour, IDropHandler where ItemType : Item { 

    //... 

    public void OnDrop(PointerEventData eventData) 
    { 
    //... 

    //string currentInvSlot 
    //Item droppedItem 

    if (droppedItem.validInvTypes.Contains(currentInvSlot)) 
     // Swap the items... 
    } 
} 
+0

これはうまくいくでしょうし、もっと簡単な解決策かもしれません。私が今やっていることは、最初にアイテムが正しいスロットに入っていると仮定して、最初のスロットタイプ最終的なスロットタイプ(基本的には実際のアイテムタイプを無視します)。私がこのアプローチで問題に遭遇した場合、私はあなたに試してみましょう。あなたのご意見ありがとうございます! –

関連する問題