【Unity】スタンプカードの作り方。コピペで動作する骨格となるスクリプト。

2022年8月25日

どうも、だらはです。
今回はスタンプカードの作り方をまとめてみました。

スポンサーリンク

機能

  1. スタンプが押せるのは決められた場所のみ。
  2. 複数の選択肢からスタンプを選択できる。
  3. スタンプを押すときに音声が鳴る。
  4. アプリ再起動しても押したスタンプを保存。

作り方

先ず最終的な動作イメージをつけるため、実行結果を表示します。
スタンプを押す場所の上に、任意のスタンプが表示されるように動作させます。
処理内容は次項から記載していきます。

◆動作イメージ

(a)スタンプが押せるのは決められた場所のみ。

先ずはスタンプを押す場所をUnityの機能を使って簡単に作るところから始めます。
[Project -> Sprites -> Circle]から円のSpriteを生成します。(任意の多角形も作れます)
スタンプも同じ方法で作っても良いですが、今回は分かりやすいようにJpeg画像を私の方で準備しました。

そうしたら、下図1を参考に各種コンポネントをアタッチしてください。
ユーザーからのクリック判定は、EventTriggerを使って後述スクリプトのtoStamp関数を指定します。
EventTriggerの使い方については、こちらの記事を参考にして頂けたらと思います。

本作業により、スタンプを押す場所が完成します。

◆下図1

◆スタンプを押す場所にアタッチするスクリプト(ItemStamp.cs)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemStamp : MonoBehaviour
{
    [SerializeField] string objActiveName;  //アクティブ化するオブジェクト名
    [SerializeField] string objSoundName;   //AudioClipの転送先
    [SerializeField] string objSendName1;   //ゲームオブジェクト転送先
    [SerializeField] string objSendName2;   //ゲームオブジェクト転送先

    GameObject objParent;       //親
    GameObject objParentP;      //親の親
    GameObject objItem;         //アクティブ化するオブジェクト
    CopyStamp copyStamp1;       //スタンプ(Crown)
    CopyStamp copyStamp2;       //スタンプ(Drop)

    AudioSource audioSource;
    AudioSource audioSourceMy;

    void Start()
    {
        objParent = transform.parent.gameObject;                        //親を取得
        objParentP = objParent.transform.parent.gameObject;             //親の親を取得
        objItem = objParentP.transform.Find(objActiveName).gameObject;  //アクティブ化するオブジェクトを取得

        audioSourceMy = GetComponent<AudioSource>();
        audioSource = GameObject.Find(objSoundName).GetComponent<AudioSource>();

        copyStamp1 = objItem.transform.Find(objSendName1).GetComponent<CopyStamp>();    //スタンプ(Crown)を取得
        copyStamp2 = objItem.transform.Find(objSendName2).GetComponent<CopyStamp>();    //スタンプ(Drop)を取得
    }

    public void toStamp()
    {
        audioSource.PlayOneShot(audioSourceMy.clip);    //音声を鳴らす
        objItem.SetActive(true);                        //アクティブ化

        copyStamp1.objCircle = transform.gameObject;    //スタンプ(Crown)にスタンプを押す場所を転送
        copyStamp2.objCircle = transform.gameObject;    //スタンプ(Drop)にスタンプを押す場所を転送

        objParent.SetActive(false);                     //非アクティブ化   
    }
}

スクリプトの処理はシンプルで、EventTriggerによってtoStamp()が呼ばれたら、
Selectオブジェクトをアクティブ化し、クリックしたオブジェクトをスタンプに渡す。(スタンプを押す場所の指定に使う)
その後、選択肢であるスタンプ一覧を表示します。
詳細は、スクリプトにコメントで記載しましたので参照頂けたらと思います。

(b)複数の選択肢からスタンプを選択できる。

次は選択肢であるスタンプ一覧を表示します。
(a)によってSelectオブジェクトがアクティブ化することでスタンプ一覧が表示されます。
今回も、下図2を参考に各種コンポネントをアタッチしてください。

なお、下図のOrder in Layerについてですが、これはSpriteの描画順を意味します。
円(Circle_Area1Circle_Area2)よりスタンプ(CrownDrop)を手前に描画したいため、円の設定を0、スタンプの設定を1としています。

本作業により、スタンプ一覧が完成します。

◆下図2

