Unityでカーリングゲームを作る #6 敵のストーンを自動で動かす

投稿者: | 2019-12-27


敵のストーンが自動で発射されるようにします。

まず石のプレハブに付けたスクリプトで、最新の石が動きを止めるとゲームの状態が3になるようにしました。

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

public class StoneScript : MonoBehaviour
{
    public int stoneState = 0;
    public bool player = true;
    Rigidbody rb;
    public static int num = 0;
    public int stoneNumber;

    public Color color2;

    public static int gameState = 0;

    

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();

        stoneNumber = num;
        if (num % 2 == 1)
        {
            player = false;
            GetComponent<Renderer>().material.color = color2;
        }

        num++;

        gameState = 1;
    }

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

        if (stoneState == 1 && rb.velocity != Vector3.zero)
        {
            stoneState = 2;
            gameState = 2;
        }

        if (stoneState == 2 && rb.velocity == Vector3.zero)
        {
            stoneState = 3;
            gameState = 3;
        }
        
    }
}

(ストーンを投げるスクリプト)

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

public class CurlingScript : MonoBehaviour
{
    Plane groundPlane;
    Vector3 downPosition3D;
    Vector3 upPosition3D;

    //public GameObject sphere;
    public float thrust = 3f;

    float rayDistance;
    Ray ray;

    public GameObject stone;
    //GameObject currentStone;

    List<Rigidbody> stones;

    bool stoneEnter = false;
    //bool stoneExit = false;

    public GameObject mainCamera;
    public GameObject lookDownCam;

    public GameObject house;

    StoneScript sc_stone;

    bool mouseButtonDown;

    

    //public static bool moving = false;

    // Start is called before the first frame update
    void Start()
    {
        groundPlane = new Plane(Vector3.up,0f);

        stones = new List<Rigidbody>();

        stones.Add(Instantiate(stone, new Vector3(42f, 3f, 0f), Quaternion.Euler(0f, 0f, 0f)).GetComponent<Rigidbody>());

        mouseButtonDown = false;

        StoneScript.num = 0;
        StoneScript.gameState = 0; 

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0) && StoneScript.gameState == 1 && stones[stones.Count - 1].GetComponent<StoneScript>().player) // 左クリックを押した時
        {
            downPosition3D = GetCursorPosition3D();

            mouseButtonDown = true;
        }
        else if (Input.GetMouseButtonUp(0) && mouseButtonDown && StoneScript.gameState == 1) // 左クリックを離した時
        {
            mouseButtonDown = false;
            upPosition3D = GetCursorPosition3D();

            
            if (stones.Count != 0 && downPosition3D != ray.origin && upPosition3D != ray.origin && stones[stones.Count - 1].GetComponent<StoneScript>().stoneState == 0 && downPosition3D != upPosition3D)
            {
                stones[stones.Count - 1].GetComponent<Rigidbody>().AddForce((downPosition3D - upPosition3D) * thrust, ForceMode.Impulse); // ストーンをはじく
                stones[stones.Count - 1].GetComponent<StoneScript>().stoneState = 1;
            }
        }

        // ストーンを出現させる
        /*if(Input.GetKeyDown(KeyCode.R) && (stones.Count == 0 || stones[stones.Count - 1].GetComponent<StoneScript>().stoneState != 0))
        {
            //currentStone = Instantiate(stone, new Vector3(42f, 3f, 0f), Quaternion.Euler(0f, 0f, 0f));
            //SceneManager.LoadScene("curling");

            //stones.Add(currentStone);
            
            stones.Add(Instantiate(stone, new Vector3(42f, 3f, 0f), Quaternion.Euler(0f, 0f, 0f)).GetComponent<Rigidbody>());

        }*/


        if (stoneEnter)
        {

            stoneEnter = false;

            foreach (Rigidbody stone in stones)
            {

                if (stone.velocity != Vector3.zero && stone.transform.position.x > -13f)
                {
                    stoneEnter = true;
                }
            }

            if (!stoneEnter) // 全てのストーンが止まっているとき
            {
                
                mainCamera.SetActive(true);
                lookDownCam.SetActive(false);
            }

        }

        if (StoneScript.num == 8 && StoneScript.gameState == 3)//Input.GetKeyDown(KeyCode.Space)
        {
            StoneScript.gameState = 4;
            house.SetActive(!house.activeSelf);

        }


        if (StoneScript.gameState == 3)
        {
            StoneScript.gameState = 0;
            SpawnStone(); // ストーンを出現させる
            
        }

        if (StoneScript.gameState == 4 && Input.GetKeyDown(KeyCode.R))
        {
            SceneManager.LoadScene("curling");

        }
        
    }

    Vector3 GetCursorPosition3D()
    {
        ray = Camera.main.ScreenPointToRay(Input.mousePosition); // マウスカーソルから、カメラが向く方へのレイ
        groundPlane.Raycast(ray, out rayDistance); // レイを飛ばす

        return ray.GetPoint(rayDistance); // Planeとレイがぶつかった点の座標を返す
            
    }

    private void OnTriggerEnter(Collider other)
    {
        stoneEnter = true;
        mainCamera.SetActive(false);
        lookDownCam.SetActive(true);
        //Debug.Log("enter");

    }

    public void SpawnStone()
    {

        if (StoneScript.num % 2 == 1)
        { // 相手の手番
            stones.Add(Instantiate(stone, new Vector3(42f, 3f, 0f), Quaternion.Euler(0f, 0f, 0f)).GetComponent<Rigidbody>());
            StartCoroutine("autoThrow");
        }
        else { // 自分の手番
            stones.Add(Instantiate(stone, new Vector3(Random.Range(37f,47f), 3f, Random.Range(-10f,10f)), Quaternion.Euler(0f, 0f, 0f)).GetComponent<Rigidbody>());

        }
    }

    private IEnumerator autoThrow()
    {
        yield return new WaitForSeconds(1.0f);

        sc_stone = stones[stones.Count - 1].GetComponent<StoneScript>();

        if (sc_stone.stoneState == 0 && !sc_stone.player)
        {

            float power = 4.5f;
            if (Random.Range(0, 5) == 0)
            {
                power = 10f;
            }
            

            stones[stones.Count - 1].GetComponent<Rigidbody>().AddForce(new Vector3(-1f, 0f, Random.Range(-0.02f, 0.02f)) * Random.Range(25f, 28f) * power, ForceMode.Impulse);
            stones[stones.Count - 1].GetComponent<StoneScript>().stoneState = 1;
        }
    }
}

