LoginSignup
57
50

More than 1 year has passed since last update.

【Unity】Googleドライブとスプレッドシートでお知らせ機能実装(専用サーバー不要)

Last updated at Posted at 2022-07-11

本記事で出来るコト

お知らせ機能を「Googleドライブ」と「Googleスプレッドシート」で作ります。
GSSInfomation.gif

はじめに

ゲームクリエイターのべすとまんです。
突然ですが、自分の開発するゲームに「お知らせ」を実装したくなることありませんか?
本記事では、Googleドライブとスプレッドシートを使用し、Unity製のゲームへお知らせ機能を実装する方法を紹介します。
もちろん専用のサーバーを用意する必要もありません!

注意点

  • キャッシュせずに実行するたびに画像をダウンロードする方法のため、容量の大きい画像を指定すると通信料が大きくなる可能性があります。
  • 600ユーザー以上からのアクセスがあるとアクセス制限がかかる、などのGoogle側の制限(参照: 共有ドライブの制限)があるため、大規模ゲームへの実装は非推奨となります。
  • Googleへのアクセスができない環境での動作確認は行っておりません。
  • たまに一定時間Googleドライブ画像へのアクセスができない(SendWebRequest();が返ってこない)ことがあります。

内容

Googleスプレッドシートの対応

1. お知らせ用のスプレッドシートを用意

  • 新しいスプレッドシートを作成します。

    • 共有設定を「リンクを知っている全員」に変更します
      0010_Link.png
  • 作成したスプレッドシートのURLよりsheetIDをメモしておきます。(※後で使います)

    • https://docs.google.com/spreadsheets/d/***/edit#gid=0
      ↑URLの***の部分がsheetIDになります。
  • 表示用のsheetNameをメモしておきます。(※後で使います)

    • sheetNameとはGoogleスプレッドシートのタブの名前です。
    • 任意の名前でOKです。
      • お知らせ情報はsheetName指定により読み込みます。sheetNameを「本番環境」「ステージング」などに分けることでお知らせを出し分けることもできます。
        SheetName_.png

2. セルへデータ入力

  • 実際にお知らせを入力していきます。
  • 用意するカラムは以下になります。
