i-school - HushSet と List の使い分けガイド
 ゲーム開発において、データの管理と操作は不可欠です。

 その中でも、HushSet と List は頻繁に使用されるデータ構造ですが、それぞれの適切な運用方法はどうするべきか、
HushSetとListの違いについて説明し、ゲーム内での実際の使用例を提供します。



HushSetとは?


 HashSet(ハッシュセット)は、一意な値のコレクションを管理するためのデータ構造です。
同じ値を重複して格納できないため、データの一貫性を保つのに適しています。

 例えば、ゲーム内のユニークなアイテムリストを管理するのに便利です。


参考サイト
MisroSoft
HashSet クラス


Listとは?


 Listは、順序付きの要素のリストを管理するためのデータ構造です。
要素の重複を許容します。また要素を追加すると末尾に加えられるため、順番の管理が用意です。

 例えば、プレイヤーの所持アイテムリストなど、順序が重要な場合に使用されます。

参考サイト
MisroSoft
List クラス


HushSetと List の主な違い


 HushSetとListの主な違いは以下です。それぞれを比較しながら見てみましょう。


1.一意性


HashSet: 一意な値しか格納できない。
List: 重複した値も格納できる。


2.順序


HashSet: 要素の順序は保証されない。
List: 要素の順序は保持される。


3.検索時間


HashSet: 一意な値を検索するのに非常に高速。
List: 要素を検索するのには適していないが、要素の位置にアクセスするのは速い。


ゲーム内での使用例


 詳細な比較を行うために、ゲーム内での具体的な運用に基づいたサンプルコードを提供します。
以下は、HushSetとListを使用してゲーム内でプレイヤーの所持アイテムを管理するサンプルコードです。

 それぞれ順番に掲載します。


1.HashSetの使用例



using System;
using System.Collections.Generic;

public class GameManager : MonoBehaviour
{
    HashSet<string> uniqueItems = new HashSet<string>();

    void Start()
    {
        // ユニークなアイテムを追加
        uniqueItems.Add("Sword");
        uniqueItems.Add("Shield");
        uniqueItems.Add("Potion");
        uniqueItems.Add("Sword"); // 重複したアイテムは追加されない

        // ユニークなアイテムの一覧を表示
        foreach (string item in uniqueItems)
        {
            Debug.Log(item);
        }
    }
}

 このサンプルコードでは、HashSetを使用してプレイヤーの所持アイテムを管理しています。
HashSetは重複を許容しないため、同じアイテムが複数回追加されることはありません。


2.Listの使用例



using System;
using System.Collections.Generic;

public class PlayerInventory : MonoBehaviour
{
    List<string> items = new List<string>();

    void Start()
    {
        // アイテムを追加
        items.Add("Sword");
        items.Add("Shield");
        items.Add("Potion");
        items.Add("Sword"); // 重複したアイテムも追加可能

        // アイテムの一覧を表示
        foreach (string item in items)
        {
            Debug.Log(item);
        }
    }
}

 このサンプルコードでは、Listを使用してプレイヤーの所持アイテムを管理しています。
Listは重複を許容するため、同じアイテムが複数回追加することができます。


使い分ける際の考え方


 HashSetとListの使い分けのポイントを順番に説明します。


1. 一意性の必要性を検討する

<HashSetの使用>

 一意な要素が必要な場合、つまり同じ値の要素が重複して存在しないことが求められる場合に使用します。

   例: プレイヤーの所持アイテムを重複しない形式(大事なもの系)で管理する場合、ユーザーの達成した成果(アチーブメント)など。


<Listの使用>

 同じ要素が複数回現れる可能性がある場合、Listを使用します。

   例: プレイヤーの行動ログ、スコアランキングのスコア、アイテムの所在地リスト、ゲーム内に登場している敵のリストなど。


2. 要素の順序が重要かどうかを考える

<HashSetの使用>

 要素の順序が重要でない場合、HashSetを使用します。一意性が重要で順序は問題ではない場合に適しています。
アイテムで言えば、持っているか、持っていないか、フラグ管理で言えば、そのフラグがオンかオフか、という形で、順番に左右されないケースです。


<Listの使用>

 要素の順序が重要な場合、Listを使用します。要素の追加や取り出しの順序が重要な場合に適しています。


3.検索やアクセスの効率を考える

<HashSetの使用>

 一意な要素を高速に検索する場合、HashSetが適しています。要素の追加や削除も高速です。


<Listの使用>

 特定の位置の要素にアクセスが必要な場合、Listを使用します。
要素の位置をインデックスで指定してアクセスするのに適しています。


4.メモリ使用量を考える

<HashSetの使用>

 一意な要素のみを格納するため、メモリ使用量が少ない傾向があります。


<Listの使用>

 重複した要素も格納できるため、同じ要素を複数回格納する場合、メモリ使用量が増加する可能性があります。


 
 これらのポイントを考慮しながら、プロジェクトの要件に合わせてHashSetとListの使い分けを行うことが大切です。
一意性、順序、検索の効率、メモリ使用量などの要因を検討し、適切なデータ構造を選択しましょう。

 初心者であっても、これらの基本的な考慮事項を理解すれば、HashSetとListの使い分けがより容易になります。


ユースケースとサンプルコード


 ゲームの進行状況などをフラグを利用して管理した場合のサンプルコードです。

 HashSetは一意な要素を格納するため、重複を許容せず、高速な検索が可能です。
以下に、HashSetを使用したフラグ管理のサンプルコードを示します。



using System.Collections.Generic;
using UnityEngine;

public class FlagManager : MonoBehaviour
{
    HashSet<string> flags = new HashSet<string>();

    /// <summary>
    /// フラグを設定します。
    /// </summary>
    /// <param name="flag">設定するフラグ名</param>
    void SetFlag(string flag)
    {
        flags.Add(flag);
    }

    /// <summary>
    /// 指定したフラグが設定されているかどうかを確認します。
    /// </summary>
    /// <param name="flag">確認するフラグ名</param>
    /// <returns>フラグが設定されていればtrue、設定されていなければfalse</returns>
    bool HasFlag(string flag)
    {
        return flags.Contains(flag);
    }

    /// <summary>
    /// 指定したフラグが設定されているかどうかを確認し、ログに出力します。
    /// </summary>
    /// <param name="flag">確認するフラグ名</param>
    void CheckAndLogFlag(string flag)
    {
        if (HasFlag(flag))
        {
            Debug.Log($"{flag} is set.");
        }
        else
        {
            Debug.Log($"{flag} is not set.");
        }
    }

    void Start()
    {
        // フラグの設定
        SetFlag("Flag1");
        SetFlag("Flag2");
        SetFlag("Flag1"); // 同じフラグを再度設定しても重複は無視される

        // フラグの確認とログ出力
        CheckAndLogFlag("Flag1");
        CheckAndLogFlag("Flag3");
    }
}

 このサンプルコードでは、HashSetを使用してフラグを管理しています。
同じフラグを複数回設定しても、HashSetは重複を無視します。

 また、HasFlagメソッドを使用して指定したフラグが設定されているかどうかを確認できます。

 HashSetは高速な検索を提供し、一意なフラグを管理するために非常に適しています。
したがって、フラグ管理の場面でHashSetを使用することは一般的な選択肢、アプローチとなるでしょう。


まとめ


 HushSetとListは、異なる用途に使用されるデータ構造であり、それぞれの特性を理解し、適切に選択することが重要です。
一意なアイテムの管理にはHashSetが適しており、順序が重要な場合にはListを使用できます。

 プロジェクトの要件に合わせて、適切なデータ構造を選択しましょう。