ストーンを投げるスクリプトで、ゲームの状態が3のときにストーンを出現させます。

if (StoneScript.gameState == 3)
{
    StoneScript.gameState = 0;
    SpawnStone(); // ストーンを出現させる
            
}

StoneScriptの静的プロパティの番号で手番を確認して、相手の時は自動でストーンを動かすためのコルーチンをスタートしています。

public void SpawnStone()
{

    if (StoneScript.num % 2 == 1)
    { // 相手の手番
        stones.Add(Instantiate(stone, new Vector3(42f, 3f, 0f), Quaternion.Euler(0f, 0f, 0f)).GetComponent<Rigidbody>());
        StartCoroutine("autoThrow");
    }
    else { // 自分の手番
        stones.Add(Instantiate(stone, new Vector3(Random.Range(37f,47f), 3f, Random.Range(-10f,10f)), Quaternion.Euler(0f, 0f, 0f)).GetComponent<Rigidbody>());

    }
}

自分のストーンを投げるときは、クリックする位置を覚えて真ん中を狙うことは簡単なので、スポーン位置をランダムにしました。

自動でストーンを投げるコルーチンでは、相手のストーンがたまに強く発射されるようにしました。

private IEnumerator autoThrow()
{
    yield return new WaitForSeconds(1.0f);

    sc_stone = stones[stones.Count - 1].GetComponent<StoneScript>();

    if (sc_stone.stoneState == 0 && !sc_stone.player) // 最新のストーンがまだ発射されていなくて、手番が相手のとき
    {

        float power = 4.5f;
        if (Random.Range(0, 5) == 0)
        {
            power = 10f;
        }      

        stones[stones.Count - 1].GetComponent<Rigidbody>().AddForce(new Vector3(-1f, 0f, Random.Range(-0.02f, 0.02f)) * Random.Range(25f, 28f) * power, ForceMode.Impulse);
        stones[stones.Count - 1].GetComponent<StoneScript>().stoneState = 1;
    }
}

コメントを残す

メールアドレスが公開されることはありません。