◆スタンプを押すためのスクリプト(CopyStamp.cs)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CopyStamp : MonoBehaviour
{
    [SerializeField] string objActiveName;  //アクティブ化するオブジェクト名
    [SerializeField] string objSoundName;   //AudioClipの転送先
    [SerializeField] GameObject selectItem; //押すスタンプ(Projectに保存したプレハブ)
    public GameObject objCircle;            //スタンプを押す場所

    GameObject objParent;       //親
    GameObject objParentP;      //親の親
    GameObject objItem;         //アクティブ化するオブジェクト

    AudioSource audioSource;
    AudioSource audioSourceMy;

    void Start()
    {
        objParent = transform.parent.gameObject;                        //親を取得
        objParentP = objParent.transform.parent.gameObject;             //親の親を取得
        objItem = objParentP.transform.Find(objActiveName).gameObject;  //アクティブ化するオブジェクトを取得

        audioSourceMy = GetComponent<AudioSource>();
        audioSource = GameObject.Find(objSoundName).GetComponent<AudioSource>();
    }

    public void Stamp()
    {
        audioSource.PlayOneShot(audioSourceMy.clip);            //音声を鳴らす
        GameObject obj = (GameObject)Instantiate(selectItem);   //スタンプ押す

        PlayerPrefs.SetString(objCircle.transform.name, selectItem.transform.name);     //key保存
        PlayerPrefs.Save();

        if (objCircle.transform.childCount >= 1)    //既にスタンプがある場合はスタンプを削除
        {
            for (int i = 0; i < objCircle.transform.childCount; i++)
            {
                Transform child = objCircle.transform.GetChild(i);
                Destroy(child.gameObject);
            }
        }

        obj.transform.parent = objCircle.transform;                 //階層をスタンプを押す場所に移動
        obj.transform.localPosition = new Vector3(0f, 0f, 0f);      //階層移動すると座標がバグるので位置を調整

        objItem.SetActive(true);        //アクティブ化
        objParent.SetActive(false);     //非アクティブ化   
    }
}

(c)スタンプを押すときに音声が鳴る。

スタンプを押すときに音声が鳴らせるにはスクリプトを書く必要がありますが、実は上述のスクリプトに処理を記載済みです。
具体的にはPlayOneShotという関数を使います。
使い方は以下の記事に別途まとめましたので参照頂けたらと思います。

◆スクリプトから動的に音声を再生する方法

(d)アプリ再起動しても押したスタンプを保存。

アプリを再起動しても押したスタンプを保存させるには、セーブ/ロード機能を実装する必要があります。
実は、セーブ機能に関しては既にCopyStamp.csに記載済みです。
具体的にはPlayerPrefs.SetStringPlayerPrefs.Saveという関数を使います。

ロード機能に関してはStampCardオブジェクトに後述のStampManagement.csをアタッチすることで実現します。
処理内容としては、PlayerPrefs.HasKeykeyの有無を確認し、PlayerPrefs.GetStringkeyの値を取り出します。
使い方は以下の記事に別途まとめましたので参照頂けたらと思います。

◆セーブ/ロード機能の実装方法

◆StampCardカードにアタッチするスクリプト(StampManagement.cs)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StampManagement : MonoBehaviour
{
    void Start()
    {
        for (int i = 1; i < transform.childCount + 1; i++)
        {
            if (PlayerPrefs.HasKey("Circle_Area" + i))  //keyが存在する場合
            {
                string keyString = PlayerPrefs.GetString("Circle_Area" + i);
                GameObject obj = (GameObject)Resources.Load("Stamp/" + keyString);
                obj = (GameObject)Instantiate(obj);

                GameObject objCircle = GameObject.Find("Circle_Area" + i).gameObject;

                obj.transform.parent = objCircle.transform;             //階層をスタンプを押す場所に移動
                obj.transform.localPosition = new Vector3(0f, 0f, 0f);  //階層移動すると座標がバグるので位置を調整
            }
        }
    }
}

最後に

いかがでしたでしょうか。
ちょっと、記事が長くなってしまいましたが、コピペで動作するようにまとめられました。
スタンプの削除機能は実装していないので、もし要望等あればまた記事にまとめようと思います。
その際は、コメント等頂けると嬉しいです!
スクリプトの最適化のご指摘なども頂けると嬉しいです:)

以上、だらはでした。

スポンサーリンク

応用

Posted by daraha_gm