i-school - ソースコード一覧
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PanelCreater : MonoBehaviour
{
    public int maxArrow;
    public int waitTime;

    public int maxColumn;
    public int maxRow;

    public int maxWaveCount;
    private int currentWaveCount = 0;

    //private float timer;
    public int oneWaveTimeLimit;
    private float waveTimer;

    public AnimalPanelItem animalPanelItemPrefab;
    public Transform animalPanelGenerateTran;

    public PanelItem panelItemPrefab;
    public Transform panelGenerateTran;

    public List<PanelItem> panelItemList = new List<PanelItem>();
    public List<AnimalPanelItem> animalPanelList = new List<AnimalPanelItem>();

    public PlayerController playerController;
    public UIController uIController;

    public enum GameState {
        Wait,
        Play,
        Game_Up,
    }
    public GameState gameState;

    IEnumerator Start()
    {
        yield return new WaitForSeconds(0.5f);

        gameState = GameState.Wait;

        StartCoroutine(NextWave());
    }

    void Update()
    {
        if (gameState == GameState.Game_Up) {
            return;
        }

        if (gameState == GameState.Wait) {
            return;
        }

        waveTimer -= Time.deltaTime;
        uIController.txtWaveTimer.text = waveTimer.ToString("F0");

        if (waveTimer <= 0) {
            if (currentWaveCount >= maxWaveCount) {
                gameState = GameState.Game_Up;
                uIController.DisplayaGameUp();
                return;
            }
            gameState = GameState.Wait;
            StartCoroutine(NextWave());
        }
    }

    public void NextPanels() {
        DestroyPanels();
        GenerateArrowPanels();
    }

    /// <summary>
    /// PanelItemの破棄
    /// </summary>
    private void DestroyPanels() {
        if (panelItemList.Count <= 0) {
            return;
        }

        for (int i = 0; i < panelItemList.Count; i++) {
            Destroy(panelItemList[i].gameObject);
        }
        panelItemList.Clear();
    }

    /// <summary>
    /// PanelItemの生成
    /// </summary>
    private void GenerateArrowPanels() {
        for (int i = 0; i < maxArrow; i++) {
            PanelItem panelItem = Instantiate(panelItemPrefab, panelGenerateTran, false);
            panelItem.SetupPanel(playerController, this);
            panelItemList.Add(panelItem);
        }
    }

    private IEnumerator NextWave() {
        if (currentWaveCount != 0) {
            DestroyAnimalPanels();

            DestroyPanels();

            playerController.ResetPosition();
        }
        uIController.ActivateReloadButton(false);

        yield return StartCoroutine(GenerateAnimalPanaels());

        waveTimer = oneWaveTimeLimit;
        currentWaveCount++;

        StartCoroutine(uIController.DisplayWaveStart(currentWaveCount));

        yield return new WaitForSeconds(1.5f);

        GenerateArrowPanels();

        uIController.ActivateReloadButton(true);

        gameState = GameState.Play;
    }

    /// <summary>
    /// AnimalPanelItemの破棄
    /// </summary>
    private void DestroyAnimalPanels() {
        for (int i = 0; i < animalPanelList.Count; i++) {
            Destroy(animalPanelList[i].gameObject);
        }
        animalPanelList.Clear();
    }

    /// <summary>
    /// AnimalPanelItemの生成
    /// </summary>
    private IEnumerator GenerateAnimalPanaels() {
        for (int x = 0; x < maxColumn; x++) {
            for (int y = 0; y < maxRow; y++) {
                AnimalPanelItem animalPanelItem = Instantiate(animalPanelItemPrefab, animalPanelGenerateTran, false);
                animalPanelItem.SetUpAnimalPanel(Random.Range(0,7), 100);
                animalPanelList.Add(animalPanelItem);
                yield return new WaitForSeconds(0.2f);
            }
        }
    }
}

using UnityEngine;
using UnityEngine.UI;

public class PanelItem : MonoBehaviour
{
    public Button btnPanel;
    public Image imgPanel;
    public ArrowDirectionType ArrowDirectionType;
    
    private bool isClickable;
    private PlayerController playerController;
    private PanelCreater panelCreater;

    public void SetupPanel(PlayerController playerController, PanelCreater panelCreater) {
        isClickable = true;

        this.playerController = playerController;
        this.panelCreater = panelCreater;
        
        FetchArrowDirection();

        btnPanel.onClick.AddListener(OnClickPanel);

        isClickable = false;
    }

    /// <summary>
    /// 矢の方向情報とイメージの方向を一致させる
    /// </summary>
    private void FetchArrowDirection() {
        // 矢の方向をランダムで決定
        int randomDirection = Random.Range(0, (int)ArrowDirectionType.Count);

        // 矢のイメージと方向の情報を一致
        imgPanel.transform.rotation = Quaternion.Euler(0, 0, randomDirection * 45);
        ArrowDirectionType = (ArrowDirectionType)randomDirection;
    }

