【unity】3D脱出ゲーム作成_その14

3D脱出ゲーム

ダイヤル合わせ

脱出ゲームでよくあるダイヤル合わせを作りたいと思います。電線を正しく繋げると通電するといった設定です。まずはシリンダー及びシリンダーボックスそれぞれの子として以下のように細長いプレートとクリア目視用の正方形プレート+TextMeshを追加します。

前回作った主電源をオン→lampからPOWERSUPPLYとTRAINまで線を繋げる事が出来ればクリア。繋げる方法はシリンダーを回転させるのみです。繋がった状態→あえてy軸(表面)回転させたのが画像の状態です。つまり全てのシリンダーのy軸=0=クリアとなります。今回は45度単位の回転ギミックにするので45度単位でずらしてください。

プレートには以下のようにそれぞれタグを設定しましょう。

・lampからPOWERSUPPLY→Uroad

・lampからTRAIN→DRoad

またプレートの親シリンダーにもUcylinder、Dcylinderのタグを設定します。

クリア状態=シリンダーy軸=0
初期状態はシリンダーy軸をあえて回転させる

ここまで出来たら各シリンダーに新たにスクリプトを設定

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Cylinder : MonoBehaviour
{
    public GameObject CeilingLight;//電源がついてる事の確認用に天井ライト
    public AudioClip sound1;//カチッ
    AudioSource audioSource;
    void Start()
    {
        audioSource = GetComponent<AudioSource>();
    }
    public void CylinderClick()
    {
        if (CeilingLight.activeSelf)
        {
            audioSource.PlayOneShot(sound1);
            transform.Rotate(0, 45, 0);
            PowerBox.instance.Correct();//他スクリプトから参照
        } 
    }
}

powerboxクラスにコード追加します。


bool flagA, flagB;//A=Uroadが揃った、B=Droadが揃った
public GameObject PPS, PT;//POWERSUPPLYとTRAINのクリア目視プレート
public AudioClip sound3;//ピコン
public static PowerBox instance;//他スクリプトで参照
public void Awake()//他スクリプトで参照
{
   if (instance == null)
   {
       instance = this;
   }
}
public void Correct()
{
  GameObject[] uroads = GameObject.FindGameObjectsWithTag("Uroad");
  GameObject[] droads = GameObject.FindGameObjectsWithTag("Droad");
  GameObject[] ucylinders = GameObject.FindGameObjectsWithTag("Ucylinder");
  GameObject[] dcylinders = GameObject.FindGameObjectsWithTag("Dcylinder");
  float uca = Mathf.Floor(ucylinders[0].transform.localEulerAngles.y);
  float ucb = Mathf.Floor(ucylinders[1].transform.localEulerAngles.y);
  float ucc = Mathf.Floor(ucylinders[2].transform.localEulerAngles.y);
  float ucd = Mathf.Floor(ucylinders[3].transform.localEulerAngles.y);
  float dca = Mathf.Floor(dcylinders[0].transform.localEulerAngles.y);
  float dcb = Mathf.Floor(dcylinders[1].transform.localEulerAngles.y);
  float dcc = Mathf.Floor(dcylinders[2].transform.localEulerAngles.y);
  float dcd = Mathf.Floor(dcylinders[3].transform.localEulerAngles.y);
  float dce = Mathf.Floor(dcylinders[4].transform.localEulerAngles.y);
  if (uca == 0 && (ucb == 0 || ucb == 180) && (ucc == 0 || ucc == 180) && ucd == 0)
  {
      if (!flagA)
      {
          audioSource.PlayOneShot(sound3);
          foreach (GameObject j in uroads)
          {
              j.GetComponent<MeshRenderer>().material = PowerSet[1];
              PPS.SetActive(true);
          }
      }
      flagA = true;   
  }
  if (dca == 0 && dcb == 0 && (dcc == 0 || dcc == 180) && dcd == 0 && dce == 0)
  {
       if (!flagB)
       {
          audioSource.PlayOneShot(sound3);
          foreach (GameObject k in droads)
          {
              k.GetComponent<MeshRenderer>().material = PowerSet[1];
              PT.SetActive(true);
          }
      }
      flagB = true;   
  }

シリンダーを1クリック毎に表面45度回し、その度にpowerboxクラスのCorrectメソッドを呼び出します。スクリプトが異なるのでinstanceを生成→それを参照する方法を使ってます。Correctメソッドではまずシリンダーオブジェクトを配列化、それぞれの角度を変数化した後全て0度(場合によっては180度も)ならPowerSet[1]に色変え・フラグONにしています。

小数点以下を使用してないのが原因かわかりませんが、シリンダー1クリックで表面45.00000度ときっちりとは回転せず小数点以下で微細なずれが生じた為、Correctメソッドの角度変数化の過程でMathf.Floor(切り捨て)を使用しました。以下デモ

*留意点:cylindersの配列化はヒエラルキー順に格納してますが、スマホ等の実機操作ではその順番に格納されない可能性があります。

instance

この言葉 いまだに分かったようで分かってないのですが簡潔にいうと””コードという設計図から作った実体””らしいですね。私の様な初心者は溝にハマってしまうのでまだ深く知る必要はないなと感じました。

コメント

タイトルとURLをコピーしました