★Kosuke Kobayashi

(2024年4月22日)

・車をターンさせる

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

public class TurnX : MonoBehaviour
{
    public Vector3 value;
    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Car"))
        {
            other.transform.rotation = Quaternion.Euler(other.transform.eulerAngles.x, value.y, other.transform.eulerAngles.z);
        }
    }
}

(2024年4月1日)

<データベースの作成>

・新規にC#スクリプトを作成

・名前を「ItemStatus」に変更

・下記のコードを書いてチェック

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System; // ★追加

[Serializable] // ★追加
public class ItemStatus
{
    public string itemName;
    public Sprite itemImage;
}

・新規にC#スクリプトを作成

・名前を「ItemDataBase」に変更

・下記のコードを書いてチェック

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

// ★追加
[CreateAssetMenu]
public class ItemDataBase : ScriptableObject // ★変更
{
   public List<ItemStatus> itemList = new List<ItemStatus>();
}

・Assetsエリアの余白で右クリック

・「Create」→「Item Data Base」をクリック

・名前を「Item Data Base」に変更

・ItemListに「アイテム数」を記入

・アイテムの名前と画像を登録する。

*これでアイテムを管理するデータベースの完成です。

<<データベースを使ったサンプルコード>>

*これはあくまでサンプルなので、うまく動くのを確認したら自分のアイデアに合わせて改良してください。

・今回はPボタンを押したら、画像がどんどん切り替わるようになっています。

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

public class ItemSelectController : MonoBehaviour
{
    public ItemDataBase itemDataBase;

    public Image itemImage;
    private int num = 0;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            StartCoroutine(ItemSelect());
        }
    }

    private IEnumerator ItemSelect()
    {
        for (int i = 0; i < 30; i++)
        {
            num = (num + 1) % itemDataBase.itemList.Count;

            itemImage.sprite = itemDataBase.itemList[num].itemImage;

            yield return new WaitForSeconds(0.1f);
        }
    }
}

 


(2024年3月11日)

<レースクラスの設定>

(1)CPUスクリプトの改良

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

public class CPU : MonoBehaviour
{
    private SplineAnimate splineAnimate;

    // ★追加(レースクラスの設定)
    private int class50;
    private int class150;
    private int class200;

    public string carClassName { get; set; }

    private void Awake()
    {
        // 各レースクラスのスピードをランダム設定にする。
        class50 = Random.Range(10, 30);
        class150 = Random.Range(20, 60);
        class200 = Random.Range(70, 100);

        // ★テスト用のコード★
        // スピードのランダム設定がうまくいくかを確認する。
        // 確認できたらこのコードは削除(もしくはコメントアウト)すること(重要!)
        carClassName = "50cc";
    }

    private void Start()
    {
        splineAnimate = GetComponent<SplineAnimate>();

        // ★追加(レースクラスの設定)
        switch (carClassName)
        {
            case "50cc":
                splineAnimate.MaxSpeed = class50;
                break;

            case "150cc":
                splineAnimate.MaxSpeed = class150;
                break;

            case "200cc":
                splineAnimate.MaxSpeed = class200;
                break;
        }

        Invoke("Go", 21.5f);
    }

    void Go()
    {
        splineAnimate.enabled = true;
    }
}

*チェックが完了したらゲームを再生

*CPUのスピードが「50cc」クラスの範囲内に入っているかを確認する。

(2)StartButtonスクリプトの改良

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

public class StartButton : MonoBehaviour
{
    public string p1CarName { get; set; }
    public string p2CarName { get; set; }

    // ★追加(レースクラスの設定)
    public string selectCarClassName { get; set; }

    public void OnStartButtonClicked()
    {
        SceneManager.sceneLoaded += SetCar;

        // ★追加(レースクラスの設定)
        SceneManager.sceneLoaded += SetCPUSpeed;

        SceneManager.LoadScene("MarioKart");
    }

    void SetCar(Scene next, LoadSceneMode mode)
    {
        CarSelect cs = GameObject.Find("CarSelect").GetComponent<CarSelect>();

        cs.P1_CarName = p1CarName;
        cs.P2_CarName = p2CarName;

        SceneManager.sceneLoaded -= SetCar;
    }

    // ★追加(レースクラスの設定)
    void SetCPUSpeed(Scene next, LoadSceneMode mode)
    {
        // CPUオブジェクトは「複数」あるので「配列」でデータを取得する。
        GameObject[] cpus = GameObject.FindGameObjectsWithTag("CPU");

        foreach (var c in cpus)
        {
            // 自分が選択したレースクラスをCPUのcarClassNameに設定
            c.GetComponent<CPU>().carClassName = selectCarClassName;
        }

        SceneManager.sceneLoaded -= SetCPUSpeed;
    }
}

