質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.43%

  • C#

    7979questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    4675questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Visual Studio

    2086questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • Windows 10

    1059questions

    Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

  • Unity2D

    1030questions

【Unity&C#】アイテムショップの実装

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 171

k2zu1112

score 5

前提・実現したいこと

現在、サッカーをモチーフにしたクリッカーゲームを作っている者です。
クリックによるスコアの上昇などの機能は出来たのですが、アイテムショップの機能を追加することに苦戦しています。
Scriptについてもですが、そもそもの構成要素などにも不安を抱えています。
まずは実装までの考え方を「文字で」理解したいです。
最終地点は、ゲーム内通貨を消費してアイテムを購入するシステムの構築です。
まさに以下の画像のようなイメージです。
イメージ説明

現状

UIのButton機能を使って配置・装飾(画像の挿入など)止まり

試したこと

右も左も分からない状態でどこへ向かえば良いのかわからず、とにかく書店やサイトを探しましたが類似例はほとんど見つかりませんでした。

 仕様

・アイテムは大きく分けて2種類(1クリック当たりの生産を増やす物、自動生成ぺースを高める物)
・ゲーム内で生産したゲーム内通貨を消費してアイテムを購入
・レベルマックス、アンロックはグレーアウト
・アイテム購入の際は「購入しますか?はいorいいえ」のようなシーンは設けず、クリック後すぐに購入・実装

見つけた参考になりそうなページ

理想は以下のようなものですが、用語を置き換えるだけで成立するのでしょうか...?
http://yasuaki-ohama.hatenablog.com/entry/2015/05/16/092032
http://yasuaki-ohama.hatenablog.com/entry/2016/07/06/235528

