山傘のプログラミング勉強日記

プログラミングに関する日記とどうでもよい雑記からなるブログです。

Unityでボウリングを作る その3

ボウリング

前回よりは進捗していると思うので、報告したいと思います。

今回の進捗

ピンをスクリプトで配置するようにしました 。

また、倒れたピンの数を数えて表示させています。ピンやボールが場外に出たときに、消滅させるようにしました。

動画

www.youtube.com

ソースコード

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

public class ControlPin : MonoBehaviour {
    public GameObject pinPrefab;
    private GameObject[] pin = new GameObject[10];
    private Vector3[] pinPos = new Vector3[10];
    private static bool[] pinFlag = new bool[10];
    private static PIN_STATE[] pinState = new PIN_STATE[10];
    private enum PIN_STATE {
        IN = 0,
        OUT = 1,
    }
    // Use this for initialization
    void Start () {
        InitPinFlag();
        InitPinPosition();
        for (int i = 0; i < 10; i++) {
            pin[i] = Instantiate(pinPrefab);
            pin[i].transform.position = pinPos[i];
        }
    }
    // Update is called once per frame
    void Update() {
        DestroyPin();
        CheckPin();
    }

    // ピンの生存フラグの初期化
    void InitPinFlag() {
        for(int i = 0; i < 10; i++) {
            pinFlag[i] = true;
        }
    }
    // ピンの初期位置の配列を初期化する
    void InitPinPosition() {
        float l = 1f;
        // 1番ピンの位置
        pinPos[0] = new Vector3(1.4f, 3.0f, 12.65f);
        for (int i = 1; i < 10; i++) {
            if (i == 1) {
                Vector3 p = pinPos[0];
                pinPos[i] = new Vector3(p.x - l, p.y, p.z + 2 * l);
            } else if (i == 3) {
                Vector3 p = pinPos[1];
                pinPos[i] = new Vector3(p.x - l, p.y, p.z + 2 * l);
            } else if (i == 6) {
                Vector3 p = pinPos[3];
                pinPos[i] = new Vector3(p.x - l, p.y, p.z + 2 * l);
            } else {
                Vector3 p = pinPos[i - 1];
                pinPos[i] = new Vector3(p.x + 2 * l, p.y, p.z);
            }
        }
    }
    // ピンが外に出たときに消滅させる
    void DestroyPin() {
        for(int i = 0; i < 10; i++) {
            if(pinState[i] == PIN_STATE.IN) {
                if (pin[i].transform.position.y < -5.0f) {
                    Destroy(pin[i]);
                    pinFlag[i] = false;
                    pinState[i] = PIN_STATE.OUT;
                }
            } 
        }
    }
    // 倒れた又は場外に出たピンのフラグの管理
    void CheckPin() {
        for(int i = 0; i < 10; i++) {
            if (pinFlag[i] == true) {
                if (pin[i].transform.position.y < 2.0f) {
                    pinFlag[i] = false;
                }
            }
        }
    }
    // 倒したピンの数
    public static int CountPin() {
        int ret = 0;
        for(int i = 0; i < 10; i++) {
            if (pinFlag[i] == false) {
                ret++;
            }
        }
        return ret;
    }   
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ControlScore : MonoBehaviour {
    public GameObject score;
    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        int cnt = ControlPin.CountPin();
        score.GetComponent<TextMesh>().text = cnt.ToString();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ControlBall : MonoBehaviour {
    public GameObject ball;
    // speedを制御する
    public float speed = 10;
    private void FixedUpdate() {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");

        // 同一のGameObjectが持つRigidbodyコンポーネントを取得
        if(ball != null) {
            Rigidbody rigidbody = ball.GetComponent<Rigidbody>();
            // rigidbodyのx軸(横)とz軸(奥)に力を加える
            rigidbody.AddForce(speed * x, 0, speed * z);

            if (ball.transform.position.y < -5.0f) {
                Destroy(ball);
            }
        }     
    }
}

感想

物理的挙動が一番難しいところですが、調整は最後にしようと思います。次はスコアや二投目の処理を書きたいと思います。