    private void OnClickPanel() {
        if (isClickable) {
            return;
        }
        isClickable = true;
        btnPanel.interactable = false;
        playerController.JudgeMove(ArrowDirectionType);
        panelCreater.NextPanels();
    }
}

public enum ArrowDirectionType {
    Right_Middle,     // 0 東
    Right_Top,        // 1 北東
    Center_Top,       // 2 北
    Left_Top,         // 3 北西
    Left_Middle,      // 4 西
    Left_Bottom,      // 5 南西
    Center_Bottom,    // 6 南
    Right_Bottom,     // 7 南東
    Count
}

using UnityEngine;
using UnityEngine.UI;

public class AnimalPanelItem : MonoBehaviour
{
    public Image imgAnimal;
    public int animalNo;
    public int score;
    public bool isGetPanel;
    public BoxCollider2D boxCollider2D;

    public void SetUpAnimalPanel(int no, int score)
    {
        animalNo = no;
        this.score = score;
        imgAnimal.sprite = Resources.Load<Sprite>("animal_" + animalNo);
    }

    public void GetPanel() {
        imgAnimal.color = new Color(1, 1, 1, 0.25f);
        isGetPanel = true;
        boxCollider2D.enabled = false;
    }
}

using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private int currentAnimalNo = 0;     // 現在のAnimalPanelのNo。コンボ判定に使用する
    private int comboCount;              // 現在のコンボ数。異なるAnimalNoのAnimalPanelを通過するとアップ。同じNoを通過するとリセット
    private int totalScore;              // 現在のトータルスコア。Wave共通
    private Vector3 startPos;            // Playerのスタート地点登録用。Waveが切り替わる度にこの地点に戻る
    private float moveAmount;            // Playerのパネルの移動量

    public BoxCollider2D boxCol;         // PlayerのBoxCollier2Dをアサインする
    public UIController uIController;    // ヒエラルキー上にあるUIControlerをアサインする
    public LayerMask wallLayer;          // Wallレイヤーをアサインする

    Dictionary<ArrowDirectionType, Vector3> moveDirection;   // Dictionaryの宣言

    void Start() {
        // スタート地点を登録
        startPos = transform.position;

        // Playerの移動量をPlayerオブジェクトの大きさから取得
        moveAmount = GetComponent<RectTransform>().sizeDelta.x;

        // 移動判定用のDictionayを用意
        SetUpMoveDirection();
    }

    /// <summary>
    /// 向きのEnumと、それに対応する方向情報をセットしてDictionayに順次登録
    /// </summary>
    private void SetUpMoveDirection() {
        // 初期化
        moveDirection = new Dictionary<ArrowDirectionType, Vector3>();

        // 向きのEnumと方向情報を1セット単位で登録
        moveDirection.Add(ArrowDirectionType.Right_Middle, new Vector3(moveAmount, 0, 0));
        moveDirection.Add(ArrowDirectionType.Right_Top, new Vector3(moveAmount, moveAmount, 0));
        moveDirection.Add(ArrowDirectionType.Center_Top, new Vector3(0, moveAmount, 0));
        moveDirection.Add(ArrowDirectionType.Left_Top, new Vector3(-moveAmount, moveAmount, 0));
        moveDirection.Add(ArrowDirectionType.Left_Middle, new Vector3(-moveAmount, 0, 0));
        moveDirection.Add(ArrowDirectionType.Left_Bottom, new Vector3(-moveAmount, -moveAmount, 0));
        moveDirection.Add(ArrowDirectionType.Center_Bottom, new Vector3(0, -moveAmount, 0));
        moveDirection.Add(ArrowDirectionType.Right_Bottom, new Vector3(moveAmount, -moveAmount, 0));
    }

    /// <summary>
    /// Wave切り替え時にPlayerをスタート地点に戻す
    /// </summary>
    public void ResetPosition() {
        transform.position = startPos;
    }

    /// <summary>
    /// 矢印パネルの方向に移動可能かどうかを判定
    /// </summary>
    /// <param name="arrowDirectionType"></param>
    public void JudgeMove(ArrowDirectionType arrowDirectionType) {

        // 戻り値を利用して、作成したDictionaryの中から、向きのEnumから方向情報を取得
        Vector3 judgeDirection = SearchDirectionFromDictionary(arrowDirectionType);

        // Playerの位置と方向を取得
        Vector3 playerPos = transform.position;

        // Rayを使って移動先に壁があるか判定
        RaycastHit2D raycastHit2D = Physics2D.Raycast(playerPos, judgeDirection, 1, wallLayer);

        // RayをSceneプレビュー内に可視化
        Debug.DrawRay(playerPos, judgeDirection, Color.red, 1);

        // Wallであった場合、Debugとして内容を表示する
        Debug.Log(raycastHit2D.collider);

        // 移動先が壁の場合、移動失敗の判定をする(raycast2D変数内にゲームオブジェクトが格納されるので、移動処理をしない)
        if (raycastHit2D.collider != null) {
            // 移動失敗のSE鳴らす
            return;
        }

        // 移動判定に成功したのでPlayerを移動
        ActionMove(judgeDirection);
    }

    /// <summary>
    /// DicitonayであるmoveDirectionを検索して、向きのEnumからVector3の方向情報を取得して戻す
    /// </summary>
    /// <param name="arrowDirectionType"></param>
    /// <returns></returns>
    private Vector3 SearchDirectionFromDictionary(ArrowDirectionType arrowDirectionType) {
        // 変数を用意
        Vector3 direction = new Vector3(0, 0, 0);

        // Dicitonayを検索し、引数のEnumとKeyのEnumが一致したら、その方向情報(Value)を取得
        foreach (KeyValuePair<ArrowDirectionType, Vector3> item in moveDirection) {
            if (item.Key == arrowDirectionType) {
                // 値を代入して戻す(ここで処理は終了)
                return direction = item.Value;
            }
        }
        return direction;
    }

    /// <summary>
    /// Playerを移動する
    /// </summary>
    /// <param name="currentMoveDirection"></param>
    private void ActionMove(Vector3 currentMoveDirection) {
        // Playerを移動
        transform.localPosition += currentMoveDirection;
        // Playerの当たり判定をオンにする(移動後にオンにすることで、その間は当たり判定を取らないようにする)
        boxCol.enabled = true;
    }

    private void OnTriggerEnter2D(Collider2D col) {
        // 当たり判定に入った移動先のパネルがAnimalPanelItemを持っているか確認して変数に代入
        if (col.gameObject.TryGetComponent(out AnimalPanelItem animalPanelItem)) {

            // AnimalPanelItemクラスを持っていないパネルなら処理を止める
            if (animalPanelItem.isGetPanel) {            
                return;
            }

            // コンボ判定を行う。今までいたパネルのAnimalNoと新しく移動した先のパネルのAnimalNoを比べて違う場合にはコンボ成功
            if (currentAnimalNo != animalPanelItem.animalNo) {                
                comboCount++;
            } else {
                // 同じAnimalNoならコンボ失敗。次のコンボに向けて初期化する
                currentAnimalNo = animalPanelItem.animalNo;
                comboCount = 1;
            }

            // スコアを更新(TODO アニメ処理する)
            totalScore += animalPanelItem.score * comboCount;

            // スコアの画面表示を更新
            uIController.UpdateDisplayScore(totalScore);

            // 通過したパネルは重複して通過できないように処理をする
            animalPanelItem.GetPanel();
        }

        // Playerの当たり判定をオフ
        boxCol.enabled = false;
    }
}

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;

