Unityでボーリングゲームを作る #8 機械の動きを表にする - Unityの使い方



Unity -> スクリプト -> Unityでボーリングゲームを作る #8 機械の動きを表にする

Unityでボーリングゲームを作る #8 機械の動きを表にする

ピンを置き直したり、倒れたピンを取り除くピンセッターの動きをスクリプトで作ってみました。

ピンを置く機械の動きは、Youtubeでボーリングの動画を見ながら表に書いて整理しました。

表にすると思ったよりシンプルでした。閉じたバーが後ろに下がって倒れたピンを排除する動きは結局毎回入ります。あとは、表を見ながらif文の条件を作るだけなので簡単です。

普通の決定表で良かったです。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;


public class GameScript3 : MonoBehaviour
{
    public Text text;
    public Text text2;

    GameObject[] pins;
    public float q = 0.01f;

    Animator pinsetterAnimator;
    public Animator barAnimator;
    public GameObject pinsetter;

    bool setpin = false;

    // スコアを入れるリスト
    List<int> playerPins;
    List<int> npcPins;

    public GameObject bowling_pin; // ピンのプレハブ
    public GameObject leadingPin; // 新しく作るピンの先頭の位置を教える空のゲームオブジェクト

    // Start is called before the first frame update
    void Start()
    {
        text.text = "";
        pinsetterAnimator = pinsetter.GetComponent<Animator>();

        playerPins = new List<int>();
        npcPins = new List<int>();
        text2.text = "FRAME 1";
    }

    // Update is called once per frame
    void Update()
    {

        if(Input.GetKeyDown(KeyCode.R))
        {
            SceneManager.LoadScene("Bowling");
        }

    }

    void CountStandingPins()
    {
        pins = GameObject.FindGameObjectsWithTag("Pin"); //「Pin」タグのついたオブジェクトを探して、全て配列pinsにいれる

        setpin = true;
        StartCoroutine("SetPin", pins);        
    }


    IEnumerator SetPin()
    {
    barAnimator.SetTrigger("barTrig"); // バーが降りる
    yield return new WaitForSeconds(2f);

        // 立っているピンの数を数える
        int n = 0;

        foreach (GameObject pin in pins)
        {
            if (pin.transform.rotation.x * pin.transform.rotation.x < q && pin.transform.rotation.z * pin.transform.rotation.z < q)
            {
                n++;

            }
        }

        text.text = n.ToString();

        playerPins.Add(10 - n); // 倒れたピンの数をリストに追加

        if(playerPins.Count % 2 == 1 && n == 0) 
        {
            playerPins.Add(-1); // 1投目でストライクのときは2投目は無いので、配列にその分の -1 を入れて要素数を調整する。
        }


        if (playerPins.Count % 2 == 1 && playerPins[playerPins.Count - 1] < 10) // 1投目で、ストライク以外の時
        {
            pinsetterAnimator.SetTrigger("Pinsetter"); // 天井が降りる

            foreach (GameObject pin in pins)
            {
                if (pin.transform.rotation.x * pin.transform.rotation.x < q && pin.transform.rotation.z * pin.transform.rotation.z < q)
                {
                    pin.GetComponent<Rigidbody>().isKinematic = true; // 立っているピンの動きを止める。
                }

            }

            yield return new WaitForSeconds(1.7f);

            text.text = "";

            foreach (GameObject pin in pins)
            {
                if (pin.transform.rotation.x * pin.transform.rotation.x < q && pin.transform.rotation.z * pin.transform.rotation.z < q)
                {
                    pin.transform.parent = pinsetter.transform; // 立っているピンを天井の子オブジェクトにする。
                }
            }

            pinsetterAnimator.SetTrigger("Pinsetter"); // 天井が上がる
        }
        else {
            yield return new WaitForSeconds(1.7f);
            text.text = "";
        }


        yield return new WaitForSeconds(1f);
    barAnimator.SetTrigger("barTrig"); // バーがピンを排除

    yield return new WaitForSeconds(0.6f);

        if (playerPins.Count % 2 == 0 || playerPins[playerPins.Count - 1] == 10) // 2投目のときまたは、ストライクかスペアのとき
        {
            // 今あるピンを全て削除
            foreach (GameObject pin in pins)
            {
                Destroy(pin);
            }

            SetNewPins(leadingPin.transform, 0.7f, 4);// 新しいピンを作る

            foreach (GameObject pin in GameObject.FindGameObjectsWithTag("Pin"))
            {
                pin.GetComponent<Rigidbody>().isKinematic = true; // 物理で動かないようにする
                pin.transform.parent = pinsetter.transform; // ピンを天井の子オブジェクトにする
            }
        }

    //yield return new WaitForSeconds(1f);  

    pinsetterAnimator.SetTrigger("Pinsetter"); // 天井が降りる

        
        yield return new WaitForSeconds(1.5f);

    foreach (GameObject pin in GameObject.FindGameObjectsWithTag("Pin"))
    {
        if (pin.transform.rotation.x * pin.transform.rotation.x < q && pin.transform.rotation.z * pin.transform.rotation.z < q)
        {
            pin.transform.parent = null; // 立っているピンと天井の親子関係を解く
            pin.GetComponent<Rigidbody>().isKinematic = false;
        }
    }
    barAnimator.SetTrigger("barTrig"); // バーが上がる

        


        pinsetterAnimator.SetTrigger("Pinsetter"); // 天井が上がる
        yield return new WaitForSeconds(0.7f);

        if (playerPins.Count % 2 == 0)
        {
            text2.text = "";
        }
        yield return new WaitForSeconds(0.4f);
        //yield return new WaitForSeconds(1.1f);
        setpin = false;
    
    //yield return new WaitForSeconds(0.5f);
    text2.text = "FRAME " + (playerPins.Count / 2 + 1);
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Ball" && !setpin)
        {
            
            CountStandingPins();
        }

    }

