投稿記事

脱出ゲームの記事 (6)

yosita/たんすかい 2024/04/06 17:16

【Unity推理脱出ゲーム】宴のParamTblで犯人当てを実装する

久しぶりの更新になります。
先日、Unityを2022にし宴4にバージョンアップしました。
推理脱出ゲームを夏コミに向けて絶賛開発中です。

今回は犯人当ての画面の作り方です。
演出関連はほぼ入ってないので一旦基本編(最低限の機能に絞った実装)になります。
開発中画面は以下です。


仕様としては以下です。

/// 1、犯人を推理するボタンを押されるとUIを表示
/// 2、宴から犯人数、犯人の名前、犯人の画像、犯人かのフラグ、を取得し、ボタンを生成。
/// 3、ボタンを押されると、ボタンをグレーアウトし、ユーザーの選択を記録
/// 4、OKボタンを押されると、ユーザーの選択を確認し、正解か不正解かを判定
/// 5、正解の場合は、正解用のシナリオを再生し、クリアフラグを立てる
/// 6,不正解の場合は、不正解用のシナリオ再生
宴から取得している
犯人数、犯人の名前、犯人の画像、犯人かのフラグなどは全て可変で
宴エクセルから変更可能です。

必要なパラメーターテーブル
犯人当て用の概要パラメーターテーブル
HanninHitOverviewTbl{}


CharaNumが犯人当てに表示するキャラ数

犯人当て詳細パラメーターテーブル
HanninHitDetailTbl{}


IsHanninがTrueが犯人です。
パラメーターテーブルを2つに分けることで入力内容をシンプルにしています

Unityインスペクターの設定例です


スクリプトは以下です。

HanninHitController.cs (11.02kB)

ダウンロード

特に難しい処理は入れてないですが
正解判定を
宴から取得したリスト
犯人フラグ配列(HanninHitArray)と
ユーザー入力配列HanninHitUserArrayの比較を行ってます。
スクリプト箇所は、ResultHanninHitです。
これで仮に犯人が0でも全員犯人でも対応可能(なはず)です。


    public void ResultHanninHit()
    {
        //正解判定
        bool IsCorrect = true;
        for (int i = 1; i < HanninHitArray.Length; i++)
        {
            if (HanninHitArray[i] != HanninHitUserArray[i])
            {
                IsCorrect = false;
                break;
            }
        }

        if (IsCorrect)
        {
            Debug.Log("正解");
            Success();
            
        }
        else
        {
            Debug.Log("不正解");
            Failed();
        }

    }

他には
Unity grid layout group
をキャラボタンの親オブジェクトに配置している為
キャラ数が多くなっても綺麗に配置される想定です。

本日は以上となります。良さそうな演出ができたら
また記事を書きます。
宴4は以下です。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

yosita/たんすかい 2023/12/03 10:41

冬コミ受かりました&頒布作品について

冬コミ(C103)受かりました!

参加情報
日時:12月31日(日)
スペース:東R_17ab です。
webカタログは下記です。
https://webcatalog.circle.ms/Circle/18007237

頒布物ですが
開発中の探偵のすすめ推理x脱出ゲームの体験版(新作)
探偵のすすめシリーズセット(既刊作)
の予定です。

新作については体験版になります、すいません。。
完成版のリリースはクオリティ及びボリューム等を考慮して
2024年夏目標とさせてください。

なお、冬コミで頒布予定の体験版は後日ダウンロード頒布予定です。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

yosita/たんすかい 2023/10/25 23:33

【Unity脱出ゲーム】宴のParamTblで数値組み合わせギミックを実装する

今回は、宴のParamTblを利用した数値組み合わせギミックについてです。
宴の公式サイトの解説はこちら

現在開発中の脱出ゲーム部分の
数値を組み合わせで開けるギミックの一部です。
脱出ゲームではよくある機能です。

実現したこと
脱出ゲーム用の仕掛けである
数字組み合わせギミックにおいて、ギミックの答え(数値)、答えの桁数、初期値、
正解時のシナリオ再生用のラベル、ギミックを解いた後の獲得アイテム
上記を宴Excelのみで完結できる作りにしています。

宴のParamTbl活用方法について
簡易的なデータベーステーブルに近い使い方をしています。
宴にはParamシートがありますが、開発中のゲームが変数の数が多いのと
どの機能に紐付いている変数なのかが分かりづらい為、途中からParamTblをシートを増やしスクリプトから呼び出しや更新を行っています。
ScriptableObjectを使う手もありますが、Excel管理は簡単なのと宴のシナリオがExcelなので宴内で完結した方が管理しやすいのがParamTbl採用した理由です。