using System.Collections;
using Sy![![イメージ](f07998b715d0964338192328b8d658e7.png)ollections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;

public class GameManager : MonoBehaviour {

    //定数定義
    private const int MAX_ORB = 5000; //オーブ最大数
    private const int RESPAWN_TIME = 15; //オーブが発生する秒数
    private const int MAX_LEVEL = 5; //最大キーパーレベル

    //データセーブ用キー
    private const string KEY_SCORE = "SCORE"; //スコア
    private const string KEY_LEVEL = "LEVEL"; //レベル
    private const string KEY_ORB = "ORB"; //オーブ数
    private const string KEY_TIME = "TIME"; //時間

    //オブジェクト参照
    public GameObject orbPrefab; //オーブプレハブ
    public GameObject trophyPrefab; //トロフィープレハブ
    public GameObject canvasGame; //ゲームキャンバス
    public GameObject textScore; //スコアテキスト
    public GameObject imageKeeper; //キーパー
    public float clickrate = 0.5f;
    public GameObject ball;

    //メンバ変数
    private int score = 0; //現在のスコア
    private int nextScore = 400; //レベルアップまでに必要なスコア

    private int currentOrb = 0; //現在のオーブ数

    private int keeperLevel = 0; //キーパーのレベル

    private DateTime lastDateTime; //前回オーブを生成した瞬間

    private int[] nextScoreTable = new int[] { 100,200,300,400,500 }; //レベルアップ値

    private int numOfOrb; //まとめて生成するオーブの数

    // Use this for initialization
    void Start () {

        //データ削除メソッド
        //PlayerPrefs.DeleteAll();

        //初期設定
        score = PlayerPrefs.GetInt(KEY_SCORE, 0);
        keeperLevel = PlayerPrefs.GetInt(KEY_LEVEL, 0);

        nextScore = nextScoreTable[keeperLevel];
        imageKeeper.GetComponent<KeeperManager>().SetKeeperPicture(keeperLevel);
        imageKeeper.GetComponent<KeeperManager>().SetKeeperScale(score, nextScore);       

        RefreshScoreText();

    }

    // Update is called once per frame
    void Update () {
        //まとめて生成するオーブがあれば生成
        while (numOfOrb > 0)
        {
            Invoke("CreateNewOrb",0.1f*numOfOrb);
            numOfOrb--;
        }
    }

    //バックグラウンドへの移行時と復帰時(アプリ起動時も含む)に呼び出される

    private void OnApplicationPause(bool pauseStatus)
    {
        if (pauseStatus)
        {
            //アプリがバックグラウンドへ移行
        }
        else
        {
            //バックグラウンドから復帰
            //時間の復元
            string time = PlayerPrefs.GetString(KEY_TIME, "");
            if (time == "")
            {
                lastDateTime = DateTime.UtcNow;
            }
            else
            {
                long temp = Convert.ToInt64(time);
                lastDateTime = DateTime.FromBinary(temp);
            }

            numOfOrb = 0;
            //時間によるオーブ自動生成
            TimeSpan timeSpan = DateTime.UtcNow - lastDateTime;
            if (timeSpan >= TimeSpan.FromSeconds(RESPAWN_TIME))
            {
                while (timeSpan >= TimeSpan.FromSeconds(RESPAWN_TIME))
                {
                    if (numOfOrb < MAX_ORB)
                    {
                        numOfOrb++;
                    }
                    timeSpan -= TimeSpan.FromSeconds(RESPAWN_TIME);
                }
            }
        }
    }

    //新しいオーブの生成
    public void CreateNewOrb()
    {
        lastDateTime = DateTime.UtcNow;
        if (currentOrb >= MAX_ORB)
        {
            return;
        }
        CreateOrb();
        currentOrb++;

        SaveGameData();
    }

    //オーブ生成
    public void CreateOrb()
    {
        GameObject orb = (GameObject)Instantiate(orbPrefab);
        orb.transform.SetParent(canvasGame.transform, false);
        orb.transform.localPosition = new Vector3(
            UnityEngine.Random.Range (-100.0f, 100.0f),
            UnityEngine.Random.Range (-300.0f, -450.0f),
            0f);

        orb.GetComponent<OrbManager>().Flyorb();

        //ボールアニメーション
        StartCoroutine("ClickAnim");//"ClickAnim"のコルーチンを呼ぶ.

    }



    //オーブ入手
    public void GetOrb()
    {
        score += 1;
        //キーパー画像切り替えメソッド挿入予定

        //レベルアップ値を超えないように制限
        if (score > nextScore)
        {
            score = nextScore;
        }

        KeeperLevelUp();
        RefreshScoreText();
        imageKeeper.GetComponent<KeeperManager>().SetKeeperScale(score, nextScore);
        SaveGameData();



    }

    //スコアテキスト更新
    void RefreshScoreText()
    {
        textScore.GetComponent<Text>().text =
            score + "GOAL";
    }

    //キーパーのレベル管理
    void KeeperLevelUp()
    {
        if (score >= nextScore)
        {
            if (keeperLevel < MAX_LEVEL)
            {
                keeperLevel++;
                score = 0;

                KeeperLevelUpEffect();

                nextScore = nextScoreTable[keeperLevel];
                imageKeeper.GetComponent<KeeperManager>().SetKeeperPicture(keeperLevel);
            }
        }
    }

    //レベルアップ時の演出
    void KeeperLevelUpEffect()
    {
        GameObject trophy = (GameObject)Instantiate(trophyPrefab);
        trophy.transform.SetParent(canvasGame.transform, false);
        trophy.transform.SetSiblingIndex(5);

        Destroy(trophy, 0.5f);
    }

    //ゲームデータをセーブ
    void SaveGameData()
    {
        PlayerPrefs.SetInt(KEY_SCORE, score);
        PlayerPrefs.SetInt(KEY_LEVEL,keeperLevel);
        PlayerPrefs.SetInt(KEY_ORB,currentOrb);
        PlayerPrefs.SetString(KEY_TIME,lastDateTime.ToBinary().ToString());


        PlayerPrefs.Save();
    }

有識者の方、どうぞよろしくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • k2zu1112

    2019/01/06 12:51

    yukkuri様、ただいま編集しました。
    もし編集に仕方が違うようであれば、その際は一言いただけると幸いです。

    キャンセル

  • yukkuri

    2019/01/06 12:52

    すいません、私の説明がだめでした。
    ```C#
    using ...
    ```
    みたいな感じにしてください。

    キャンセル

  • k2zu1112

    2019/01/06 13:09

    今回はちゃんと修正出来たと思います。
    大変勉強になりました、ありがとうございます。

    キャンセル

回答 1

checkベストアンサー

0

質問いただきありがとうございます!
大まかな方針としてはゲーム内通貨をPlayerPrefsに書き込んで処理するのが良いと思います。

コード

これを好きなクラス名にして(MonoBehaviorは継承)ショップのシーンに貼り付けて下さい
UIのボタンからBuyを指定するとイベントを登録出来ます。
pricesをinspector画面から指定すると値段を設定できます(設定しないとエラー吐きます)。
moneydialogはお金が足りないときに表示されるダイアログのgameobjectです。使う場合は閉じるボタンにイベントを設定して下さい。いらなかったら消してください

アイテムの種類が多いのであればscriptableObjectを使った方がいいと思います

public GameObject moneydialog;
public List<int> prices;
public void Buy(int id){
    int a=0;
    string key="ITEM"+id;
    if(PlayerPrefs.HasKey(key)){
        a=PlayerPrefs.GetInt(key);
    }
    int m=0;
    if(PlayerPrefs.HasKey("SCORE")){
       m=PlayerPrefs.GetInt("SCORE");
    }
    if(m<prices[id]){
        moneydialog.SetActive(true);
        return;
    }
    m-=prices[id];
    a+=1;
    PlayerPrefs.SetInt(key,a);
    PlayerPrefs.SetInt("SCORE",m);
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/06 12:26

    bochan2様、昨夜に引き続きご質問への返答ありがとうございます。
    大まかな方針の件、理解いたしました。
    出来れば動くコードも頂戴したいと思っております。
    現在のスクリプトを追記しました。
    よろしくお願いいたします。

    キャンセル

  • 2019/01/06 15:14

    動くコードの作成ありがとうございます。
    ダイアログまで付けていただけて非常に嬉しいです。
    そこでコードについて1点質問なのですが、今回のゲーム中ではクリックにより生成されたものを”ORB”と呼んでおり、それがゴールへ飛んでいく演出を付けております。そして、飛んで行って消滅した後は「score」として得点を保存しております。
    それを踏まえた場合では、先ほどいただいたコードの”ORB”の部分は「score」への変更が必要でしょうか?
    同時並行で2つの質問にご回答いただいて本当に感謝しております。
    何度もお手数をおかけしますが回答の方宜しくお願い致します。

    キャンセル

  • 2019/01/06 15:53

    scoreでしたか
    修正しておきまづしておきます

    キャンセル

  • 2019/01/06 18:07

    すみません、非常に助かります。

    現在は作成していただいた文章をお借りして作業をしているのですが、文章の3~5行目の
    public void Buy(int id){
    int a=0;
    string key="ITEM"+id;
    部分の理解に少々苦しんでおります。
    他に出てきた変数を言葉でいうと、a=アイテム保有数、m=所持金(score)で合っているかと思いますが、"ITEM"と変数idは何を表しているのでしょうか?

    また、新たに"ITEM"を作る必要があるかと思いますが、"SCORE"や"ORB"などと同じように、データセーブ用のキーを作れば良いということでしょうか?
    初歩的な質問かもしれませんがよろしくお願いします。

    キャンセル

  • 2019/01/06 19:01

    仰るとおりアイテムごとに新しいキーを作るということです

    キャンセル

  • 2019/01/06 19:37

    ありがとうございます。
    コードがだいぶ読み取れるようになりました。
    コードのところであと一つだけ教えていただきたいのですが、変数idは言葉でいうと何と表現されるものでしょうか...?
    Buy(int id) は何を引数に取ったメソッドなのかがもう一つ分かりません。
    よろしくお願いします。

    キャンセル

  • 2019/01/06 21:02

    BuyはUIのボタンのInspector画面でイベントを設定するもので、Inspector画面からボタンごとに対応するidの値を設定するようにしました

    キャンセル

  • 2019/01/06 21:20

    ということはつまり、idの値=各Prices(アイテムの価格)ということでよろしいのでしょうか?

    キャンセル

  • 2019/01/11 13:04

    体調を崩して数日間寝込んでおり、返信が遅れてしまいました。
    ご回答本当にありがとうございました。

    キャンセル

同じタグがついた質問を見る

  • C#

    7979questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Unity

    4675questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Visual Studio

    2086questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • Windows 10

    1059questions

    Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

  • Unity2D

    1030questions