-
(1) 챌린지 모드 제작Galaxy Ball/3. 싱글플레이 - 챌린지모드 2024. 6. 24. 17:52
챌린지 모드란, 적 유닛도, 상대방도 없는 빈 영역에서 끊임없이 구체가 발사되며,
플레이어는 본인의 구체를 날려 끊임없이 생성되는 적 구체를 제거해 나가야 한다
여기서 스코어 시스템이 추가되어 적 구체를 하나 제거할때마다 1점이 더해진다
시간이 가면 갈수록 적 구체가 발사되는 간격이 짧아지고,
기존 패배조건처럼 플레이어의 공이 데드존에 닿거나, 모든 구체의 합이 15개가 넘어가면 종료된다
이는 이 게임안에 있는 유일한 스코어 게임으로 신기록을 계속 갱신해 나갈 수 있으며
게임 특성상 구체가 어느방향으로 날아갈지 발사선을 보여주지 않기에 기본기 연습 목적으로도
굉장히 좋은 모드가 될 수 있다
우선 기본적인 판은 싱글플레이 모드와 거의 똑같이 가져왔다. 그나마 차이점이라면
우측 상단에 스코어가 기록된다는것
사실 거의 다른거 없고 싱글플레이 모드에서 구체만 랜덤생성 해주면 되니 날로 먹을 수 있을줄 알았지만
시스템 상 같은 코드를 공유할수가 없어 결국 챌린지 모드용 스크립트와 프리팹들을 하나씩 새로 제작해주었다
생성되는 아이템은 싱글플레이와 달리 Endless를 제외하고 BlackHole 아이템을 추가시켰다
그리고 아이템이 너무 자주 생성되면 밸런스가 쉬워지기에 아이템 생성시간을 8~16초로 잡아주었다
using UnityEngine; public class BulletSpawn : MonoBehaviour { public GameObject[] bullets; public float spawnInterval = 10f; public float minimumSpawnInterval = 1f; public float minForce = 1.7f; public float maxForce = 7f; private BoxCollider2D backgroundCollider; private float timer; void Start() { GameObject background = GameObject.Find("BackGround"); if (background != null) { backgroundCollider = background.GetComponent<BoxCollider2D>(); } timer = spawnInterval; } void Update() { timer -= Time.deltaTime; if (timer <= 0f) { SpawnBullet(); spawnInterval = Mathf.Max(minimumSpawnInterval, spawnInterval - 0.2f); timer = spawnInterval; } } void SpawnBullet() { float x = Random.Range(backgroundCollider.bounds.min.x, backgroundCollider.bounds.max.x); float y = Random.Range(backgroundCollider.bounds.min.y, backgroundCollider.bounds.max.y); Vector2 spawnPosition = new Vector2(x, y); int randomIndex = Random.Range(0, bullets.Length); GameObject bulletPrefab = bullets[randomIndex]; GameObject bullet = Instantiate(bulletPrefab, spawnPosition, Quaternion.identity); Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>(); if (rb != null) { Vector2 forceDirection = Random.insideUnitCircle.normalized; float forceMagnitude = Random.Range(minForce, maxForce); rb.AddForce(forceDirection * forceMagnitude, ForceMode2D.Impulse); } } }
챌린지 모드에만 존재하는 BulletSpawn. 말 그대로 일정시간이 찰 때마다 총알프리팹을 생성시키는데다
발사하는 방향, 힘까지 랜덤으로 정해줘 발사까지 시켜준다
챌린지 모드는 영원히 할 수 있는 모드가 아니기에 언젠가는 게임을 끝내줘야 한다. 그렇기에
void Update()
{
timer -= Time.deltaTime;
if (timer <= 0f)
{
SpawnBullet();
spawnInterval = Mathf.Max(minimumSpawnInterval, spawnInterval - 0.2f);
timer = spawnInterval;
}
}한번 구체가 생성될때마다 생성 시간을 0.2초 줄여 시간이 흐르면 흐를수록 점점 난이도가 높아지도록 유도하였다
생성되는 총알은 Normal Bullet. 원래는 이런저런 다양한 총알들을 넣어주려 했으나
기본기 연습이 목적이기도 하기에 깔끔하게 기본적인 프리팹 하나만 사용하기로 했다
using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; public class ChallengeGameManager : MonoBehaviour { public int maxscorenum; public int scorenum; public TMP_Text maxscoretext; public TMP_Text scoretext; private void Start() { // 게임 시작 시 저장된 maxscorenum 불러오기 maxscorenum = PlayerPrefs.GetInt("MaxScore", 0); maxscoretext.text = "Best : " + maxscorenum.ToString(); P1firezone.gameObject.SetActive(true); } ..... private void Update() { if (maxscorenum < scorenum) { maxscorenum = scorenum; // maxscorenum이 갱신될 때마다 저장 PlayerPrefs.SetInt("MaxScore", maxscorenum); PlayerPrefs.Save(); } maxscoretext.text = "Best : " + maxscorenum.ToString(); scoretext.text = "Score : " + scorenum.ToString();
그리고 새로 추가되는 점수 시스템. 드디어 처음으로 이 게임에 저장/불러오기 기능이 사용되었다
전에 배웠던 PlayerPrefs 기능을 사용했다.
가장 먼저 점수 저장할 변수 scorenum, maxscorenum을 사용하였고
이 두가지 숫자를 텍스트로 출력할 scoretext, maxscoretext를 선언해주었다
if (maxscorenum < scorenum)
{
maxscorenum = scorenum;
// maxscorenum이 갱신될 때마다 저장
PlayerPrefs.SetInt("MaxScore", maxscorenum);
PlayerPrefs.Save();
}scorenum은 총알이 파괴될때마다 1씩 증가하고, maxscorenum은 scorenum이 maxscorenum을 넘어버리는 순간
그때부터 함께 증가하도록 설정하였다
그리고 maxscorenum은 게임을 종료하더라도 저장되도록 하였다. 자 그럼 이 스코어는 언제 어디서 증가시킬까?
if (coll.gameObject.name == "SPInvincibleF(Clone)") { chmanager.scorenum++; Destroy(gameObject); } if ((coll.gameObject.tag == "P1ball" || coll.gameObject.tag == "P2ball" || coll.gameObject.tag == "P1Item" || coll.gameObject.tag == "P2Item" || coll.gameObject.tag == "EnemyBall" || coll.gameObject.tag == "Item") && rigid == null) { if (randomNumber > 0) { randomNumber--; textMesh.text = randomNumber.ToString(); } if (randomNumber <= 0) { chmanager.scorenum++; Destroy(gameObject); } } if (coll.gameObject.name == "SPTwiceF(Clone)" || coll.gameObject.name == "TwiceBullet(Clone)") { randomNumber -= 1; textMesh.text = randomNumber.ToString(); if (randomNumber <= 0) { chmanager.scorenum++; Destroy(gameObject); } }
바로 총알을 관리하는 EnemyBulletcontrol에서 Hp가 0이되어 파괴되기직전 chmanager.scorenum을 1 더해주고
그 다음에 파괴되도록 했다.
플레이 영상. 이제 게임이 종료됐을때 뜨게 될 씬을 하나 더 만들어주자
이름은 ChFailScene. 재도전을 누르면 다시 챌린지 씬으로 이동, 좌측하단에 빨간 화살표 버튼을 누르면
메인메뉴씬으로 이동하게 된다. 이것까진 특별한게 없고 점수를 출력해야하는게 특별하다면 특별한건데
내가 원하는건
"당신의 점수는"
"Best Score : 9"
"Score : 3"
이렇게 뜨길 원한다. 그럴려면 최고기록과 방금 세운 현재 기록을 둘다 가져와야 하는데
다행히 최고기록은 저장을 해놓은 상태니 가져오는게 어렵지 않지만 문제는 씬이 이동하면 지워지는 현재 기록이다
그래서 이 데이터는 static으로 CurrentScore라는 변수를 하나 더 만들어
구체가 15개가 넘어 ChallengeFail씬으로 넘어가기 직전에 이 안에 scorenum 값을 넣어준뒤
using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; using static ChallengeGameManager; public class ChfailManager : MonoBehaviour { public Button retry; public Button back; public TMP_Text scoretext; void Start() { this.retry.onClick.AddListener(() => { SceneManager.LoadScene("ChallengeScene"); }); this.back.onClick.AddListener(() => { SceneManager.LoadScene("Start Scene"); }); int maxScore = PlayerPrefs.GetInt("MaxScore", 0); // 저장된 스코어 가져오기 scoretext.text = "Best Score : " + maxScore + "\nScore : " + GameData.CurrentScore.ToString(); }
ChfailManager라는 fail씬 전용관리 스크립트에서 CurrentScore를 출력해주었다
추가로 MaxScore라는 이름으로 저장된 스코어를 가져와 maxScore도 함께 출력해주었다
public class ChDeadzone : MonoBehaviour { public bool isExpand; private void OnTriggerEnter2D(Collider2D collision) { if (collision.gameObject.tag == "P1ball") { BallController ball = collision.GetComponent<BallController>(); if (!ball.hasExpanded) { ChallengeGameManager chgamemanager = FindObjectOfType<ChallengeGameManager>(); GameData.CurrentScore = chgamemanager.scorenum; SceneManager.LoadScene("ChallengeFail"); } }
게임이 종료되는 조건은 총 2가지. 구체가 15개가 넘어가는것 말고도 내 공이 Deadzone에 닿는것
그러므로 Deadzone을 관리하는 스크립트에서도 수정해준다
이제 씬변환에 점수 표시까지 잘 되는것을 확인할 수 있다
'Galaxy Ball > 3. 싱글플레이 - 챌린지모드' 카테고리의 다른 글
(2) 챌린지 모드 수정 (1) 2024.10.25