    /*
    void GenerateNewPins()
    {
        Vector3[] newPinsPos = {
        new Vector3(-42.29f, 1.318f, 0.0493f),new Vector3(-42.85f, 1.318f, 0.42f),new Vector3(-42.85f, 1.318f, -0.35f),
        new Vector3(-43.34f, 1.318f, 0.79f),new Vector3(-43.34f, 1.318f, 0.02f),new Vector3(-43.34f, 1.318f, -0.769f),
        new Vector3(-43.86f, 1.318f, 1.178f),new Vector3(-43.86f, 1.318f, 0.408f),new Vector3(-43.86f, 1.318f, -0.39f),
        new Vector3(-43.86f, 1.318f, -1.16f),};

        for(int p = 0; p < 10; p++)
        {
            Instantiate(bowling_pin, newPinsPos[p],Quaternion.Euler(0f, 0f, 0f));
        }

    }
    */

    void SetNewPins(Transform t, float interval, int line_total)
    {
        int line = 0; // 行
        int column = 1; // 列

        for (int o = 0; o < line_total; o++)
        {

            for (int p = 0; p < column; p++)
            {
                Vector3 pos = t.position;

                // 先頭のピンを基準に位置を変える
                pos -= t.forward * (interval * line); // 置く列に合わせて後ろに下げる
                pos += t.right * (interval * p - interval / 2 * line); // 左方向に動かす

                Instantiate(bowling_pin, pos, Quaternion.Euler(0f, 0f, 0f));
            }

            line++;
            column++;
        }

    }

}

2回投げるか、ストライクを取ると次のフレームへ進みます。


投げるごとに、残ったピンの数をリストに入れて、その要素数が奇数か偶数かで何投目かを判断しています。途中で順番が入れ替わらないように、ストライクの場合はさらに次の要素に-1を入れて要素数が偶数になるようにします。

yield return new WaitForSeconds()に入れた秒数だけ処理を待ちます。何度か試して値を決めます。


新しいピンを生成するときは、前の記事で作った関数を使っています。
空のゲームオブジェクトを置いて、新しくセットされる先頭のピンの位置を教えます。

トップページへ


tags: ボーリング, ボウリング, コルーチン, 決定表, アルゴリズム