일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 다이나믹 프로그래밍
- 유니티
- 입문
- 5월
- c++
- 코딩 기초 트레이닝
- 개인 프로젝트
- 골드메탈
- 코딩 테스트
- 유니티 심화과정
- 2월
- todolist
- 2023년
- 프로그래머스
- 10월
- 1월
- 게임 엔진 공부
- 백준
- 자료 구조
- 3월
- 7월
- 4월
- 기초
- 개인 프로젝트 - 런앤건
- 수학
- 2022년
- 단계별로 풀어보기
- C/C++
- 2025년
- 2024년
- Today
- Total
기록 보관소
[Unity/유니티] 기초-물리 퍼즐게임: 모바일 게임으로 완성하기[BE6] 본문
개요
유니티 입문과 독학을 위해서 아래 링크의 골드메탈님의 영상들을 보며 진행 상황 사진 또는 캡처를 올리고 배웠던 점을 요약해서 적는다.
현재는 영상들을 보고 따라하고 배우는 것에 집중할 것이며, 영상을 모두 보고 따라한 후에는 개인 프로젝트를 설계하고 직접 만드는 것이 목표다.
https://youtube.com/playlist?list=PLO-mt5Iu5TeYI4dbYwWP8JqZMC9iuUIW2
유니티 강좌 기초 채널 Basic
유니티 개발을 처음 시작하시는 입문자 분들을 위한 기초 채널. [ 프로젝트 ] B00 ~ B12 (BE1) : 유니티 필수 기초 B13 ~ B19 (BE2) : 2D 플랫포머 B20 ~ B26 (BE3) : 2D 탑다운 대화형 RPG B27 ~ B37 (BE4) : 2D 종스크롤
www.youtube.com
물리 퍼즐게임: 모바일 게임으로 완성하기[BE6]
1. 변수 정리
//GameManager 스크립트 파일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour {
[Header("============[ Core ]============")]
public bool isOver;
public int score;
public int maxLevel;
[Header("========[ Object Pooling ]========")]
public GameObject donglePrefab;
public Transform dongleGroup;
public List<Dongle> donglePool;
public GameObject effectPrefab;
public Transform effectGroup;
public List<ParticleSystem> effectPool;
[Range(1, 30)] //Inspector 창에서 poolSize가 1~30까지 스크롤형태로 표현됨
public int poolSize;
public int poolCursor;
public Dongle lastDongle;
[Header("===========[ Audio ]===========")]
public AudioSource bgmPlayer;
public AudioSource[] sfxPlayer;
public AudioClip[] sfxClip; //효과음
public enum Sfx { LevelUp, Next, Attach, Button, Over };
int sfxCursor;
void Awake() {
Application.targetFrameRate = 60; //60프레임 이하로 유지
donglePool = new List<Dongle>();
effectPool = new List<ParticleSystem>();
for (int index = 0; index < poolSize; index++)
MakeDongle();
}
void Start() {
bgmPlayer.Play();
NextDongle();
}
Dongle MakeDongle() {
//이펙트 생성
GameObject instantEffectObj = Instantiate(effectPrefab, effectGroup);
instantEffectObj.name = "Effect " + effectPool.Count;
ParticleSystem instantEffect = instantEffectObj.GetComponent<ParticleSystem>();
effectPool.Add(instantEffect);
//동글 생성
GameObject instantDongleObj = Instantiate(donglePrefab, dongleGroup);
instantDongleObj.name = "Dongle " + donglePool.Count;
Dongle instantDongle = instantDongleObj.GetComponent<Dongle>();
instantDongle.manager = this;
instantDongle.effect = instantEffect; //이펙트 전달
donglePool.Add(instantDongle);
return instantDongle;
}
Dongle GetDongle() {
for (int index = 0; index < donglePool.Count; index++) {
poolCursor = (poolCursor + 1) % donglePool.Count;
if (!donglePool[poolCursor].gameObject.activeSelf) //비활성화일때
return donglePool[poolCursor];
}
return MakeDongle();
}
void NextDongle() {
if (isOver)
return;
lastDongle = GetDongle();
lastDongle.level = Random.Range(0, maxLevel);
lastDongle.gameObject.SetActive(true);
SfxPlay(Sfx.Next);
StartCoroutine(WaitNext());
}
IEnumerator WaitNext() {
while (lastDongle != null) {
yield return null;
}
yield return new WaitForSeconds(2.5f);
NextDongle();
}
public void TouchDown() {
if (lastDongle == null)
return;
lastDongle.Drag();
}
public void TouchUp() {
if (lastDongle == null)
return;
lastDongle.Drop();
lastDongle = null; //드랍 후 조종 불가로 만들기
}
public void GameOver() {
if (isOver)
return;
isOver = true;
StartCoroutine("GameOverRoutine");
}
IEnumerator GameOverRoutine() {
// 1. 장면 안에 활성화 되어있는 모든 동글 가져오기
Dongle[] dongles = FindObjectsOfType<Dongle>(); //앞에 GameObject.FindObjectsOfType으로도 가능
// 2. 지우기 전에 모든 동글의 물리효과 비활성화
for (int index = 0; index < dongles.Length; index++) {
dongles[index].rigid.simulated = false;
}
// 3. 1번의 목록을 하나씩 접근해 지우기
for (int index = 0; index < dongles.Length; index++) {
dongles[index].Hide(Vector3.up * 100);
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForSeconds(1f);
SfxPlay(Sfx.Over);
}
public void SfxPlay(Sfx type) {
switch(type) {
case Sfx.LevelUp:
sfxPlayer[sfxCursor].clip = sfxClip[Random.Range(0, 3)];
break;
case Sfx.Next:
sfxPlayer[sfxCursor].clip = sfxClip[3];
break;
case Sfx.Attach:
sfxPlayer[sfxCursor].clip = sfxClip[4];
break;
case Sfx.Button:
sfxPlayer[sfxCursor].clip = sfxClip[5];
break;
case Sfx.Over:
sfxPlayer[sfxCursor].clip = sfxClip[6];
break;
}
sfxPlayer[sfxCursor].Play();
sfxCursor = (sfxCursor + 1) % sfxPlayer.Length; //값이 범위를 넘지 않도록 나머지 연산 사용
}
}
- [Header("string header")] : 인스펙터에 말머리를 추가
- 변수 순서와 위치만 조금 변경하고 Header를 통해 말머리를 추가하였다
2. 점수 시스템 완성
//GameManager 스크립트 파일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour {
[Header("============[ Core ]============")]
public bool isOver;
public int score;
public int maxLevel;
[Header("========[ Object Pooling ]========")]
public GameObject donglePrefab;
public Transform dongleGroup;
public List<Dongle> donglePool;
public GameObject effectPrefab;
public Transform effectGroup;
public List<ParticleSystem> effectPool;
[Range(1, 30)] //Inspector 창에서 poolSize가 1~30까지 스크롤형태로 표현됨
public int poolSize;
public int poolCursor;
public Dongle lastDongle;
[Header("===========[ Audio ]===========")]
public AudioSource bgmPlayer;
public AudioSource[] sfxPlayer;
public AudioClip[] sfxClip; //효과음
public enum Sfx { LevelUp, Next, Attach, Button, Over };
int sfxCursor;
[Header("=============[ UI ]=============")]
public Text scoreText;
public Text maxScoreText;
void Awake() {
Application.targetFrameRate = 60; //60프레임 이하로 유지
donglePool = new List<Dongle>();
effectPool = new List<ParticleSystem>();
for (int index = 0; index < poolSize; index++)
MakeDongle();
if (!PlayerPrefs.HasKey("MaxScore")) { //최고 점수가 없다면
PlayerPrefs.SetInt("MaxScore", 0);
}
maxScoreText.text = PlayerPrefs.GetInt("MaxScore").ToString();
}
void Start() {
bgmPlayer.Play();
NextDongle();
}
Dongle MakeDongle() {
//이펙트 생성
GameObject instantEffectObj = Instantiate(effectPrefab, effectGroup);
instantEffectObj.name = "Effect " + effectPool.Count;
ParticleSystem instantEffect = instantEffectObj.GetComponent<ParticleSystem>();
effectPool.Add(instantEffect);
//동글 생성
GameObject instantDongleObj = Instantiate(donglePrefab, dongleGroup);
instantDongleObj.name = "Dongle " + donglePool.Count;
Dongle instantDongle = instantDongleObj.GetComponent<Dongle>();
instantDongle.manager = this;
instantDongle.effect = instantEffect; //이펙트 전달
donglePool.Add(instantDongle);
return instantDongle;
}
Dongle GetDongle() {
for (int index = 0; index < donglePool.Count; index++) {
poolCursor = (poolCursor + 1) % donglePool.Count;
if (!donglePool[poolCursor].gameObject.activeSelf) //비활성화일때
return donglePool[poolCursor];
}
return MakeDongle();
}
void NextDongle() {
if (isOver)
return;
lastDongle = GetDongle();
lastDongle.level = Random.Range(0, maxLevel);
lastDongle.gameObject.SetActive(true);
SfxPlay(Sfx.Next);
StartCoroutine(WaitNext());
}
IEnumerator WaitNext() {
while (lastDongle != null) {
yield return null;
}
yield return new WaitForSeconds(2.5f);
NextDongle();
}
public void TouchDown() {
if (lastDongle == null)
return;
lastDongle.Drag();
}
public void TouchUp() {
if (lastDongle == null)
return;
lastDongle.Drop();
lastDongle = null; //드랍 후 조종 불가로 만들기
}
public void GameOver() {
if (isOver)
return;
isOver = true;
StartCoroutine("GameOverRoutine");
}
IEnumerator GameOverRoutine() {
// 1. 장면 안에 활성화 되어있는 모든 동글 가져오기
Dongle[] dongles = FindObjectsOfType<Dongle>(); //앞에 GameObject.FindObjectsOfType으로도 가능
// 2. 지우기 전에 모든 동글의 물리효과 비활성화
for (int index = 0; index < dongles.Length; index++) {
dongles[index].rigid.simulated = false;
}
// 3. 1번의 목록을 하나씩 접근해 지우기
for (int index = 0; index < dongles.Length; index++) {
dongles[index].Hide(Vector3.up * 100);
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForSeconds(1f);
int maxScore = Mathf.Max(score, PlayerPrefs.GetInt("MaxScore"));
PlayerPrefs.SetInt("MaxScore", maxScore);
SfxPlay(Sfx.Over);
}
public void SfxPlay(Sfx type) {
switch(type) {
case Sfx.LevelUp:
sfxPlayer[sfxCursor].clip = sfxClip[Random.Range(0, 3)];
break;
case Sfx.Next:
sfxPlayer[sfxCursor].clip = sfxClip[3];
break;
case Sfx.Attach:
sfxPlayer[sfxCursor].clip = sfxClip[4];
break;
case Sfx.Button:
sfxPlayer[sfxCursor].clip = sfxClip[5];
break;
case Sfx.Over:
sfxPlayer[sfxCursor].clip = sfxClip[6];
break;
}
sfxPlayer[sfxCursor].Play();
sfxCursor = (sfxCursor + 1) % sfxPlayer.Length; //값이 범위를 넘지 않도록 나머지 연산 사용
}
void LateUpdate() {
scoreText.text = score.ToString();
}
}
- 앞에 만들었던 점수 Text UI들과 연결하기 위해서 UI namespace를 추가하고, Text 변수 2개를 만들어서 각각 LateUpdate()와 Awake(), GameOverRoutine()에서 점수와 최고 점수를 세팅할 수 있도록 만들었다. 최고 점수의 경우 기존 최고 점수가 없다면 0을, 이후 게임이 오버되면 이전 최고 점수와 현재 점수를 비교해 더 큰 점수를 최고 점수로 저장하고, 다시 실행시 그 값을 보여준다.
3. 게임 종료 UI
//GameManager 스크립트 파일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
[Header("============[ Core ]============")]
public bool isOver;
public int score;
public int maxLevel;
[Header("========[ Object Pooling ]========")]
public GameObject donglePrefab;
public Transform dongleGroup;
public List<Dongle> donglePool;
public GameObject effectPrefab;
public Transform effectGroup;
public List<ParticleSystem> effectPool;
[Range(1, 30)] //Inspector 창에서 poolSize가 1~30까지 스크롤형태로 표현됨
public int poolSize;
public int poolCursor;
public Dongle lastDongle;
[Header("===========[ Audio ]===========")]
public AudioSource bgmPlayer;
public AudioSource[] sfxPlayer;
public AudioClip[] sfxClip; //효과음
public enum Sfx { LevelUp, Next, Attach, Button, Over };
int sfxCursor;
[Header("=============[ UI ]=============")]
public GameObject endGroup;
public Text scoreText;
public Text maxScoreText;
public Text subScoreText;
void Awake() {
Application.targetFrameRate = 60; //60프레임 이하로 유지
donglePool = new List<Dongle>();
effectPool = new List<ParticleSystem>();
for (int index = 0; index < poolSize; index++)
MakeDongle();
if (!PlayerPrefs.HasKey("MaxScore")) { //최고 점수가 없다면
PlayerPrefs.SetInt("MaxScore", 0);
}
maxScoreText.text = PlayerPrefs.GetInt("MaxScore").ToString();
}
void Start() {
bgmPlayer.Play();
NextDongle();
}
Dongle MakeDongle() {
//이펙트 생성
GameObject instantEffectObj = Instantiate(effectPrefab, effectGroup);
instantEffectObj.name = "Effect " + effectPool.Count;
ParticleSystem instantEffect = instantEffectObj.GetComponent<ParticleSystem>();
effectPool.Add(instantEffect);
//동글 생성
GameObject instantDongleObj = Instantiate(donglePrefab, dongleGroup);
instantDongleObj.name = "Dongle " + donglePool.Count;
Dongle instantDongle = instantDongleObj.GetComponent<Dongle>();
instantDongle.manager = this;
instantDongle.effect = instantEffect; //이펙트 전달
donglePool.Add(instantDongle);
return instantDongle;
}
Dongle GetDongle() {
for (int index = 0; index < donglePool.Count; index++) {
poolCursor = (poolCursor + 1) % donglePool.Count;
if (!donglePool[poolCursor].gameObject.activeSelf) //비활성화일때
return donglePool[poolCursor];
}
return MakeDongle();
}
void NextDongle() {
if (isOver)
return;
lastDongle = GetDongle();
lastDongle.level = Random.Range(0, maxLevel);
lastDongle.gameObject.SetActive(true);
SfxPlay(Sfx.Next);
StartCoroutine(WaitNext());
}
IEnumerator WaitNext() {
while (lastDongle != null) {
yield return null;
}
yield return new WaitForSeconds(2.5f);
NextDongle();
}
public void TouchDown() {
if (lastDongle == null)
return;
lastDongle.Drag();
}
public void TouchUp() {
if (lastDongle == null)
return;
lastDongle.Drop();
lastDongle = null; //드랍 후 조종 불가로 만들기
}
public void GameOver() {
if (isOver)
return;
isOver = true;
StartCoroutine("GameOverRoutine");
}
IEnumerator GameOverRoutine() {
// 1. 장면 안에 활성화 되어있는 모든 동글 가져오기
Dongle[] dongles = FindObjectsOfType<Dongle>(); //앞에 GameObject.FindObjectsOfType으로도 가능
// 2. 지우기 전에 모든 동글의 물리효과 비활성화
for (int index = 0; index < dongles.Length; index++) {
dongles[index].rigid.simulated = false;
}
// 3. 1번의 목록을 하나씩 접근해 지우기
for (int index = 0; index < dongles.Length; index++) {
dongles[index].Hide(Vector3.up * 100);
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForSeconds(1f);
//최고 점수 갱신
int maxScore = Mathf.Max(score, PlayerPrefs.GetInt("MaxScore"));
PlayerPrefs.SetInt("MaxScore", maxScore);
//게임 오버 UI
subScoreText.text = "점수 : " + scoreText.text;
endGroup.SetActive(true);
bgmPlayer.Stop();
SfxPlay(Sfx.Over);
}
public void Reset() {
SfxPlay(Sfx.Button);
StartCoroutine("ResetCoroutine");
}
IEnumerator ResetCoroutine() {
yield return new WaitForSeconds(1f);
SceneManager.LoadScene("Main");
}
public void SfxPlay(Sfx type) {
switch(type) {
case Sfx.LevelUp:
sfxPlayer[sfxCursor].clip = sfxClip[Random.Range(0, 3)];
break;
case Sfx.Next:
sfxPlayer[sfxCursor].clip = sfxClip[3];
break;
case Sfx.Attach:
sfxPlayer[sfxCursor].clip = sfxClip[4];
break;
case Sfx.Button:
sfxPlayer[sfxCursor].clip = sfxClip[5];
break;
case Sfx.Over:
sfxPlayer[sfxCursor].clip = sfxClip[6];
break;
}
sfxPlayer[sfxCursor].Play();
sfxCursor = (sfxCursor + 1) % sfxPlayer.Length; //값이 범위를 넘지 않도록 나머지 연산 사용
}
void LateUpdate() {
scoreText.text = score.ToString();
}
}
- 재시작 버튼을 처리하기위해서 SceneManagement namespace를 추가하고, Reset()함수와 ResetCoroutine() 코루틴을 만든다. 또한 앞에서 만든 게임 오버 UI들을 연결하기위해서 UI 헤더에 변수들을 추가하고, GameOverRoutine()에서 이를 처리하도록 만들었다. 게임 오버시 bgm이 멈추는 문장도 추가했다.
4. 게임 시작
//GameManager 스크립트 파일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
[Header("============[ Core ]============")]
public bool isOver;
public int score;
public int maxLevel;
[Header("========[ Object Pooling ]========")]
public GameObject donglePrefab;
public Transform dongleGroup;
public List<Dongle> donglePool;
public GameObject effectPrefab;
public Transform effectGroup;
public List<ParticleSystem> effectPool;
[Range(1, 30)] //Inspector 창에서 poolSize가 1~30까지 스크롤형태로 표현됨
public int poolSize;
public int poolCursor;
public Dongle lastDongle;
[Header("===========[ Audio ]===========")]
public AudioSource bgmPlayer;
public AudioSource[] sfxPlayer;
public AudioClip[] sfxClip; //효과음
public enum Sfx { LevelUp, Next, Attach, Button, Over };
int sfxCursor;
[Header("=============[ UI ]=============")]
public GameObject startGroup;
public GameObject endGroup;
public Text scoreText;
public Text maxScoreText;
public Text subScoreText;
[Header("=============[ ETC ]=============")]
public GameObject line;
public GameObject bottom;
void Awake() {
Application.targetFrameRate = 60; //60프레임 이하로 유지
donglePool = new List<Dongle>();
effectPool = new List<ParticleSystem>();
for (int index = 0; index < poolSize; index++)
MakeDongle();
if (!PlayerPrefs.HasKey("MaxScore")) { //최고 점수가 없다면
PlayerPrefs.SetInt("MaxScore", 0);
}
maxScoreText.text = PlayerPrefs.GetInt("MaxScore").ToString();
}
public void GameStart() {
//오브젝트 활성화
line.SetActive(true);
bottom.SetActive(true);
scoreText.gameObject.SetActive(true);
maxScoreText.gameObject.SetActive(true);
startGroup.SetActive(false);
//사운드 플레이
bgmPlayer.Play();
SfxPlay(Sfx.Button);
//게임 시작(동글 생성)
Invoke("NextDongle", 1.5f); //1.5초 딜레이
}
Dongle MakeDongle() {
//이펙트 생성
GameObject instantEffectObj = Instantiate(effectPrefab, effectGroup);
instantEffectObj.name = "Effect " + effectPool.Count;
ParticleSystem instantEffect = instantEffectObj.GetComponent<ParticleSystem>();
effectPool.Add(instantEffect);
//동글 생성
GameObject instantDongleObj = Instantiate(donglePrefab, dongleGroup);
instantDongleObj.name = "Dongle " + donglePool.Count;
Dongle instantDongle = instantDongleObj.GetComponent<Dongle>();
instantDongle.manager = this;
instantDongle.effect = instantEffect; //이펙트 전달
donglePool.Add(instantDongle);
return instantDongle;
}
Dongle GetDongle() {
for (int index = 0; index < donglePool.Count; index++) {
poolCursor = (poolCursor + 1) % donglePool.Count;
if (!donglePool[poolCursor].gameObject.activeSelf) //비활성화일때
return donglePool[poolCursor];
}
return MakeDongle();
}
void NextDongle() {
if (isOver)
return;
lastDongle = GetDongle();
lastDongle.level = Random.Range(0, maxLevel);
lastDongle.gameObject.SetActive(true);
SfxPlay(Sfx.Next);
StartCoroutine(WaitNext());
}
IEnumerator WaitNext() {
while (lastDongle != null) {
yield return null;
}
yield return new WaitForSeconds(2.5f);
NextDongle();
}
public void TouchDown() {
if (lastDongle == null)
return;
lastDongle.Drag();
}
public void TouchUp() {
if (lastDongle == null)
return;
lastDongle.Drop();
lastDongle = null; //드랍 후 조종 불가로 만들기
}
public void GameOver() {
if (isOver)
return;
isOver = true;
StartCoroutine("GameOverRoutine");
}
IEnumerator GameOverRoutine() {
// 1. 장면 안에 활성화 되어있는 모든 동글 가져오기
Dongle[] dongles = FindObjectsOfType<Dongle>(); //앞에 GameObject.FindObjectsOfType으로도 가능
// 2. 지우기 전에 모든 동글의 물리효과 비활성화
for (int index = 0; index < dongles.Length; index++) {
dongles[index].rigid.simulated = false;
}
// 3. 1번의 목록을 하나씩 접근해 지우기
for (int index = 0; index < dongles.Length; index++) {
dongles[index].Hide(Vector3.up * 100);
yield return new WaitForSeconds(0.1f);
}
yield return new WaitForSeconds(1f);
//최고 점수 갱신
int maxScore = Mathf.Max(score, PlayerPrefs.GetInt("MaxScore"));
PlayerPrefs.SetInt("MaxScore", maxScore);
//게임 오버 UI
subScoreText.text = "점수 : " + scoreText.text;
endGroup.SetActive(true);
bgmPlayer.Stop();
SfxPlay(Sfx.Over);
}
public void Reset() {
SfxPlay(Sfx.Button);
StartCoroutine("ResetCoroutine");
}
IEnumerator ResetCoroutine() {
yield return new WaitForSeconds(1f);
SceneManager.LoadScene("Main");
}
public void SfxPlay(Sfx type) {
switch(type) {
case Sfx.LevelUp:
sfxPlayer[sfxCursor].clip = sfxClip[Random.Range(0, 3)];
break;
case Sfx.Next:
sfxPlayer[sfxCursor].clip = sfxClip[3];
break;
case Sfx.Attach:
sfxPlayer[sfxCursor].clip = sfxClip[4];
break;
case Sfx.Button:
sfxPlayer[sfxCursor].clip = sfxClip[5];
break;
case Sfx.Over:
sfxPlayer[sfxCursor].clip = sfxClip[6];
break;
}
sfxPlayer[sfxCursor].Play();
sfxCursor = (sfxCursor + 1) % sfxPlayer.Length; //값이 범위를 넘지 않도록 나머지 연산 사용
}
void Update() {
if (Input.GetButtonDown("Cancel")) { //모바일 뒤로 가기 버튼(esc와 동일)을 눌렀다면
Application.Quit(); //끄기
}
}
void LateUpdate() {
scoreText.text = score.ToString();
}
}
- 앞에서 비활성화했던 배경 UI 및 오브젝트들을 게임 시작시 활성화하기 위해서 ETC 헤더를 만들고 거기에 GameObject 변수들을 추가했다.
- 그리고 버튼 클릭시 게임 시작을 할 수 있도록 GameStart()함수를 만들어서 앞의 변수들을 활성화하는 동시에, 기존의 Start() 함수에 있던 사운드 플레이 및 동글 생성 함수 작동 기능도 가능하도록 했다.
- 동글 생성의 경우 시작과 동시에 바로 생성하지 않고 Invoke를 통해서 1.5초 뒤에 생성되도록 했다.
- 또한 Update에서 모바일에서 뒤로가기 키(컴퓨터 ESC 키)를 눌렀을때 종료되도록 추가했다.
5. 모바일 빌드
'유니티 프로젝트 > 물리 퍼즐게임' 카테고리의 다른 글
[Unity/유니티] 기초-물리 퍼즐게임: 쉽게 구현해보는 오브젝트풀링[B60] (0) | 2022.04.27 |
---|---|
[Unity/유니티] 기초-물리 퍼즐게임: 채널링이 포함된 사운드 시스템[B59] (0) | 2022.04.24 |
[Unity/유니티] 기초-물리 퍼즐게임: 게임 오버 구현하기[B58] (0) | 2022.04.23 |
[Unity/유니티] 기초-물리 퍼즐게임: 멋진 이펙트 만들기[B57] (0) | 2022.04.22 |
[Unity/유니티] 기초-물리 퍼즐게임: 물리 이벤트로 동글 합치기[B56] (0) | 2022.04.17 |