ビヨンドランチのメンバー抽選するツールを作成


お疲れ様です。
システム開発室、松山です。

唐突ですが、弊社には「ビヨンドランチ」という制度があります。
月に1回、ランダムにグループ分けされたメンバーでランチに行き、普段絡むことの少ないメンバーとの交流を楽しめます。
会社からランチ代も補助されるので、なかなかにお得な制度です。

このグループ分けですが、組織文化委員会のメンバーが毎月 “人力” でやっているようだったので、
Unity の基本を復習がてらアプリを作成してみようと思います。

要件

① ボタンで、ランダムにグループ分け
② 各グループを1つの要素として、スクロールリストで表示
③ 社員名は Scriptable Object で管理
④ ランダムにグループ分けを行う
⑤ WebGL(ブラウザ)で動作(ビルド)
※ Unity 2019.4.11f1(LTS)で作成

こんな感じでしょうか。
本当に基礎的な機能がちょっとだけですが、順に組み立てていきましょう。

① 画面(UI)作成

見出しとバージョンは Text で適当に。
抽選用のボタンを追加して、大枠は OK です。
Canvas のサイズを適当に設定します。(※ スマホの癖で、1920x1080にして後で修正する羽目になりました)

大体、こんな感じです。
背景はそれっぽい無料画像を探して貼っておきました。

② スクロールリスト

みんな大好きスクロールリストです。
いつもここでハマっていたりします(涙)

先に、グループ毎の要素用に、Prefab を作成しておきます。
各グループ、リーダー 1名とメンバー 4 〜 5名の構成なのでこんな感じで。

メンバー決定時に名前を登録するので、Text を更新できるよう、ちょっとコードを作成しておきます。
機能としてはメンバーの設定と、表示切り替えくらいでしょうか。

public class GroupBoard : MonoBehaviour
{
    [SerializeField] private GameObject objBoard;
    [SerializeField] private List<GameObject> objList = new List<GameObject>();
    [SerializeField] private List<Text> txtName = new List<Text>();

    private List<string> memberNames = new List<string>();

    /// <summary>
    /// 起動時処理
    /// </summary>
    void Start()
    {
        Initialize();
    }

    /// <summary>
    /// 初期化
    /// </summary>
    public void Initialize()
    {
        memberNames.Clear();
        hide();        
    }

    /// <summary>
    /// 非表示(非アクティブ)
    /// </summary>
    private void hide()
    {
        // 全てのプレートを非表示
        foreach (GameObject obj in objList)
        {
            obj.SetActive(false);
        }

        // 下敷きを非表示
        objBoard.SetActive(false);
    }

    /// <summary>
    /// 表示(アクティブ)
    /// </summary>
    public void Show()
    {
        int mid = 0;
        objBoard.SetActive(true);
        for(int i=0; i<memberNames.Count; i++)
        {
            objList[mid].SetActive(true);
            txtName[mid].text = memberNames[mid];
            mid++;
        }
    }

    /// <summary>
    /// メンバー登録
    /// </summary>
    /// <param name="name">メンバー名</param>
    public void SetMember(string name)
    {
        memberNames.Add(name);
    }
}

肝心のスクロールリストですが、
メニューの UI > Scroll View
で必要なものは全て作成されます。簡単です。
あとは、ぽちぽち設定をしていきます。
・Scroll View のサイズを調整
・水平方向のスクロールは不要なので削除
・Viewport の Mask を Rect Mask 2D に変更
・Content の Height を調整
・グループの Prefab に Layout Element を追加
※ 今回は要素数が少ないので、要素の再利用は考慮しません。

大体、これで UI まわりの設定は完了です。

メモ)スクロールリストは、この記事が分かり易いです(感謝)
ScrollView 参考

③ Scriptable Object

リーダーの名簿と、社員の名簿を用意します。
Scriptable Object で管理・拡張をしやすくしておきましょう。

