주말은 푹 쉬고 오늘부터 다시 Unity 강의 시작!
오늘 만들 게임은 라이즈 업! 이라는 게임과 유사하다.
풍선과 풍선을 지킬 실드를 만들어서 풍선 위로 떨어지는 오브젝트를 실드로 지켜내는 게임이다.
기본세팅은 잊지말고 2by3 레이아웃과 해상도 조절, 씬 이름을 메인 씬으로 변경해준다.
스퀘어 스프라이트를 만들고 색상과 크기를 조절하고 백그라운로 이름을 변경한다.
이제 메인이 될 풍선을 만들어준다. 2D Sprite 중에 Cicle을 선택하고 위치를 조정해주자.
풍선을 지켜줄 실드도 만들어준다.
실드는 크기를 작게 0.5로 설정해주었다.
시간을 표시해줄 UI도 하나 추가해준다.
Balloon에 애니메이션을 추가한 후 색상을 변경해 깜빡이는 효과를 추가해준다.
이제 실드 스크립트에 마우스를 따라 움직이도록 스크립트를 추가해보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shield : MonoBehaviour
{
void Start()
{
}
void Update()
{
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);//마우스의 좌표를 월드 좌표로 바꿔줌
}
}
mousePos이라는 변수를 생성해 마우스의 좌표를 메인카메라가 촬영중인 월드 좌표로 변경해 담아주자.
void Update()
{
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
transform.position = mousePos; //위치를 마우스 위치로 변경한다.
}
업데이트 함수에 넣었기 때문에 매 프레임마다 마우스의 위치로 이동할 것이다. 즉 마우스를 따라 움직이는 모양이 된다.
떨어지는 장애물을 만들기 위해 Box Collider 2D와 Rigidbody 2D를 추가해준다.
마찬가지로 실드와 풍선에도 Circle Collider 2D를 추가하는 걸 잊지 말자.
Square 스크립트를 생성해 랜덤한 사이즈와 위치에서 생성되게 설정해보자.
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using UnityEngine;
public class Square : MonoBehaviour
{
void Start()
{
float x = Random.Range(-3.0f, 3.0f); //x라는 변수에 -3.0 ~ 3.0의 랜덤 값 생성
float y = Random.Range(3.0f, 5.0f); //y라는 변수에 3.0 ~ 5.0의 랜덤 값 생성
transform.position = new Vector2(x, y); //x ,y 랜덤 값으로 위치 변경
float size = Random.Range(0.5f, 1.5f); //size라는 변수에 0.5 ~ 1.5의 랜덤 값 생성
transform.localScale = new Vector2(size, size); //size*size 크기로 변경
}
void Update()
{
if (transform.position.y < -6) //포지션 Y값이 -6보다 작다면
{
Destroy(this.gameObject); //이 오브젝트를 파괴한다.
}
}
이제 빈 Hierachy인 GameManager를 만들고 스크립트를 작성해보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
public GameObject square; //square Prefab을 참조한다.
void Start()
{
InvokeRepeating("MakeSquare", 0f, 1f); //0초부터 매 1초마다 MakeSquare 함수를 실행한다.
}
// Update is called once per frame
void Update()
{
}
void MakeSquare()
{
Instantiate(square); //squre를 만든다.
}
}
이제 실행해보면?
이제 풍선에 닿으면 풍선이 터지고 게임이 끝나는 부분과 시간 UI를 작동시켜보자
게임매니저 스크립트를 다시 수정하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //UI에 접근
public class GameManager : MonoBehaviour
{
public GameObject square; //square Prefab을 참조한다.
public Text timeTxt; //timeTxt를 참조한다.
float time = 0.0f;
void Start()
{
InvokeRepeating("MakeSquare", 0f, 1f); //0초부터 매 1초마다 MakeSquare 함수를 실행한다.
}
// Update is called once per frame
void Update()
{
time += Time.deltaTime; //델타 타임은 프레임과 상관없이 모든 기기에서 같은 시간을 가짐
timeTxt.text = time.ToString("N2"); //소숫점 2자리 수까지 문자열로 입력
}
void MakeSquare()
{
Instantiate(square); //squre를 만든다.
}
}
using UnityEngine.UI에 접근해서 Text 오브젝트를 만들어서 시간 값을 안에 넣어준다.
우선 게임 종료를 위해 EndPanel UI를 만들어주자
엔드패널을 다 만들었다면 다시 게임매니저로 돌아가자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //UI에 접근
public class GameManager : MonoBehaviour
{
public static GameManager instance;
public GameObject square; //square Prefab을 참조한다.
public Text timeTxt; //timeTxt를 참조한다.
public GameObject endPanel; //endPanel를 참조한다.
public Text currentScore; //currentScore를 참조한다.
public Text bestScore; //bestScore를 참조한다.
float time = 0.0f;
private void Awake() //싱글톤 선언
{
if(instance == null) //인스턴스 값이 비어있다면
{
instance = this;
}
}
void Start()
{
InvokeRepeating("MakeSquare", 0f, 1f); //0초부터 매 1초마다 MakeSquare 함수를 실행한다.
}
// Update is called once per frame
void Update()
{
time += Time.deltaTime; //델타 타임은 프레임과 상관없이 모든 기기에서 같은 시간을 가짐
timeTxt.text = time.ToString("N2"); //소숫점 2자리 수까지 문자열로 입력
}
void MakeSquare()
{
Instantiate(square); //squre를 만든다.
}
public void GameOver() //게임오버 함수
{
Time.timeScale = 0f; //시간을 멈춘다.
currentScore.text = time.ToString("N2");
endPanel.SetActive(true); //엔드패널 활성화
}
}
게임오버 함수를 추가하고 게임매니저를 싱글톤 선언해 다른 곳에서 참조할 수 있게 해주자
이번엔 Squre 스크립트를 열어서
private void OnCollisionEnter2D(Collision2D collision) //충돌 함수 호출
{
if(collision.gameObject.CompareTag("Player")) //Player 태그를 가진 객체와 충돌한다면
{
GameManager.instance.GameOver(); //게임오버 함수를 호출한다.
}
}
풍선에 Player 태그를 추가해주고 Player 태그와 충돌한다면 게임오버가 되게 설정해준다.
RetryBtn 스크립트를 만들고 수정하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; //씬매니저 참조
public class RetryBtn : MonoBehaviour
{
public void Retry()
{
SceneManager.LoadScene("MainScene"); //메인씬을 다시 불러온다.
}
}
스크립트 파일을 버튼에 먹여주고 온클릭 부분에 추가해준다.
이제 정상적으로 작동하는지 확인해보자.
잘 작동되는 것을 볼 수 있다.
이제 최고점수 기능을 만들어보자.
게임매니저의 게임오버 함수를 수정하자.
public void GameOver() //게임오버 함수
{
isPlay = false;
Time.timeScale = 0f; //시간을 멈춘다.
currentScore.text = time.ToString("N2");
if(PlayerPrefs.HasKey("bestScore"))//최고 점수가 있다면
{
float best = PlayerPrefs.GetFloat("bestScore"); //best 변수 값에 베스트 스코어를 넣는다.
if(best < time) //이번 플레이의 시간이 최고 기록보다 높다면
{
PlayerPrefs.SetFloat("bestScore", time); //현재 점수를 최고 기록에 저장한다.
bestScore.text = time.ToString("N2");
}
else
{
bestScore.text = best.ToString("N2"); //최고 점수를 최고 기록에 저장한다.
}
}
else//최고 점수가 없다면
{
PlayerPrefs.SetFloat("bestScore", time); //현재 점수를 최고 기록에 저장한다.
}
endPanel.SetActive(true); //엔드패널 활성화
}
실행해보면?
다시 실행해서 최고 점수보다 낮은 점수에서 끝내보자
마지막으로 최고 점수를 넘겨보자
진짜 마지막으로 풍선이 닿으면 터지게 만들어보자.
풍선애니메이션 idle을 켜고 Create New Clip버튼을 눌러 새 클립을 만들어 주자
터지는 듯한 효과를 적용한 뒤 Window > Animation > Animator 창을 열어보자.
make Transition을 눌러 BalloonDie로 연결해준다.
Parameter창에서 불을 추가해주고
컨디션에 isDie가 트루라면 BalloonDie를 실행하도록 한다.
다시 게임매니저로 이동한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //UI에 접근
public class GameManager : MonoBehaviour
{
public static GameManager instance;
public GameObject square; //square Prefab을 참조한다.
public Text timeTxt; //timeTxt를 참조한다.
public GameObject endPanel; //endPanel를 참조한다.
public Text currentScore; //currentScore를 참조한다.
public Text bestScore; //bestScore를 참조한다.
public Animator anim; //Animator anim을 참조한다.
bool isPlay = true;
float time = 0.0f;
string key = "bestScore";
private void Awake() //싱글톤 선언
{
if(instance == null) //인스턴스 값이 비어있다면
{
instance = this;
}
}
void Start()
{
Time.timeScale = 1.0f;
InvokeRepeating("MakeSquare", 0f, 1f); //0초부터 매 1초마다 MakeSquare 함수를 실행한다.
}
// Update is called once per frame
void Update()
{
if(isPlay == true)
{
time += Time.deltaTime; //델타 타임은 프레임과 상관없이 모든 기기에서 같은 시간을 가짐
timeTxt.text = time.ToString("N2"); //소숫점 2자리 수까지 문자열로 입력
}
}
void MakeSquare()
{
Instantiate(square); //squre를 만든다.
}
public void GameOver() //게임오버 함수
{
isPlay = false;
anim.SetBool("isDie", true);
Invoke("TimeStop", 0.5f);
currentScore.text = time.ToString("N2");
if (PlayerPrefs.HasKey(key))//최고 점수가 있다면
{
float best = PlayerPrefs.GetFloat(key); //best 변수 값에 베스트 스코어를 넣는다.
if (best < time) //이번 플레이의 시간이 최고 기록보다 높다면
{
PlayerPrefs.SetFloat(key, time); //현재 점수를 최고 기록에 저장한다.
bestScore.text = time.ToString("N2");
}
else
{
bestScore.text = best.ToString("N2"); //최고 점수를 최고 기록에 저장한다.
}
}
else//최고 점수가 없다면
{
PlayerPrefs.SetFloat(key, time); //현재 점수를 최고 기록에 저장한다.
}
endPanel.SetActive(true); //엔드패널 활성화
}
void TimeStop()
{
Time.timeScale = 0.0f; //시간을 멈춘다.
}
}
애니메이터 Anim 변수를 선언해서 Balloon 애니메이터를 참조할 수 있게 한 후 게임오버 함수에 아까 만든 애니메이션 조건문을 True로 설정하게 한 다음 시간을 멈추는 부분을 TimeStop함수로 빼내서 Invoke로 애니메이션이 재생될 시간을 벌어주었다.
0828 TIL - 르탄이 찾기 카드게임 만들기 (7) | 2024.08.28 |
---|---|
0827 TIL - 고양이 밥주기 게임 제작 (2) | 2024.08.27 |
0823 TIL - 빗물 받는 르탄 제작 _2 (0) | 2024.08.23 |
0822 TIL - 빗물 받는 르탄 제작 _1 (0) | 2024.08.22 |
0821 TIL - C# 기초문법_1 (0) | 2024.08.21 |