public class UIController : MonoBehaviour
{
    public Text txtScore;
    public Text txtWaveCount;
    public Text txtWaveTimer;
    public Text txtInfo;

    public Button btnReload;
    public PanelCreater panelCreater;

    public bool isClickable;
    private float waitTime = 0.5f;

    private Sequence sequence;

    void Start() {
        sequence = DOTween.Sequence();
        btnReload.onClick.AddListener(() => StartCoroutine(OnClickReloadArrowPanels(waitTime)));
    }

    public void DisplayaGameUp() {
        txtInfo.text = "Game Up!";
        sequence.Append(txtInfo.transform.DOLocalMoveX(0, 1.0f)).SetEase(Ease.Linear).SetRelative();
    }

    public IEnumerator DisplayWaveStart(int waveCount) {
        txtWaveCount.text = waveCount.ToString();
        txtInfo.text = "Wave : " + waveCount + " Start!";
        sequence.Append(txtInfo.transform.DOLocalMoveX(0, 1.0f)).SetEase(Ease.Linear).SetRelative();
        yield return new WaitForSeconds(2.0f);
        sequence.Append(txtInfo.transform.DOLocalMoveX(700, 1.0f)).SetEase(Ease.Linear).SetRelative();
        yield return new WaitForSeconds(1.0f);
        txtInfo.text = "";
        sequence.Append(txtInfo.transform.DOLocalMoveX(-700, 1.0f)).SetEase(Ease.Linear).SetRelative();
    }

    public void UpdateDisplayScore(int score) {
        // アニメさせる
        txtScore.text = score.ToString();
    }

    private IEnumerator OnClickReloadArrowPanels(float waitTime) {
        if (isClickable) {
            yield break;
        }
        isClickable = true;
        ActivateReloadButton(false);
        panelCreater.NextPanels();
        yield return new WaitForSeconds(waitTime);
        isClickable = false;
        ActivateReloadButton(true);
    }

    public void ActivateReloadButton(bool isSwitch) {
        btnReload.interactable = isSwitch;
    }
}