-
(18) 아이템 #랜덤 생성Galaxy Ball/1. 멀티플레이 - 대전모드 2024. 4. 3. 16:45
우선 시작하기전에 아이템을 랜덤 생성시킬 스크립트는 어디에 들어가야할지부터 생각해보겠다
using System; using UnityEngine; public class GameManager : MonoBehaviour { public GameObject P1ballPrefab; public GameObject P2ballPrefab; public GameObject P1firezone; public GameObject P2firezone; private Vector3 clickPosition; public bool isDragging = false; public static float shotDistance; public static Vector3 shotDirection; private bool P1FireMode = true; private bool P2FireMode = false; private void Start() { P1firezone.gameObject.SetActive(true); P2firezone.gameObject.SetActive(true); } private void Update() { if (Input.GetMouseButtonDown(0)) { clickPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); clickPosition.z = 0f; Collider2D[] colliders = Physics2D.OverlapPointAll(clickPosition); foreach (Collider2D collider in colliders) { if (P1FireMode && collider.gameObject == P1firezone) { Instantiate(P1ballPrefab, clickPosition, Quaternion.identity); P1FireMode = false; P2FireMode = true; isDragging = true; P1firezone.gameObject.SetActive(false); P2firezone.gameObject.SetActive(true); break; } if (P2FireMode && collider.gameObject == P2firezone) { Instantiate(P2ballPrefab, clickPosition, Quaternion.identity); P1FireMode = true; P2FireMode = false; isDragging = true; P1firezone.gameObject.SetActive(true); P2firezone.gameObject.SetActive(false); break; } } } if (isDragging && Input.GetMouseButtonUp(0)) { Vector3 currentPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); currentPosition.z = 0f; GameManager.shotDistance = Vector3.Distance(clickPosition, currentPosition); Vector3 dragDirection = (currentPosition - clickPosition).normalized; GameManager.shotDirection = -dragDirection; isDragging = false; } } }
사실 어디 들어가냐고 해봤자 GameManager인 여기에 들어가냐마냐긴 하지만
구체 생성, 구체의 힘&방향 결정, 턴제 구현을 전부 하고 있는
GameManager에 랜덤 생성까지 들어가기에는 무리가 있어보인다
무엇보다 여기서 구체 생성 역할을 맡고 있어 이후에 아이템 기능 적용도 이곳에서 이루어질것 같으니
랜덤 생성은 다른 스크립트에서 맡는걸로 하겠다
우선 랜덤 생성 스크립트가 들어가는 씬은 당연히 인게임씬이다.
하지만 인게임씬에 너무 오브젝트들이 많아지고 있으니
오브젝트 GameManager에 GameManager와 Main Button Manager를 함께 넣는걸로 하겠다
그리고 여기에 랜덤 생성 스크립트까지 넣어주기로 하겠다
GameManager에 새로운 스크립트 Random Generate를 만들어 넣어준뒤 이제 생각해보자
어떻게하면 랜덤생성을 구현할 수 있을까?
우선 처음에 고안한 방법은
"10~15초 사이에 랜덤한 아이템을 플레이 영역에 생성하되 아이템 마다 드랍률을 각자 다르게 잡는다" 였다
그럼 이제 이걸 단계별로 구현하도록 나눠보자
1. 10~15초마다 플레이 영역 한정 랜덤한 곳에 구체를 생성
2. 그 구체는 내가 정해놓은 확률에 따라 구체의 이미지가 달라짐
3. 내가 발사한 구체가 랜덤생성 구체에 충돌하는 순간 사라짐(발사가 아닌 팽창되는 과정에서 충돌하는것도 충돌판정)
4. 사라진 구체(먹은 아이템)는 내가 지정해놓은 위치에 아이템 보관함에 버튼으로 활성화
5. 보관 가능한 아이템의 갯수는 최대 3개. 먹은 순서대로 아이템창에 보관
6. 아이템 기능구현
7. 내 턴에 보관한 아이템을 클릭시 아이템 기능이 구현되어 게임에 적용됨
우선 이번글(아이템 랜덤생성)에서는 1,2번까지
다음글(아이템 UI)에서는 3~5번까지
다다음글(아이템 기능구현)에서는 6,7번을 구현해보도록 하겠다
우선 가장 간단한 랜덤 생성부터 구현해보도록 하자
using UnityEngine; public class SphereSpawner : MonoBehaviour { public GameObject spherePrefab; public GameObject background; public float minSpawnTime = 3f; public float maxSpawnTime = 5f; private float nextSpawnTime; private Collider2D backgroundCollider; void Start() { nextSpawnTime = Time.time + Random.Range(minSpawnTime, maxSpawnTime); backgroundCollider = background.GetComponent<Collider2D>(); } void Update() { if (Time.time >= nextSpawnTime) { SpawnSphere(); // 구체 생성 nextSpawnTime = Time.time + Random.Range(minSpawnTime, maxSpawnTime); } } void SpawnSphere() { Vector2 min = backgroundCollider.bounds.min; Vector2 max = backgroundCollider.bounds.max; Vector3 randomPosition = new Vector3(Random.Range(min.x, max.x), Random.Range(min.y, max.y), 0f); Instantiate(spherePrefab, randomPosition, Quaternion.identity); } }
우선 코드에서 콜라이더를 이용했기 때문에 이제 BackGround에도 Box Collider를 넣어줘야 한다
랜덤 생성되는 위치를 정하는데에는 bounds라는 기능과 min&max(최소 & 최대 지점 꼭짓점)을 이용하여 만들었다
우선 보기 쉽게 생성시간을 3~5초 사이로 대폭 줄였고, 지정한 시간내에 잘 생성되는것을 확인할 수 있다
근데 위의 영상에서는 생성된 구체가 정가운데 고정구체 위에 올라가는것을 볼 수 있다
원래는 아예 저 영역에는 생성이 되지 못하도록 만들어야 할까 했지만 그러려면 코드가 너무나도 복잡해지고
크게 게임에 지장이 되는것도 아니기에 그렇게까진 가지 않고 다만 생성구체가 고정구체 밑에 깔리는걸로 하겠다
이것 역시 굳이 코드에 한줄 추가하기보다는
고정 구체의 레이어를 바꿔주기로 하자
2. 그 구체는 내가 정해놓은 확률에 따라 구체의 이미지가 달라짐
확률을 정하기 전에 우선은 일정한 확률로 각자 이미지, 정확히는 생성되는 프리펩이 달라지게 코드를 작성해보겠다
using UnityEngine; public class SphereSpawner : MonoBehaviour { public GameObject[] spherePrefabs; public GameObject background; public float minSpawnTime = 10f; public float maxSpawnTime = 15f; private float nextSpawnTime; private Collider2D backgroundCollider; void Start() { nextSpawnTime = Time.time + Random.Range(minSpawnTime, maxSpawnTime); backgroundCollider = background.GetComponent<Collider2D>(); } void Update() { if (Time.time >= nextSpawnTime) { SpawnSphere(); nextSpawnTime = Time.time + Random.Range(minSpawnTime, maxSpawnTime); } } void SpawnSphere() { Vector2 min = backgroundCollider.bounds.min; Vector2 max = backgroundCollider.bounds.max; Vector3 randomPosition = new Vector3(Random.Range(min.x, max.x), Random.Range(min.y, max.y), 0f); int randomIndex = Random.Range(0, spherePrefabs.Length); Instantiate(spherePrefabs[randomIndex], randomPosition, Quaternion.identity); } }
달라진게 있다면 이제 코드 맨 윗줄에서 구체의 프리팹을 Gameobject[] 배열로 받는다는것,
그리고 코드 맨 밑부분에서 생성시 spherePrefabs[randomIndex] 로 랜덤 생성한다는것이다
이제 프리팹까지 랜덤으로 생성되는것을 확인할 수 있다. 이제는 내가 직접 이 확률을 조작할 수 있게 짜보겠다
이 아이템들은 전부 똑같은 성능이 아니다. 그렇기에 드랍률을 전부 똑같게 해줄 수 없다
(아 그리고 게임 만들면서 레이어 순서도 항상 체크해주면서 가자.
글에 적진 않았지만 지금처럼 오브젝트가 많아질수록 레이어가 엉망진창이 될 확률이 크다)
아이템 티어창이다. 높을수록 성능이 좋고 보기 힘든 아이템이며
같은 등급이라면 왼쪽에 있을수록 더 희귀한 아이템으로 정리를 해보았다
...를 하려 했으나 도대체 이 랜덤의 기준이 뭔지 아무리 코드를 수정하고 수정해봐도 나온것만 또 나오고
정해둔 확률은 별로 의미도 없는것같아 깔끔하게 모든 프리팹이 랜덤으로 생성되도록 하겠다
using UnityEngine; public class SphereSpawner : MonoBehaviour { public GameObject[] spherePrefabs; public GameObject background; public float minSpawnTime = 7f; public float maxSpawnTime = 12f; private float nextSpawnTime; private Collider2D backgroundCollider; void Start() { nextSpawnTime = Time.time + Random.Range(minSpawnTime, maxSpawnTime); backgroundCollider = background.GetComponent<Collider2D>(); } void Update() { if (Time.time >= nextSpawnTime) { SpawnSphere(); nextSpawnTime = Time.time + Random.Range(minSpawnTime, maxSpawnTime); } } void SpawnSphere() { Vector2 min = backgroundCollider.bounds.min; Vector2 max = backgroundCollider.bounds.max; Vector3 randomPosition = new Vector3(Random.Range(min.x, max.x), Random.Range(min.y, max.y), 0f); int prefabIndex = Random.Range(0, spherePrefabs.Length); Instantiate(spherePrefabs[prefabIndex], randomPosition, Quaternion.identity); } }
복잡하게 확률을 정하느니 그냥 모두 랜덤으로 둔게 가장 밸런스 있고 적절하게 생성되는것 같아보인다
아 그리고 생성 시간은 7~12초로 다시 조절하였다.
'Galaxy Ball > 1. 멀티플레이 - 대전모드' 카테고리의 다른 글
(20) 아이템 #사용구현 (0) 2024.04.08 (19) 아이템 #UI (1) 2024.04.04 (17) inGame Scene #Pause (0) 2024.04.03 (16) 아이템 디자인 (1) 2024.04.03 (15) Setting Scene # 자잘한 보완 & Credit Scene (0) 2024.04.02