(3)スクリプトの作成

・新規にC#スクリプトを作成

・名前を「SelectCarClass」に変更

・下記のコードを書いてチェック

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

// ★追加(レースクラスの設定)
public class SelectCarClass : MonoBehaviour
{
    public StartButton startButton;
    public Canvas gameStartCanvas;
    public Canvas classSelectCanvas;

    public void OnCarClassButtonClicked()
    {
        // (ポイント)
        // ボタンの名前が条件になるので
        // 「50cc」「150cc」「200cc」の名前をつけること。
        startButton.selectCarClassName = this.gameObject.name;

        // クラスセレクトのキャンバスをオフにする。
        classSelectCanvas.enabled = false;

        // スタートボタンのキャンバスをオンにする。
        gameStartCanvas.enabled = true;
    }
}

・このスクリプトを3つのボタンオブジェクトに追加

*3つのボタンオブジェクト名前を必ず「50cc」「150cc」「200cc」にすること

・3つの空欄を設定(全部のボタンに同じ設定を行うこと)

・ボタンを動作させる設定(これもすべてのボタンに行うこと)

(4)CarSelect2スクリプトの改良

・今回は、プレーヤ2が車を選択

・レースクラスの選択

という流れになるので、そのように設定します。

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

public class CarSelect2 : MonoBehaviour
{
    public Canvas p2Canvas;

    // ★追加(レースクラスの設定)
    //public Canvas gameStartCanvas;
    public Canvas classSelectCanvas;

    public StartButton startButton;

    public void P2ButtonClicked()
    {
        p2Canvas.enabled = false;

        // ★追加(レースクラスの設定)
        //gameStartCanvas.enabled = true;
        classSelectCanvas.enabled = true;

        startButton.p2CarName = this.gameObject.name;
    }
}

設定が完了したらゲームを再生して確認してみましょう。

 


(2024年3月4日)

<バーチャルカメラのフォロー設定>

(1)スクリプトの改良

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// ★追加
using Cinemachine;

public class CarSelect : MonoBehaviour
{
    public GameObject Kart11;
    public GameObject Kart12;
    public GameObject Kart13;
    public GameObject Kart14;

    public GameObject Kart21;
    public GameObject Kart22;
    public GameObject Kart23;
    public GameObject Kart24;

    // ★改良
    //public VirtualCamera1 cmv1;
    //public VirtualCamera2 cmv2;
    public CinemachineVirtualCamera cmv1;
    public CinemachineVirtualCamera cmv2;

    public string P1_CarName { get; set; }
    public string P2_CarName { get; set; }

    void Start()
    {
        switch (P1_CarName)
        {
            case "Kart1-1":
                Kart11.SetActive(true);

                // ★改良
                //cmv1.carName = "kart1-1";
                cmv1.Follow = Kart11.transform;
                break;
            case "Kart1-2":
                Kart12.SetActive(true);

                // ★改良
                //cmv1.carName = "kart1-2";
                cmv1.Follow = Kart12.transform;
                break;
            case "Kart1-3":
                Kart13.SetActive(true);

                // ★改良
                //cmv1.carName = "kart1-3";
                cmv1.Follow = Kart13.transform;
                break;
            case "Kart1-4":
                Kart14.SetActive(true);

                // ★改良
                //cmv1.carName = "kart1-4";
                cmv1.Follow = Kart14.transform;
                break;
        }

        switch (P2_CarName)
        {
            case "Kart2-1":
                Kart21.SetActive(true);

                // ★改良
                //cmv2.carName = "kart2-1";
                cmv2.Follow = Kart21.transform;
                break;
            case "Kart2-2":
                Kart22.SetActive(true);

                // ★改良
                //cmv2.carName = "kart2-2";
                cmv2.Follow = Kart22.transform;
                
                break;
            case "Kart2-3":
                Kart23.SetActive(true);

                // ★改良
                //cmv2.carName = "kart2-3";
                cmv2.Follow = Kart23.transform;
                break;
            case "Kart2-4":
                Kart24.SetActive(true);

                // ★改良
                //cmv2.carName = "kart2-4";
                cmv2.Follow = Kart24.transform;
                break;
        }
    }
}

(設定)

・使わないスクリプトを外す

・これで完了

・ゲームを再生して確認しましょう!

 


(2024年2月12日)

<セレクト画面で選択した車をステージシーンで出現させる。>

(ステージシーンでの作業)

(1)スクリプト

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

public class CarSelect : MonoBehaviour
{
    // P1
    public GameObject P1_Car_Red;
    public GameObject P1_Car_Green;
    public GameObject P1_Car_Blue;
    public GameObject P1_Car_Yellow;

