유니티 기초

로비씬, 사과, 폭탄 - [게임종료구현, 종료 후 스코어 미구현]

다모아 2023. 8. 7. 18:10

EndMain

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

public class EndMain : MonoBehaviour
{
    [SerializeField]
    private Button btnLobby;
    [SerializeField]
    private Button btnRestart;
    [SerializeField]
    private List<GameObject> basketPrefabs;
    // Start is called before the first frame update
    void Start()
    {
        //할거 없을듯?
        this.btnLobby.onClick.AddListener(() => {
            SceneManager.LoadScene("LobbyScene");
        });
        
        //점수 불러와야함
        this.btnRestart.onClick.AddListener(() => {
            SceneManager.LoadScene("AppleCatchScene");
        });

        this.CreateBasket();
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void CreateBasket()
    {
        int index = InfoManager.instance.selectedBasketType;

        GameObject prefab = this.basketPrefabs[index];
        GameObject basketGo = Instantiate(prefab);
        basketGo.transform.position = Vector3.zero;
    }
}

 

GameMain

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

//모든 게임씬 애들 관리
public class GameMain : MonoBehaviour
{
    private BasketController basketController;

    [SerializeField]
    private List<GameObject> basketPrefabs;

    private ItemGenerator itemGenerator;

    private GameObject gameDirectorGo;
    // Start is called before the first frame update
    void Start()
    {
        this.gameDirectorGo = GameObject.Find("GameDirector");
        GameDirector gameDirector = GetComponent<GameDirector>();

        this.CreateBasket();
    }

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

    private void CreateBasket()
    {
        GameObject prefab = this.basketPrefabs[InfoManager.instance.selectedBasketType];
        GameObject basketGo = Instantiate(prefab);
        basketGo.transform.position = Vector3.zero;
        this.basketController = basketGo.GetComponent<BasketController>();
    }
}

 

ItemGenerator

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

public class ItemGenerator : MonoBehaviour
{
    private float elasedTime; //경과 시간
    private float spawnTime = 1f; // 1초에 한번씩 스폰
    public GameObject applePrefab;
    public GameObject bombPrefab;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        //시간 재기
        //변수에 Time.deltaTime더해라
        this.elasedTime += Time.deltaTime;
        //1초가 지났다면
        if(this.elasedTime >= this.spawnTime)
        {
            //아이템을 생성
            this.CreateItem();
            //초기화
            this.elasedTime = 0;
        }
    }

    private void CreateItem()
    {
        //사과 또는 폭탄
        int rand = Random.Range(1, 11); // 1 ~ 10
        GameObject itemGo = null;
        if (rand > 2) //3, 4, 5, 6, 7, 8, 9, 10
        {
            //사과
            itemGo = Instantiate<GameObject>(this.applePrefab);
        }
        else //1, 2
        {
            //폭탄
            itemGo = Instantiate<GameObject>(this.bombPrefab);
        }
        //위치 설정
        //x: -1, 1 [좌 , 우]
        //z: -1, 1 [위 아래]
        int x = Random.Range(-1, 2); // -1, 0, 1
        int z = Random.Range(-1, 2); // -1, 0, 2
        //위치를 설정
        itemGo.transform.position = new Vector3(x, 3.5f, z);
    }
}

 

InfoManager

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


//Monobehavior 상속받지 않고 InfoManager에 남겨둔다.
public class InfoManager
{
    public static readonly InfoManager instance = new InfoManager();

    public int selectedBasketType = -1; // 0 : Yellow, 1 : Red, 2 : Green

    private InfoManager()
    {

    }
}

 

GameDirector

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameDirector : MonoBehaviour
{
    [SerializeField]
    private Text txtTime;
    [SerializeField]
    private Text txtScore;

    private float time = 5.0f;
    private int score = 0;
    // Start is called before the first frame update
    void Start()
    {
        //노란색
        if (InfoManager.instance.selectedBasketType == 0)
        {
            time += 10;
        }

        GameObject txtTimeGo = GameObject.Find("txtTime");
        this.txtTime = txtTimeGo.GetComponent<Text>();
        GameObject txtScoreGo = GameObject.Find("txtScore");
        this.txtScore = txtScoreGo.GetComponent<Text>();

        this.UpdateScoreUI();
    }

    
    // Update is called once per frame
    void Update()
    {
        this.time -= Time.deltaTime; // 매프레임마다 감소된 시간을 표시
        this.txtTime.text = this.time.ToString("F1");

        if(time <= 0)
        {
            SceneManager.LoadScene("GameOverScene");
        }
    }
    public void UpdateScoreUI()
    {
        this.txtScore.text = string.Format("{0} Point", score);
    }

    public void IncreaseScore(int score)
    {
        this.score += score;
    }

    public void DecreaseScore(int score)
    {
        this.score -= score;
    }
}

 

