유니티를 활용한 3D 적 피하기 게임 만들기(2)

728x90

플레이어가 코인을 먹으면 점수가 올라가고, 남은 시간이 표시되는 UI를 구성하기 위해 TEXT - UI에서 캔버스를 생성해주었다. 그리고 기존에 만들었던 Game_Manager 스크립트에 scoretext 내용을 추가, 게임매니저의 인스펙터 창에 생성한 scoretext와 timetext 오브젝트를 넣어주면 된다.

 

1. Scoretext 설정

스크립트에 추가하는 내용은

1)게임 매니저 스크립트

using UnityEngine.UI     

//TEXT UI를 사용하기 위해 Namespace에 추가

 

public Text scorerText;

int currentScorer = 0;

 

public void SetScore(int _score)
    {
        currentScore += _score;
        scoreText.text = currentScore.ToString();
    }

//SetScore 함수를 만들어 매개변수로 더해질 점수 _score변수를 만들어주고 선언된 정수형 변수 currentScore에 _score를 더해서 대입

 

2)플레이어 스크립트

 void OnTriggerEnter(Collider other)
    {
        if (other.name == "coin")
        {
            gameManager.EnableCoin_Invoke();
            gameManager.SetScore(2);
        }

     }

//Player 스크립트에서 충돌되었을 때 SetScore함수를 호출할 수 있도록 수정

 

2. TimeText 설정

1)게임 매니저 스크립트

public int playTime = 30;

public Text timeText;

 

void Time_Calc()
    {
        if (playTime > 0)
        {
            playTime = playTime - 1; //playTime--;
            timeText.text = playTime.ToString();
        }

     }

//한번 호출 될때마다 1초씩 줄어들고 text ui 게임 오브젝트에 남은 시간을 텍스트로 표현하는 Time_Calc 함수 생성

 

2)게임 매니저 스크립트 - InvokeRepeating() 함수 사용

InvokeRepeating("호출함수명", 최초 호출 대기시간, 반복 간격 시간)

 

void Start()
    {
        InvokeRepeating("Time_Calc", 0, 1f);
        EnableCoin();
    }

 

void Time_Calc()
    {
        if (playTime > 0)
        {
            playTime = playTime - 1; //playTime--;
            timeText.text = playTime.ToString();
        }

    }

//게임 시작과 동시에 시간을 계산하기 위해 InvokeRepeating 함수로 Time_Calc 함수를 호출

 

3. 게임 종료 UI 설정

다음과 같이 IMAGE와 TEXT를 생성하고 기본 세팅을 해준다. 스크립트 생성 후 해당 오브젝트를 연결해준다. 그리고 해당 화면은 시간이 다 끝나고 게임 종료화면 시 나타나야 하기 때문에 인스펙터창에 체크박스를 해제하여 비활성화 한 채로 설정한다. 

 

#게임 매니저 스크립트 추가

public GameObject GameOver_Scene   //게임 종료 화면

public Text resultScore;  //최종 점수 출력 텍스트

 

void Time_Calc()
    {
        if (playTime > 0)
        {
            playTime = playTime - 1; //playTime--;
            timeText.text = playTime.ToString();
        }
        else
        {
            GameOver_Scene.SetActive(true); //게임 종료 화면 출력
            resultScore.text = currentScore.ToString();  //현재 점수 출력
            CancelInvoke("Time_Calc");  //더이상 호출 하지 않음
            CancelInvoke("CreateEnemy"); //더이상 호출 하지 않음
        }
    }
}

 

그 다음은 적을 생성할 것이다. 하늘에서 떨어지는 적이 게임 플레이 시간 내 지속적으로 생성되고 플레이어와 충돌 시 

플레이어가 빨갛게 변하면서 일시적으로 이동할 수 없도록 만들어보겠다. 먼저 enemy 프리팹을 씬에 생성한 후 y축을 조정해 floor보다 훨씬 높은 곳에 위치시켰다. 그리고 Sphere collider 추가 / isTrigger 체크 / rigidbody 추가 / use gravity 체크 해제를 통해 기본 세팅을 완료한다. 

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

public class Enemy : MonoBehaviour
{
    public float speed = 0.01f;
    
    void Start()
    {
        
    }

    void Update()
    {
        transform.Translate(Vector3.down * speed); 
    }

    void OnTriggerEnter(Collider other)
    {
        if(other.name == "Floor")
        {
            Destroy(gameObject);
        }
    }
}

Translate() 함수를 사용하여 enemy스크립트를 작성하였고, Destroy()함수를 사용하여 enemy프리팹이 floor바닥에 닿은 경우 삭제되도록 하였다.

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

public class Player : MonoBehaviour
{
    public CharacterController controller;
    public float speed = 0.2f;
    public float x_pos_move;
    public float z_pos_move;
    Vector3 direction; // x, y, z 방향성을 가지고 있는 벡터 변수
    public Game_manager gameManager;
    bool isAttack = false;
    public MeshRenderer meshRD;