    // P2
    public GameObject P2_Car_Red;
    public GameObject P2_Car_Green;
    public GameObject P2_Car_Blue;
    public GameObject P2_Car_Yellow;

    public string P1_CarName { get; set; }
    public string P2_CarName { get; set; }

    void Start()
    {
        // (ポイント)switch文で書く
        // P1
        switch (P1_CarName)
        {
            case "P1_Red":
                P1_Car_Red.SetActive(true);
                break;
            case "P1_Green":
                P1_Car_Green.SetActive(true);
                break;
            case "P1_Blue":
                P1_Car_Blue.SetActive(true);
                break;
            case "P1_Yellow":
                P1_Car_Yellow.SetActive(true);
                break;
        }

        // P2
        switch (P2_CarName)
        {
            case "P2_Red":
                P2_Car_Red.SetActive(true);
                break;
            case "P2_Green":
                P2_Car_Green.SetActive(true);
                break;
            case "P2_Blue":
                P2_Car_Blue.SetActive(true);
                break;
            case "P2_Yellow":
                P2_Car_Yellow.SetActive(true);
                break;
        }
    }
}

(2)設定

・P1とP2の車をすべて「ノンアクティブ状態」にして、空欄に追加

(車のセレクトシーンでの作業)

・同じシーンの中に3つのCanvasを作成する(ポイント)




(スクリプト)

<スタートボタン専用>

*一番最初に書く!

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

public class StartButton : MonoBehaviour
{
    public string p1CarName { get; set; }
    public string p2CarName { get; set; }

    public void OnStartButtonClicked()
    {
        // ★ポイント(ゲームスタートボタンを押したときにシーン遷移する)
        // シーン遷移時に呼び出したいメソッドを登録する(今回の場合は、SetCar())
        SceneManager.sceneLoaded += SetCar;

        SceneManager.LoadScene("CarStage");
    }

    // ★ポイント
    // 呼び出すメソッドを定義する(中身を書く)
    void SetCar(Scene next, LoadSceneMode mode)
    {
        CarSelect cs = GameObject.Find("CarSelect").GetComponent<CarSelect>();

        cs.P1_CarName = p1CarName;
        cs.P2_CarName = p2CarName;

        // 登録したメソッドを削除する。
        SceneManager.sceneLoaded -= SetCar;
    }
}

<P1ボタン専用>

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

public class P1_Button : MonoBehaviour
{
    public Canvas p1Canvas;
    public Canvas p2Canvas;
    public Canvas gameStartCanvas;
    public StartButton startButton;

    private void Start()
    {
        // 最初はp1CanvasのみONの状態にする。
        p1Canvas.enabled = true;
        p2Canvas.enabled = false;
        gameStartCanvas.enabled = false;
    }

    public void P1ButtonClicked()
    {
        p1Canvas.enabled = false;
        p2Canvas.enabled = true;

        // ★ポイント
        // 「CarSelectスクリプトの中にあるswitcのcase(条件)とボタンの名前を一致させる(重要)
        startButton.p1CarName = this.gameObject.name;
    }
}

<P2ボタン専用>

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

public class P2_Button : MonoBehaviour
{
    public Canvas p2Canvas;
    public Canvas gameStartCanvas;
    public StartButton startButton;

    public void P2ButtonClicked()
    {
        p2Canvas.enabled = false;

        gameStartCanvas.enabled = true;

        // ★ポイント
        startButton.p2CarName = this.gameObject.name;
    }
}

 

 

 


(2024年2月5日)

<シーン間でデータを引き継ぐ。タイトルシーンでセットした数値をメインシーンのオブジェクトにセットする方法>

(ボタン側のスクリプト)

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

public class ButtonController : MonoBehaviour
{
    public AudioClip sound;

    public float carSpeed;
    public float carTurn;
    public float carAccel;

    public void OnButtonClicked()
    {
        AudioSource.PlayClipAtPoint(sound, Camera.main.transform.position);

        Invoke("GoMain", 1.0f);
    }

    void GoMain()
    {
        // ★ポイント
        // シーン遷移時に呼び出したいメソッドを登録する(今回の場合は、SetCarStatus())
        SceneManager.sceneLoaded += SetCarStatus;

        SceneManager.LoadScene("Button_Carselect_2");
    }

    // ★ポイント
    // 呼び出すメソッドを定義する(中身を書く)
    void SetCarStatus(Scene next, LoadSceneMode mode)
    {
        // ここでは、遷移したシーンに存在するCarXオブジェクトの3つのパラメータをセットする。
        CarParam cp = GameObject.Find("CarX").GetComponent<CarParam>();

        cp.speed = carSpeed;
        cp.turn = carTurn;
        cp.accel = carAccel;

        // 登録したメソッドを削除する、
        SceneManager.sceneLoaded -= SetCarStatus;
    }
}