Time Title ImageID 画像確認 Message
掲載日時 タイトル Googleドライブ画像ID (画像確認セル) お知らせ内容
  • 詳細

    • Time
      • お知らせ掲載日時を入力します。
    • Title
      • お知らせのタイトルを入力します。
    • ImageID
      • お知らせに載せたい画像をGoogleドライブにアップロードし、「リンクを取得」より取得したURLからImageIDをコピーして入力します。
      • https://drive.google.com/file/d/***/view?usp=sharing
        ↑ドライブ上の画像URLの***部分がImageIDになります。
        ※画像の共有設定は「リンクを知っている全員」に変更しておきます。
        詳細はGoogle Drive に保存した画像を直接呼び出せるURLの取得を参照してください。
    • 画像確認
      • Googleスプレッドシート上で画像を確認する用のセルのため、Unityからは参照しません。=image("http://drive.google.com/uc?export=view&id="&画像IDを乗せるセルへのセル参照(例:C2))と入力すると、セル内にURL+ImageIDにより指定されたドライブ上の画像が表示されて便利です。
    • Message
      • お知らせの内容を入力します。
  • 入力の例
    Sheet.png

  • 注意事項

    • セル内の文字は絶対に改行しないでください。
      • セル内で改行すると行の判別が正確に行われずエラーがおきます。
      • 改行をしたい場合は改行コード(UnityC#では「\n」)を用いましょう。

Unity側の対応

1. お知らせ表示用の大枠UIを作る

  • UI/Scroll Viewを生成して中央に配置しましょう。
    0001_createUI.png
  • 縦スクロールのみの場合はScrollbar Horizontalは消しましょう。
    0003_createUI.png
  • Contentには取得したお知らせがたくさん格納されるので、Vertical Layout GroupContent Size Fitterをアタッチします。そうすることで格納されたお知らせたちがいい感じに並びます。
    • Content Size FitterVertical Fitを「Min Size」にします。
      0004_createUI.png

2. お知らせ内容表示用のUIを作る

  • 「1. お知らせ表示用の大枠UIを作る」で作ったScroll Viewの中のContentの中にお知らせ内容表示用のUIを生成します。
  • 今回1つのお知らせに含む情報は「掲載時刻」「タイトル文字列」「画像」「内容文字列」のため、表示用のTextやImageを配置します。
    0110_createElement_2.png

3. スクリプトを用意してアタッチ

  • GSSInfomationElement.cs
    • 各お知らせ情報を表示するためのスクリプトです。

    • Unity超簡単!Googleスプレッドシートでパラメータ調節する方法(共同開発にオススメ)を参考にしています。

    • 「2. お知らせ内容表示用のUIを作る」で作ったGameObjectのまとめ親オブジェクト(ここではImage)にスクリプトをアタッチします。
      0210_element.png

    • インスペクターへの入力

      • titleText:タイトル表示用のText
      • timeText:お知らせ掲載日時表示用のText
      • image:画像表示用のImage
      • nowLoading:画像読み込み中に表示するGameObject
      • messageText:お知らせ内容表示用のText
    • 操作が完了したらまとめ親オブジェクト(ここではImage)の名前をInfomationElementに変更し、プレハブ化して、Scene上からはいったん削除します。

    • (後に紹介するGSSInfomationElement.csがGoogleスプレッドシートより取得したお知らせ数分のInfomationElementを生成します。)
      0220_elementPrefab.png

GSSInformationElement.cs
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class GSSInformationElement : MonoBehaviour
{
    [SerializeField] private Text titleText;
    [SerializeField] private Text timeText;
    [SerializeField] private Image image;
    [SerializeField] private GameObject nowLoading;
    [SerializeField] private Text messageText;

    Texture2D texture;

    /// <summary>
    /// おしらせ情報反映
    /// </summary>
    /// <param name="time">時間</param>
    /// <param name="title">タイトル</param>
    /// <param name="imageID">画像ID(https://drive.google.com/open?id={ID})</param>
    /// <param name="message">メッセージ</param>
    public void SetInformation(
        DateTime time,
        string title,
        string imageID,
        string message
    )
    {
        //タイトル表示
        titleText.text = title;
        //時間表示(いい感じに整形)
        timeText.text = time.Year + "年" + time.Month + "月" + time.Day + "日 " + time.Hour + ":" + time.Minute.ToString("00") + ":" + time.Second.ToString("00");
        //メッセージ表示
        messageText.text = message.Replace(@"\n", "\n");
        messageText.rectTransform.sizeDelta = new Vector2(messageText.rectTransform.sizeDelta.x, messageText.preferredHeight);
        //imageID指定があれば画像読み込み開始
        if (imageID == "")
        {
            image.gameObject.SetActive(false);
        }
        else
        {
            StartCoroutine(GetGoogleDriveImage(imageID));
        }
    }

    /// <summary>
    /// Google上の画像を読み込んで反映
    /// </summary>
    private IEnumerator GetGoogleDriveImage(string imageID)
    {
        nowLoading.SetActive(true);
        UnityWebRequest www = UnityWebRequestTexture.GetTexture("http://drive.google.com/uc?export=view&id=" + imageID);
        yield return www.SendWebRequest();
        nowLoading.SetActive(false);
        if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
        //if (www.isNetworkError || www.isHttpError)
        {
            Debug.LogError(www.error);
            //Debug.Log(www.error);
            yield break;
        }
        //画像をダウンロード
        texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
        //textureをSpriteに変換
        image.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
    }

    private void OnDestroy()
    {
        if (texture)
        {
            Destroy(texture);
            texture = null;
        }
    }
}

  • GSSInformation.cs
    • インスペクターで指定されるsheetIDとsheetNameよりGoogleスプレッドシート上の文字列を一括読み込みし、お知らせ要素を生成するためのスクリプトです。
    • 「1. お知らせ表示用の大枠UIを作る」で作ったScroll Viewにスクリプトをアタッチします。
      0310_Infomation.png
  • インスペクターへの入力
    * sheetIDsheetName:先ほどの「Googleスプレッドシートの対応」よりメモしたsheetID、sheetName
    * viewDays:何日前までのお知らせを表示するか
    * nowLoading:読み込み中に表示するGameObject
    * infomationElementPrefab:GSSInfomationElement.csをアタッチしたお知らせ表示用プレハブ
    * infomationElementContainer:お知らせ数分生成するinfomationElementPrefabの格納先
GSSInfomation.cs
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System;

public class GSSInformation : MonoBehaviour
{
    private void Start()
    {
        StartCoroutine(GetGSSInformation());
    }

    [SerializeField, Header("GSSシートID")] private string sheetID = "読み込むシートのID";
    [SerializeField, Header("GSSシート名")] private string sheetName = "読み込むシート";
    [SerializeField, Header("何日前までのお知らせを表示するか")] private int viewDays = 7;

    [SerializeField, Header("読み込み中表示")] private GameObject nowLoading;
    /// <summary>
    /// GSSからお知らせデータを取得
    /// </summary>
    IEnumerator GetGSSInformation()
    {
        nowLoading.SetActive(true);
        //スプレットシートのURL処理
        var tqx = "tqx=out:csv";
        var url = "https://docs.google.com/spreadsheets/d/" + sheetID + "/gviz/tq?" + tqx + "&sheet=" + sheetName;
        UnityWebRequest www = UnityWebRequest.Get(url);
        //リクエスト待機
        yield return www.SendWebRequest();
        nowLoading.SetActive(false);
        //エラーチェック
        var protocol_error = www.result == UnityWebRequest.Result.ProtocolError ? true : false;
        var connection_error = www.result == UnityWebRequest.Result.ConnectionError ? true : false;
        //エラーの場合は終了
        if (protocol_error || connection_error)
        {
            Debug.LogError(www.error);
            yield break;
        }

        var reader = new StringReader(www.downloadHandler.text);
        reader.ReadLine();//ヘッダー読み飛ばし

        //表示時間判定用の現在時刻
        var nowTime = System.DateTime.Now;

        //スプレットシートより受け取った文字列をお知らせへと変換
        while (reader.Peek() >= 0)
        {
            var line = reader.ReadLine();
            var elements = line.Split(',');
            for (var i = 0; i < elements.Length; i++)
            {
                elements[i] = elements[i].TrimStart('"').TrimEnd('"');
            }

            //時間判定
            var informationTime = DateTime.Parse(elements[0]);//配列0個目:お知らせ投稿時間

            //投稿時間が表示対象内ではないお知らせは表示しない
            if (informationTime < nowTime - new TimeSpan(viewDays, 0, 0, 0) || nowTime < informationTime)
                continue;

            //お知らせ要素追加
            var informationElement = CreateInformationElement();
            informationElement.SetInformation(
              time: DateTime.Parse(elements[0]),    //配列0個目:お知らせ投稿時間
              title: elements[1],                   //配列1個目:タイトル文字列
              imageID: elements[2],                 //配列2個目:Googleドライブ画像ID
                                                    //配列3個目:画像確認用の空セル
              message: elements[4]                  //配列4個目:内容文字列
            );
        }
    }

    [SerializeField, Header("お知らせ要素プレハブ")] private GSSInformationElement informationElementPrefab;
    [SerializeField, Header("お知らせ要素格納先")] private Transform informationElementContainer;
    /// <summary>
    /// お知らせ生成
    /// </summary>
    private GSSInformationElement CreateInformationElement()
    {
        var informationElement = Instantiate(informationElementPrefab);
        informationElement.transform.SetParent(informationElementContainer, false);
        return informationElement;
    }
}

実行結果

Googleスプレッドシート上に入力した情報を元に、Unity上でお知らせが展開されました。
0410_Play.png

57
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
50