    void PlayerMove()
    {
        isAttack = false;
        meshRD.material.color = Color.white;
    }
    void OnTriggerEnter(Collider other)
    {
        if (other.name == "coin")
        {
            gameManager.EnableCoin_Invoke();
            gameManager.SetScore(2);
        }
        else if (other.name.Contains("Enemy") && isAttack == false)
        {
            isAttack = true;
            meshRD.material.color = Color.red;
            Invoke("PlayerMove", 3f); //3초 후 playermove 함수 호출
        }
    }
//캐릭터의 이동 로직 구현
    void Update()
    {
        if (isAttack == false)
        {
            x_pos_move = Input.GetAxis("Horizontal");
            z_pos_move = Input.GetAxis("Vertical");
            direction = new Vector3(x_pos_move, 0, z_pos_move);
            controller.Move(direction * speed);
        }  
    }
}

플레이어 스크립트에 다음 로직을 추가하여 enemy와 충돌 시 빨갛게 변하면서 playermove()함수가 3초동안 실행되지 않도록 했다. 여기서 isAttack()함수와 bool타입을 사용했다. 그리고 pulic으로 선언된 mesh RD에 Player을 연결해주면 된다. 그리고 게임 매니저 스크립트에 <InvokeRepeating("CreateEnemy", 0, 3f);>를 추가해준다.

 

마지막으로 플레이어가 코인에 충돌했을 때 partice effect와 sound effect가 발생하도록 세팅하겠다. 준비된 파티클과 사운드 이펙트 소스를 프리팹으로 가지고 있으면 된다.

 

게임 매니저 스크립트 추가

public ParticleSystem coinParticle;
public AudioSource coinSFX;

 

void CoinEffect()
    {
        coinParticle.transform.position = coin.transform.position;
        coinParticle.Play();
    }

 

 public void EnableCoin_Invoke()
    {
        coin.SetActive(false);
        Invoke("EnableCoin", 2f);
        CoinEffect(); //코인 획득 시 코인 이펙트 함수 호출
        coinSFX.Play(); //코인 획득시 효과음 재생
    }

실행하면 대략 다음과 같은 플레이 화면이 나오게 된다. 좌측 상단 위에는 코인 획득 시 점수(+2씩 상승) 그 아래는 남은 시간을 세팅했으며 코인 획득 시 particle과 sound 이펙트가 생성되며, 지속적으로 생성되는 enemy 프리팹이 하늘에서 떨어지고 floor에 닿을 시 파괴, 플레이어와 충돌시 플레이어가 붉게 변하며 3초간 이동 조작이 되지 않는다. 그리고 해당 시간 초가 지나면 gameover 창과 함께 획득 점수를 나타낸 종료 씬이 생성된다.

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

public class Game_manager : MonoBehaviour
{
    public GameObject coin;
    float random_x_position;
    float random_z_position;
    public Text scoreText;
    int currentScore = 0;
    public int playTime = 30;
    public Text timeText;
    public GameObject GameOver_Scene; //게임 종료 화면
    public Text resultScore; //최종 점수 출력 텍스트
    public GameObject enemy;
    float enemy_x_pos;
    float enemy_z_pos;
    public ParticleSystem coinParticle;
    public AudioSource coinSFX;

    void CreateEnemy()
    {
        enemy_x_pos = Random.Range(-4.5f, 4.5f);
        enemy_z_pos = Random.Range(-4.5f, 4.5f);
        Instantiate(enemy, new Vector3(enemy_x_pos, 5, enemy_z_pos), Quaternion.identity);
    }
    void CoinEffect()
    {
        coinParticle.transform.position = coin.transform.position;
        coinParticle.Play();
    }
    void Start()
    {
        InvokeRepeating("CreateEnemy", 0, 3f);
        InvokeRepeating("Time_Calc", 0, 1f);
        EnableCoin();
    }
    public void EnableCoin()
    {
        coin.SetActive(true);
        random_x_position = Random.Range(-4.5f, 4.5f);
        random_z_position = Random.Range(-4.5f, 4.5f);
        coin.transform.position = new Vector3(random_x_position, 1.5f, random_z_position);
    }
    //코인 게임 오브젝트의 위치를 랜덤하게 표시
    public void EnableCoin_Invoke()
    {
        coin.SetActive(false);
        Invoke("EnableCoin", 2f);
        CoinEffect(); //코인 획득 시 코인 이펙트 함수 호출
        coinSFX.Play(); //코인 획득시 효과음 재생
    }
    //코인을 시간 차를 두고 생성하기 위함
    public void SetScore(int _score)
    {
        currentScore += _score;
        scoreText.text = currentScore.ToString();
    }
    void Time_Calc()
    {
        if (playTime > 0)
        {
            playTime = playTime - 1; //playTime--;
            timeText.text = playTime.ToString();
        }
        else
        {
            GameOver_Scene.SetActive(true); //게임 종료 화면 출력
            resultScore.text = currentScore.ToString();  //현재 점수 출력
            CancelInvoke("Time_Calc");  //더이상 호출 하지 않음
            CancelInvoke("CreateEnemy"); //더이상 호출 하지 않음
        }
    }
}
728x90