注意としては、パラメータキーとパラメータは1対1のみで利用する方法となり、
取得と更新はパラメータのみです。
A列がパラメータキーです。
B列以降にパラメータをデータ型と一緒に入力しています。
Answerがギミックの答え、Lengthが入力の桁数、
InitialValueが初期値(ギミック表示時の初期値)、
Answer_Labelは正解したときに、再生される宴のシナリオラベル、
Drop_Item_Numberは、正解時に獲得できるアイテムのIDです。
ExcelのParamTblの設定例です。


ParamTbl読み込み例は以下です。


    /// <summary>
    /// 数字組み合わせギミックの生成用情報をとるNumericCombinationGimmickTbl{}
    /// </summary>
    /// <returns>InitialValue(初期値), Length(長さ),TitleText(タイトルテキスト)</returns>
    public (string, int, string) NumericCombinationGimmickInitiaInfo(string ID)
    //
    {
        int Length =
        Engine.Param.GetParameterInt
        ("NumericCombinationGimmickTbl[" + ID + "].Length");

        string InitialValue =
        Engine.Param.GetParameterString("NumericCombinationGimmickTbl[" + ID + "].InitialValue");

        string TitleText =
        Engine.Param.GetParameterString("NumericCombinationGimmickTbl[" + ID + "].TitleText");

        return (InitialValue, Length, TitleText);
    }

数字組み合わせギミック本体のスクリプトは以下です。

NumericCombinationGimmickController.txt (8.01kB)

ダウンロード
public class NumericCombinationGimmickController : MonoBehaviour
{
    [Header("NumericCombinationGimmic親")]
    [SerializeField] GameObject NumericCombinationGimmick = default;
    [Header("NumericCombinationGimmicのタイトルテキスト")]
    [SerializeField] TextMeshProUGUI GimmickTitleText = default;
    [Header("出力テキストボックス用_Prefab")]
    [SerializeField] GameObject OutPutTextBoxPrefab = default;
    [Header("出力テキストボックス用の親オブジェクト")]
    [SerializeField] GameObject OutPutTextBoxParentobj = default;
    [Header("NumericCombinationGimmic非表示用ボタン")]
    [SerializeField] GameObject ButtonDown = default;
    [Header("探索矢印右と左")]
    [SerializeField] GameObject ButtonRigt = default;
    [SerializeField] GameObject ButtonLeft = default;
    [Header("入力用のUI")]
    [SerializeField] GameObject InPutUI = default;


    public static NumericCombinationGimmickController instance;
    private void Awake()
    {
        instance = this;
    }

    /// <summary>
    /// ステージ情報を元にギミックをセットする
    /// </summary>
    public void SetGimmic()
    {

        (bool isExist, string ID) =
            EscapeParamUtageGet.instance.NumericCombinationGimmickID();

        if (isExist == false)
        {
            Debug.Log("数字組み合わせギミック存在なし" + ID);
            return;
            
        }

        NumericCombinationGimmick.SetActive(true);
        ButtonRigt.SetActive(false); ButtonLeft.SetActive(false);
        ButtonDown.SetActive(true);

        //初期値と長さとタイトルテキストをget
        (string InitialValue, int Length,string TitleText) =
        EscapeParamUtageGet.instance.NumericCombinationGimmickInitiaInfo(ID);
        Debug.Log("数字組み合わせギミックの情報" +"ID"+ ID +"桁数"+ Length+"初期値"+ InitialValue+"タイトルテキスト"+TitleText);
        GimmickTitleText.text = TitleText;


        string[] InitialValue_Array = new string[Length];
        for (int i =0;i< InitialValue_Array.Length; i++)
        {
            //左から一文字ずつ取り出す
            InitialValue_Array[i] = InitialValue.Substring(i, 1);

            Debug.Log(InitialValue_Array[i]);
        }

        SetOutPutTextBox(InitialValue_Array);
    }

    /// <summary>
    /// テキストボックスを生成し、初期値を設定
    /// </summary>
    /// <param name="InitialValue_Array"></param>
    private void SetOutPutTextBox(string[] InitialValue_Array)
    {
        GameObject OutPutTextBox;

        //表示用テキストボックスを生成
        for (int i = 0; i < InitialValue_Array.Length; i++)
        {
            OutPutTextBox = Instantiate(OutPutTextBoxPrefab, OutPutTextBoxParentobj.transform.position, Quaternion.identity, OutPutTextBoxParentobj.transform);
            OutPutTextBox.name = "TextBox" + i;
            TextMeshProUGUI textmeshPro = OutPutTextBox.GetComponent<TextMeshProUGUI>();
            //初期値を設定
            textmeshPro.text = InitialValue_Array[i];
        }
    }