(遷移したシーンで、数値をセットされる側のスクリプト)

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

public class CarParam : MonoBehaviour
{
    public float speed { get; set; }
    public float turn { get; set; }
    public float accel { get; set; }

    public Text speedLabel;
    public Text turnlabel;
    public Text accelLabel;

    private void Update()
    {
        print("速度は" + speed);
        speedLabel.text = "速度:" + speed;

        print("旋回は" + turn);
        turnlabel.text = "旋回:" + turn;

        print("加速は" + accel);
        accelLabel.text = "加速:" + accel;
    }
}

(2024年1月24日)

<ジョイスティックでボタンセレクト>


(2023年12月27日)

<Input Managerの設定>

(左右の旋回)

(1)キーボード操作用

(2)ジョイスティック操作用

(加速)

*1つの中に「キーボード用」と「ジョイスティック用」の両方を設定できる。


(2023年12月25日)

・全てのPlaneから「Mesh Collider」を外す


<加速装置の改良>

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

public class Kart : MonoBehaviour
{
    public float turnSpeed;
    private Rigidbody rb;
    private float turnInputValue;
    private bool isGround;
    private float timer = 0;
    private Vector3 pos;
    private Quaternion dir;
    //private Gate gate;
    private int rank;
    public Image rankLabel;
    public Sprite[] rankImage;

    private Vector3 rot;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        rankLabel.sprite = rankImage[8];
    }

    void Update()
    {
        rot = transform.eulerAngles;

        if(Input.GetButton("Fire1"))
        {
            rb.velocity += transform.forward * 0.6f;
            rb.velocity = Vector3.ClampMagnitude(rb.velocity,60);
        }

        if(Input.GetButton("Fire2"))
        {
            rb.velocity -= transform.forward * 0.2f;
            rb.velocity = Vector3.ClampMagnitude(rb.velocity, 20);
        }

        Turn();

        if(Input.GetButton("Jump"))
        {
            transform.eulerAngles = new Vector3(0, rot.y, 0);
        }

        if(isGround == false)
        {
            timer +=  Time.deltaTime;

            if(timer >= 3)
            {
                transform.position = pos;
                transform.rotation = dir;
            }
        }
    }

    void Turn()
    {
        turnInputValue = Input.GetAxis("Horizontal");
        float turn = turnInputValue * turnSpeed * Time.deltaTime;
        Quaternion turnRotation = Quaternion.Euler(0, turn, 0);
        rb.MoveRotation(rb.rotation * turnRotation);
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Street"))
        {
            timer = 0;
            isGround = true;
        }

        if(other.gameObject.CompareTag("Sensor"))
        {
            rank = other.GetComponent().gateCount;
            print(rank);

            if(rank == 1)
            {
                rankLabel.sprite = rankImage[0];
            }
            if (rank == 2)
            {
                rankLabel.sprite = rankImage[1];
            }

            if (rank == 3)
            {
                rankLabel.sprite = rankImage[2];
            }

            if (rank == 4)
            {
                rankLabel.sprite = rankImage[3];
            }

            if (rank == 5)
            {
                rankLabel.sprite = rankImage[4];
            }

            if (rank == 6)
            {
                rankLabel.sprite = rankImage[5];
            }
            if (rank == 7)
            {
                rankLabel.sprite = rankImage[6];
            }

            if (rank == 8)
            {
                rankLabel.sprite = rankImage[7];
            }

            if (rank == 9)
            {
                rankLabel.sprite = rankImage[8];
            }

            if (rank == 10)
            {
                rankLabel.sprite = rankImage[9];
            }

            if (rank == 11)
            {
                rankLabel.sprite = rankImage[10];
            }

            //if (rank == 12)
            //{
            //    rankLabel.sprite = rankImage[11];
            //}
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.CompareTag("Accelerator"))
        {
            //this.rb.velocity += transform.forward * 100f;
            //this.gameObject.GetComponent().AddForce(transform.root.eulerAngles,ForceMode.Force);

            // ★12月25日修正
            Vector3 forwardForce = transform.forward * 10;
            rb.AddForce(forwardForce, ForceMode.VelocityChange); // 進行方向に加速
            rb.AddForce(new Vector3(0, 5, 0), ForceMode.Impulse);// 少しだけ上方向に加速
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if(other.gameObject.CompareTag("Street"))
        {
            isGround = false;
            pos = transform.position;
            dir = transform.rotation;
        }
    }
}

<2台のバーチャルカメラを使用する>

*このやり方だと、相手方が画面に映らない。ブログを参考にすること

・対応関係を明確にするために「名前」を整理する。

・Layerを整理する

・カメラにどのLayerを描画するか(しないか)を設定する


(実行結果)