まず、ベースとなる定義を用意します。

[CreateAssetMenu]
public class BeyondMember : ScriptableObject
{
    public List<string> leaderList = new List<string>();
    public List<string> membeList = new List<string>();

}

メニューに Asset > Create に Beyond Member が追加されるので、これを実行します。
データが生成されるので、ここに社員名を登録していきます。
データは Resources に配置して読み込みし易くしておきましょう。

※ GitHub にアップするので、一旦ダミー名で登録しています。

メモ)Scriptable Object は、こちらが分かり易いです(感謝)
ScriptableObject 参考

④ ランダムにグループ分け

ここは Unity 機能ではなく、C# のコードですね。
ざっくり、以下の2点の説明をします。

Scriptable Object からのデータ読み込み

シンプルに Resources.Load() で読み込みできます。

private BeyondMember beyond;

beyond = Resources.Load<BeyondMember>("Beyond Member");

あとは List形式で、そのまま使うことができます。

ランダム選択

リーダーは固定なので、順に設定しておきます。(リーダー数 = グループ数)
各グループに対して、メンバーをランダムに抽出して配置していきます。
処理はこんな感じでしょうか。

/// <summary>
/// メンバーのランダム抽選
/// </summary>
private void lotteryMember()
{
    int gno = Random.Range(0, groupNum - 1);    // 起点となるグループ番号
    List<string> members = new List<string>(beyond.membeList);
    do
    {
        int num = members.Count;
        int mid = Random.Range(0, num);
        boardList[gno].SetMember(members[mid]);
        members.RemoveAt(mid);
        gno++;
        if (gno >= groupNum) gno = 0;
    } while (members.Count > 0);
}

※ List は単純に代入すると参照渡しになってしまうので、コンストラクタで複製します。

⑤ WebGL でビルド

WebGL に Switch Platform して Build します。
Index.html などいくつかのファイルが出力されるので、これをサーバーに配置して完了。
と思いきや、いくつかおかしなところがあります。

フォントが表示されていない

Editor 上では表示されていた日本語がブラウザ実行時に表示されません。
ちょっと調べると、Text コンポーネントの「Arial」は日本語が含まれないために表示されないようです。
メモ)こちらを参考に対応します(感謝)
WebGL で日本語フォントが表示されない
別途フォントをダウンロードして、使用するフォントを切り替えます。

画面レイアウトが崩れている

妙に解像度が低く、スクロールリストが見出しやボタンに重なって表示されてしまいます。
これも調べてみると、デフォルトの解像度が 960x600 になっているようです。
メモ)フォント含め WebGL でハマるポイントが説明されています(感謝)
WebGL 注意点
ビルド毎に index.html を調整するのもアレなので、今回は 960x600 でレイアウトを微調整して対応します。

まとめ

ひとまず、ランダムでグループ分けできる状態に出来たので完成です。
Unity の基本機能である uGUI と ScriptableObject を久しぶりに使いましたが、
ちょっとしたツールであれば、簡単に作成できますね。
WebGL 対応は初めてでしたが、フォントなど微妙なワナが隠されてました。。。

ビヨンドランチのツールとしては最低限の機能は入れられたので、今後余裕をみて以下の対応も加えたいと思います。

・年月を選択できるようにして、月毎のグループ分けを表示
・月毎のグループメンバーを保持
・ランダムでメンバーを決定する際、前月と同じメンバーを被らせない

このあたりまで対応できれば、結構使えるツールになるのではないでしょうか?
それでは、今回のお話はこれまでになります。

今回もサンプルプロジェクトを GitHub に上げておきます。
何かの参考にでもなれば幸いです。
Unity サンプル


この記事をかいた人

About the author

松山賢勝

2019年8月から横浜オフィスに勤務。
経歴としてはクライアント開発が多いため、クライアント寄りの記事が多いかも。
趣味は自転車(ロード)と競馬。