    /// <summary>
    /// 数字が押されるとカウントアップ
    /// </summary>
    public void InputNumber()
    {
        TextMeshProUGUI OutPutTextBoxTextmeshPro = GetComponent<TextMeshProUGUI>();
        int TextNumber = int.Parse(OutPutTextBoxTextmeshPro.text);
            //0-9の1桁制御
            if (TextNumber == 9)
            {
                TextNumber = 0;

            }
            else
            {
                TextNumber = TextNumber + 1;
            }

        OutPutTextBoxTextmeshPro.text = TextNumber.ToString();
    }

    /// <summary>
    /// OK押した時に答えをチェック
    /// NGならUIを揺らす(transform.DOShakePosition)
    /// </summary>
    public void CheckAnswer()
    {

        GameObject[] OutPutTextBox = GameObject.FindGameObjectsWithTag("NumericOutPutText");

        StringBuilder input = new StringBuilder("");

        for (int i = 0; i < OutPutTextBox.Length; i++)
        {
            Debug.Log(OutPutTextBox[i].name);
            TextMeshProUGUI OutPutTextBoxTextmeshPro = OutPutTextBox[i].GetComponent<TextMeshProUGUI>();
            input.Append( OutPutTextBoxTextmeshPro.text);
        }

        Debug.Log(input+"入力された文字");

        //答えを取得
        string answer = EscapeParamUtageGet.instance.NumericCombinationGimmickAnswer();

        if (input.ToString() == answer) AnswerAfter();

        if (input.ToString() != answer)
        {
            //NGなのでUIを揺らす
            InPutUI.transform.DOShakePosition(1f, 3f, 30, 0, false, true);

        }
      
        

    }

    /// <summary>
    /// 当たった後
    /// ①宴にクリアフラグを立てる
    /// ②UI消去
    /// ③シナリオラベル取得
    /// ④シナリオ再生
    /// </summary>
    private void AnswerAfter()
    {

        GameObject[] clones = GameObject.FindGameObjectsWithTag("NumericOutPutText");
        foreach (GameObject clone in clones)
        {
            Destroy(clone);
        }


        ButtonDown.SetActive(false);
        NumericCombinationGimmick.SetActive(false);

        Destroy(GameObject.FindGameObjectWithTag("NumericCombinationGimmickThis"));


        //クリアフラグ
        EscapeParamUtageSet.instance.NumericCombinationGimmickClearFlag();


        //タップ時のシナリオラベルをとる
        string Label = EscapeParamUtageGet.instance.NumericCombinationGimmickAnswerLabel();



        //脱出ゲームシステム→宴入れ替え
        UtageInput.instance.ChangeSort();

        //宴シナリオ呼ぶ(裏でスタートまで進んでポーズ状態であること)
        UtageScenarioCall.instance.UtageScenarioPlay(Label);

    }

    /// <summary>
    /// 宴からギミックIDを渡して獲得アイテムを表示
    /// </summary>
    /// <param name="command">宴のArg</param>
    public void DropItemShow(AdvCommandSendMessageByName command)

    {

        string ID = (command.ParseCellOptional<string>(AdvColumnName.Arg3, "arg3"));
        //ギミックIDを元に獲得アイテム情報をget
        string itemNumber = EscapeParamUtageGet.instance.NumericCombinationGimmickDropItem(ID);

        Debug.Log("獲得アイテム表示idとitemNumber" + ID +","+ itemNumber);

        //アセットのファイル名と表示名をとる
        (string ShowName, string FileName) =
                EscapeParamUtageGet.instance.NumericCombinationGimmickDropItemInfo(itemNumber);

        Debug.Log("獲得アイテム表示" + ShowName + FileName);
        //表示名とアセット名を表示
        FieldItemPopUp.instance.ShowItem(ShowName, FileName);
        //      
        //アイテムbox_に渡す
        ItemBox.instance.SetItemBox(FileName, ShowName, itemNumber);

        //ユーザー情報更新(phaseの更新)
        (int User_Progress_Stg, int User_Progress_StgPhase, int User_Progress_Bground) =
        GetStageInfo.instance.SetUserPhaseUpdate();

        HideNumericCombinationGimmic();
    }