LobbyMain

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

public class LobbyMain : MonoBehaviour
{
    [SerializeField]
    private List<GameObject> baskets;

    [SerializeField]
    private Button btnGameStart;
    // Start is called before the first frame update
    void Start()
    {
        this.btnGameStart.onClick.AddListener(() => {
            this.SceneChange();
        });
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Debug.DrawRay(ray.origin, ray.direction * 100f, Color.red, 2f);
            RaycastHit hit;
            if(Physics.Raycast(ray, out hit, 1000f))
            {
                Debug.Log(hit.collider.gameObject.name);

                GameObject foundBasketGo = this.baskets.Find(x => x == hit.collider.gameObject);

                int selectedBasketType = this.baskets.IndexOf(foundBasketGo);

                Debug.LogFormat("<color=yellow>selectedBasketType: {0}</color>", selectedBasketType);

                InfoManager.instance.selectedBasketType = selectedBasketType;
                foreach(var go in this.baskets)
                {
                    if(go != foundBasketGo)
                    {
                        //선택 되지 않은 것들
                        go.SetActive(false); //비활성화
                        this.btnGameStart.gameObject.SetActive(true);
                    }
                }
            }
        }
    }
    public void SceneChange()
    {
        SceneManager.LoadScene("AppleCatchScene");
    }
}

 

BasketController

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

public class BasketController : MonoBehaviour
{
    private AudioSource audioSource;
    [SerializeField]
    private AudioClip bombSfx;
    [SerializeField]
    private AudioClip appleSfx;
    [SerializeField]
    private GameDirector gameDirector;

    private void Awake()
    {
        
    }

    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            //화면상의 좌표 Ray를 만들자
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            //ray를 눈으로 확인
            Debug.DrawRay(ray.origin, ray.direction * 100f, Color.green, 2f);

            //ray와 collider의 충돌을 검사하는 메서드
            RaycastHit hitData;
            //충돌되었다면 true , 아니면 false
            if(Physics.Raycast(ray, out hitData, 100f))
            {
                Debug.LogFormat("hit.point: {0}", hitData.point);

                //바구니의 위치를 충돌한 지점으로 변경
                //this.transform.position = hitData.point;
                //x좌표와 z좌표를 반올림
                float x = Mathf.RoundToInt(hitData.point.x);
                float z = Mathf.RoundToInt(hitData.point.z);
                //새로운 좌표를 만든 후 이동
                this.transform.position = new Vector3(x, 0, z);
            }
        }
    }

    public void Init()
    {
        GameObject gameDirectorGo = GameObject.Find("GameDirector");
        this.gameDirector = gameDirectorGo.GetComponent<GameDirector>();
        this.audioSource = this.GetComponent<AudioSource>();
    }

    private void OnTriggerEnter(Collider other)
    {
        Debug.Log(other.tag);
        this.Init();
        if(other.tag == "apple")
        {
            //점수를 추가
            Debug.Log("득점");
            this.audioSource.PlayOneShot(this.appleSfx);
            //빨간색
            if(InfoManager.instance.selectedBasketType == 1)
            {
                this.gameDirector.IncreaseScore(110);
            }
            else
            {
                this.gameDirector.IncreaseScore(100);
            }
            this.gameDirector.UpdateScoreUI();
            Destroy(other.gameObject); //사과 또는 폭탄을 제거
        }
        else if(other.tag == "bomb")
        {
            Debug.Log("감점");
            this.audioSource.PlayOneShot(this.bombSfx);
            if(InfoManager.instance.selectedBasketType == 2)
            {
                this.gameDirector.DecreaseScore(45);
            }
            else
            {
                this.gameDirector.DecreaseScore(50);
            }
            this.gameDirector.UpdateScoreUI();
            Destroy(other.gameObject); //사과 또는 폭탄을 제거
        }
    }
}


ItemController

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

public class ItemController : MonoBehaviour
{
    [SerializeField]
    private float moveSpeed = 1f;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        //리지드바디가 없는 오브젝트의 이동
        //this.transform.Translate(방향 * 속도 * 시간);
        //기본이 로컬좌표로 이동
        this.transform.Translate(Vector3.down * this.moveSpeed * Time.deltaTime);

        if(this.transform.position.y <= 0)
        {
            Destroy(this.gameObject); // Destroy(this); 완전히 다른 의미. Component가 제거됌
        }
    }
}

 

1분짜리 영상[종료 후 스코어 미구현]

소리는 이 컴퓨터 자리 소리가 안나는거 같은데 볼륨믹서를 확인해보면 사과랑 폭탄 먹을 때마다 증폭이 된다

 

스코어는 InfoManager에 score를 받아서 종료화면에도 나오게하면될 것 같다.