0

カスタムクラスアイテムのリストである単純な静的在庫クラスがあります。私はクラフト システムに取り組んでおり、何かをクラフトするときに、インベントリ リストから必要なアイテムを削除する必要があります。

削除するアイテムの配列をパラメーターとして受け取る呼び出し可能なメソッドを作成しようとしましたが、機能しません。

foreach ループが削除するアイテムを認識していないためだと思います。エラーメッセージは表示されません。機能しません。どうすればこれを達成できますか?

public class PlayerInventory: MonoBehaviour 
{
    public Texture2D tempIcon;

    private static List<Item> _inventory=new List<Item>();

    public static List<Item> Inventory 
    {
        get { return _inventory; }
    }

    public static void RemoveCraftedMaterialsFromInventory(Item[] items) 
    {
        foreach(Item item in items) 
        {
            PlayerInventory._inventory.Remove(item);
        }
    }
}

削除されるアイテムを表示する関数は次のとおりです。

    public static Item[] BowAndArrowReqs()
{
    Item requiredItem1 = ObjectGenerator.CreateItem(CraftingMatType.BasicWood);
    Item requiredItem2 = ObjectGenerator.CreateItem(CraftingMatType.BasicWood);
    Item requiredItem3 = ObjectGenerator.CreateItem(CraftingMatType.String);

    Item[] arrowRequiredItems = new Item[]{requiredItem1, requiredItem2, requiredItem3};

    return arrowRequiredItems;
}

そして、ここでそれが呼び出されます:

これは RecipeCheck 静的クラス内にあります。

PlayerInventory.RemoveCraftedMaterialsFromInventory(RecipeCheck.BowAndArrowReqs());
4

2 に答える 2

0

クラスがメソッドを実装していない場合、Itemデフォルトでは、それらが同じオブジェクトであるかどうかをチェックします。(同じ値を持つ 2 つのオブジェクトではありません ---同じオブジェクトです)。 IEquatable<Item>bool Equals(Item other)Object.Equals

どのようItemに実装されているとは言わないので、Equals() の書き方を提案することはできませんが、GetHashCode()Equal である 2 つのアイテムが同じハッシュ コードを返すようにオーバーライドする必要があります。

更新 (コメントに基づく): 基本的に、 List.Remove は次のように機能します。

  foreach(var t in theList)
  {
         if (t.Equals(itemToBeRemove))
              PerformSomeMagicToRemove(t);
  }

したがって、質問で指定したコードに対して何もする必要はありません。Equals() メソッドを Item に追加するだけです。

于 2013-06-28T01:48:19.770 に答える
0

私はジェームズの答えが好きですが(そしてそれは契約を十分にカバーしています)、この平等をどのように実装し、いくつかの観察を行うかについて話します。

最初に返されるリストには、同じタイプのオブジェクトが複数ある場合があります (例: BasicWood、String)。次に、新しいオブジェクトごとに使用される識別子が必要です。

RemoveCraftedMaterialsFromInventory(new [] { aWoodBlock })2 つの木片が互いにチェックされている (「等しい」) のと同じように、木片を削除するのは良くありません。これは、「クラフトに互換性がある」ということは、「同等であること」と必ずしも同じではないためです。

簡単な方法の 1 つは、特定のオブジェクトGuid.NewGuidごとに一意の ID (を参照) を割り当てることです。このフィールドは Equals メソッドで使用されます (排他的に使用される可能性もあります)。ただし、新しいオブジェクトがそれぞれ別のオブジェクトであるという最初の問題に戻ります。

それで、解決策は何ですか?それらを削除するときは、必ず同等の (または同一の) オブジェクトを使用してください!

List<Item> items = new List<Item> {
    new Wood { Condition = Wood.Rotten },
    new Wood { Condition = Wood.Epic },
};
// We find the EXISTING objects that we already have ..
var woodToBurn = items.OfType<Wood>
    .Where(w => w.Condition == Wood.Rotten);
// .. so we can remove them
foreach (var wood in woodToBurn) {
   items.Remove(wood);
}

さて、それは的外れですが、「Equals が解体されずに、指定されたタイプのアイテムが削除されるように、Recipe でこれを行うにはどうすればよいでしょうか?」ということになります。

LINQ または述語 (つまりList.FindIndex) をサポートする List メソッドを使用してこれを行うか、この場合にのみ使用される特別な Equatable を実装することができます。

述語を使用する実装は次のようになります。

foreach (var recipeItem in recipeItems) {
    // List sort of sucks; this implementation also has bad bounds
    var index = items.FindIndex((item) => {
       return recipeItem.MaterialType == item.MaterialType;
    });
    if (index >= 0) {
       items.RemoveAt(index);
    } else {
       // Missing material :(
    }
}
于 2013-06-28T01:58:31.243 に答える