    /// <summary>
    /// 矢印↓でギミック消去
    /// テキストボックス削除
    /// </summary>
    public void HideNumericCombinationGimmic()
    {
        GameObject[] clones = GameObject.FindGameObjectsWithTag("NumericOutPutText");
        foreach (GameObject clone in clones)
        {
            Destroy(clone);
        }



        NumericCombinationGimmick.SetActive(false);
        ButtonRigt.SetActive(true); ButtonLeft.SetActive(true);
        ButtonDown.SetActive(false);
    }



}

NumericCombinationGimmickControllerの中で
宴の連携以外は
InPutUI.transform.DOShakePosition(1f, 3f, 30, 0, false, true);
でDOTweenの機能なども使っています。



宴のアセットは下記です。

本日は以上となります。少しでも参考になれば幸いです。

1件のチップが贈られています

チップを贈るにはユーザー登録が必要です。チップについてはこちら

yosita/たんすかい 2023/08/24 19:45

冬コミ申し込みしました

今年の冬コミ(C103)申し込みしました。


日程ですが、2023年12月30日(土)~31日(日)の予定です。
当落次第ですが、現在開発中の「探偵のすすめ」シリーズの新作を頒布予定です。
よろしくお願いします。

1件のチップが贈られています

チップを贈るにはユーザー登録が必要です。チップについてはこちら

yosita/たんすかい 2023/07/18 21:01

【脱出ゲーム】Unity簡易スライダーギミックの実装と宴連携

本日は脱出ゲームで使えそうな
Unityの簡易スライダーギミックの実装例です。
開発中の為、ギミックを解くと人形が獲得できるようになっています。

ギミックの解答とキャラの会話は全て宴から取得しています。
開発中の為、演出などは一部調整中です。

基本的にUIの設定は割愛しますがUnityのスライダーをほぼ初期設定で使っています。
Handleのアイコンは素材を設定しています。
inspectorの設定例です。


動画のように4つのスライダーをそれぞれ用意しています。
左から1、2、3,4のスライダー値を赤、黄色、オレンジ、紫、の4つのスライダーで持っています。
そして、スライダーのOn Value Changeで都度スクリプトを実行させて値を確認し、判定させています。スクリプトは以下です。
    [SerializeField] Slider slider0;//red
    [SerializeField] Slider slider1;//yellow
    [SerializeField] Slider slider2;//orange
    [SerializeField] Slider slider3;//purple
    [SerializeField] GameObject sliderGroup;
    public void SliderGetValue()
    {
        //SLiderGroup0
        //SLiderGroupのnameでいくつ目のSliderGimmicKかを判定
        int SliderGimmickNum = int.Parse((sliderGroup.name).Substring(11, 1));

        //宴から回答を取得
        string Answer = EscapeParamUtageGet.instance.SliderGimmickAnswer(SliderGimmickNum);
        Debug.Log("答え"+ Answer);

        int Anser0Int = int.Parse((Answer).Substring(0, 1));
        int Anser1Int = int.Parse((Answer).Substring(1, 1));
        int Anser2Int = int.Parse((Answer).Substring(2, 1));
        int Anser3Int = int.Parse((Answer).Substring(3, 1));

        if (slider0.value == Anser0Int && slider1.value == Anser1Int && slider2.value == Anser2Int && slider3.value == Anser3Int)
        {
            //正解
            Debug.Log("正解");
            GimmickSucess();

        }
        else
        {
            Debug.Log("不正解");
            GimmickFailureScenario();
        }

    }

宴からは下記関数でスライダーギミックの解答を取得しています。

    public string SliderGimmickAnswer(int SliderGimmickNum)
    //SliderGimmickの答えを返す
    {
        //SliderGimmick0_Answer"
        string Answer =
        Engine.Param.GetParameterString("SliderGimmick" + SliderGimmickNum+ "_Answer");

        return Answer;

    }

宴の設定値ですがParamシートの指定は下記です。


答えは2344です。 SliderGetValueの中のint.Parseで
「2」(赤)「3」(黄色)「4」(オレンジ)「4」(紫)の解答として
IF文判定しています。宴を除ければ基本的にはスライダーのsliderxx.valueで
値を取得しているだけなのでかなりシンプルにスクリプトを書けます。

ギミック正解、不正解時にシナリオを再生させていますが
そちらは別の機会に紹介します。

宴のアセットは下記です。

本日は以上となります。少しでも参考になれば幸いです。

1件のチップが贈られています

チップを贈るにはユーザー登録が必要です。チップについてはこちら

« 1 2

月別アーカイブ

記事を検索