ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (9) 적 특수 유닛 제작 #2
    Galaxy Ball/2. 싱글플레이 - 스토리모드 2024. 5. 22. 17:37

    이제 2개만 더 제작하면 마무리된다

    이번 특수 유닛의 경우에는 일반 유닛과 전부 동일한 스펙이지만 다른게 한가지 있다면

    기본 총알 대신 아이템을 발사한다는것이다

     

     

    이 유닛 같은 경우는 몸체를 담당하는 Center가 아닌 발사를 담당하는 Muzzle을 수정해야한다

     

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Enemy1Fire : MonoBehaviour
    {
        public GameObject[] enemyBulletPrefabs; // 여러 총알 프리팹을 담는 배열
        public float MinPower;
        public float MaxPower;
    
        public void SpawnBullet()
        {
                // 배열에서 무작위로 총알 프리팹 선택
                GameObject selectedBulletPrefab = enemyBulletPrefabs[Random.Range(0, enemyBulletPrefabs.Length)];
                GameObject bullet = Instantiate(selectedBulletPrefab, transform.position, Quaternion.identity);
                Vector2 shotDirection = -transform.up;
                float shotPower = Random.Range(MinPower, MaxPower);
                Rigidbody2D bulletRigidbody = bullet.GetComponent<Rigidbody2D>();
                bulletRigidbody.velocity = shotDirection * shotPower;
        }
    }

     

     

    당연히 코드에서 public으로 입력받을수 있게 변경해주었고

    이제부터 enemyBulletPrefabs는 하나만 입력받는것이 아닌

    배열로 직접 길이를 조절하여 그안에 총알 프리팹을 넣도록 해주겠다

     

     

    이 유닛의 경우는 모든 아이템 프리팹을 넣어주었고, 이제 이 시스템을 응용하여 기본 유닛이 아이템을

    발사하도록 할수도 있겠다

     

     

     

    이제 아이템이 랜덤으로 발사되는것을 확인할 수 있다

     

    이름 : SEnemy3

    최소/최대 내구도 : 3/5

    최소/최대 발사시간 : 5/9

    최소/최대 발사속도 : 8/12

    사용 총알 : (7가지 아이템)

    (특징 : 아이템 발사)

     

    마지막으로 만들 특수 유닛은 생김새만 봐도 알수 있듯이 유닛들 중 유일하게 공격 기능이 없다

    대신 본인의 반경원 안에 들어가있는 유닛들의 체력을 치유해줄수 있는 서포터형 유닛으로 보면 되겠다

     

    이 유닛 같은 경우 기존 유닛들과 역할 자체부터가 아예 다르기에 새로운 스크립트를 작성해주어야 한다

     

     

    using UnityEngine;
    using System.Collections;
    
    public class HEnemyCenter : MonoBehaviour
    {
        public float radius = 5f;
        public float interval = 10f;
    
        void Start()
        {
            // Coroutine을 사용하여 주기적으로 함수를 호출
            StartCoroutine(IncrementRandomNumberRoutine());
        }
    
        IEnumerator IncrementRandomNumberRoutine()
        {
            while (true)
            {
                // 10초 대기
                yield return new WaitForSeconds(interval);
    
                // 반경 안에 있는 모든 오브젝트를 가져옴
                Collider2D[] hitColliders = Physics2D.OverlapCircleAll(transform.position, radius);
    
                foreach (var hitCollider in hitColliders)
                {
                    // 오브젝트의 태그가 "Enemy"인지 확인
                    if (hitCollider.CompareTag("Enemy"))
                    {
                        // "Enemy1Center" 컴포넌트를 가져옴
                        Enemy1center enemyCenter = hitCollider.GetComponent<Enemy1center>();
    
                        if (enemyCenter != null)
                        {
                            // randomNumber를 증가시키되 초기값을 초과하지 않도록 함
                            if (enemyCenter.randomNumber < enemyCenter.initialRandomNumber)
                            {
                                enemyCenter.randomNumber++;
    
                                // isShowHP가 true일 경우 텍스트 업데이트
                                if (enemyCenter.isShowHP)
                                {
                                    enemyCenter.textMesh.text = enemyCenter.randomNumber.ToString();
                                }
    
                                // 디버깅 메시지: randomNumber 증가
                                Debug.Log($"Increased randomNumber for {hitCollider.name} to {enemyCenter.randomNumber}");
                            }
                        }
                    }
                }
            }
        }
    
        // 디버그를 위한 함수 (반경을 시각적으로 보여줌)
        void OnDrawGizmos()
        {
            Gizmos.color = Color.red;
            Gizmos.DrawWireSphere(transform.position, radius);
        }
    }

     

    우선 맨밑줄에 보면 반경을 가상으로 만들어준뒤 IncrementRandomNumberRoutine이라는 코루틴을 돌려

    지정한 시간마다 한번씩 반경안에 있는 모든 오브젝트들의 태그를 불러와 "Enemy"인 태그가 있는 오브젝트를 구한다

     

    그리고 코루틴이 한번 돌때마다 randomNumber 즉, 내구도를 1씩 올려주는것이다

     

    여기서 밸런스를 위해 한가지 더 추가한 기능이 있다면 아무리 체력을 회복 시켜준다 하더라도

    처음 내가 지정해준 randomNumber 초깃값을 넘지 못하게 막아주는 것이다

     

    initialnumber 변수를 사용했고 Enemy1Center 스크립트에 해당 변수를 추가했다

     

    이제 모든 적 프리팹에 태그를 "Enemy"로 달아주기만 하면 될줄 알았는데 아무런 변화도 일어나질 않는다...

     

    디버그를 찍어가며 문제를 뒤져보니 

      Collider2D[] hitColliders = Physics2D.OverlapCircleAll(transform.position, radius);

    콜라이더가 붙어있는 오브젝트만 정보를 가져오겠다는 것이었다

     

    즉 왼쪽이 아닌 오른쪽처럼 실질적인 체력을 띄워주고 박스 콜라이더가 달린 Center의 태그를 "Enemy"로 해줘야한다는것

     

     

    하지만 굳이 Center에 "Enemy" 태그를 넣어 후에 어떻게 헷갈리게 할지 모르니 조건태그를 "EnemyCenter"로 하겠다

     

     

     

    이제 힐이 잘 되는것을 확인할 수 있다

    지금은 예시용으로 힐이 굉장히 빠른 속도로 이루어지지만 실전에서는 이렇게 빠르지 않을것이다

     

    이제 기능구현은 끝났으니 유닛 디자인과 밸런스 조절을 해보도록 하자

     

    우선 가장 먼저 인게임 안에서도 반경 라인을 보이게 만들고 싶어 코드를 추가했다

    using UnityEngine;
    using System.Collections;
    
    [RequireComponent(typeof(LineRenderer))]
    public class HEnemyCenter : MonoBehaviour
    {
        public float radius;
        public float interval;
        public int segments = 50; // 원을 그릴 때 사용할 세그먼트 수
        private LineRenderer lineRenderer;
    
        void Start()
        {
            // LineRenderer 컴포넌트를 초기화
            lineRenderer = GetComponent<LineRenderer>();
            lineRenderer.positionCount = segments + 1;
            lineRenderer.useWorldSpace = false;
            lineRenderer.loop = true;
            lineRenderer.startWidth = 0.1f;
            lineRenderer.endWidth = 0.1f;
            lineRenderer.startColor = Color.red;
            lineRenderer.endColor = Color.red;
    
            // 반경을 그림
            CreateCircle();
    
            // Coroutine을 사용하여 주기적으로 함수를 호출
            StartCoroutine(IncrementRandomNumberRoutine());
        }
    
        void CreateCircle()
        {
            float angle = 0f;
            for (int i = 0; i <= segments; i++)
            {
                float x = Mathf.Sin(Mathf.Deg2Rad * angle) * radius;
                float y = Mathf.Cos(Mathf.Deg2Rad * angle) * radius;
    
                lineRenderer.SetPosition(i, new Vector3(x, y, 0));
    
                angle += (360f / segments);
            }
        }
    
        IEnumerator IncrementRandomNumberRoutine()
        {
            while (true)
            {
                // interval 만큼 대기
                yield return new WaitForSeconds(interval);
    
                // 반경 안에 있는 모든 오브젝트를 가져옴
                Collider2D[] hitColliders = Physics2D.OverlapCircleAll(transform.position, radius);
    
                foreach (var hitCollider in hitColliders)
                {
                    if (hitCollider.CompareTag("EnemyCenter"))
                    {
                        Enemy1center enemyCenter = hitCollider.GetComponent<Enemy1center>();
    
                        if (enemyCenter != null)
                        {
                            if (enemyCenter.randomNumber < enemyCenter.initialRandomNumber)
                            {
                                enemyCenter.randomNumber++;
    
                                if (enemyCenter.isShowHP)
                                {
                                    enemyCenter.textMesh.text = enemyCenter.randomNumber.ToString();
                                }
    
                                // 디버깅 메시지: randomNumber 증가
                                Debug.Log($"Increased randomNumber for {hitCollider.name} to {enemyCenter.randomNumber}");
                            }
                        }
                    }
                }
            }
        }
    }

     

    LineRenderer를 이용하여 radius의 값에 따라 반경의 원을 표현하려 했으나 

     

    이런식으로 뜬다...

     

    첫번째 문제 : 우선 그래픽 배울때 알게된건데 빨간색이 아닌 분홍으로 뜬다는것은

    애초에 색 인식 자체를 못한다는 의미이다

     

    두번째 문제 : 분명 백그라운드의 레이어는 0이고, 반경 레이어는 3인데 백그라운드 밑에 깔린다는것이다

     

    이건 도저히 감이 안잡혀 선생님께 물어봐 답을 얻었다

     

    첫번째 색 인식문제는 렌더러안에 Material 을 넣어주면 되고

    두번째 레이어 문제는 z축을 아주 살짝 내려주면 된다

     

     이제 반경도 나오면서 힐 역할도 잘 수행하는것을 확인할 수 있다

     

    이제 디자인만 바꿔주면 완성이다

     

    디자인도 끝났고 내구도 시스템도 추가하였다

     

    원래는 다른 유닛들과 마찬가지로 내구도를 랜덤으로 줄까 생각하다가

    가운데 있는 십자가 아이콘에 겹치기도 하고, 딱히 전투 유닛도 아니기에 내구도는 닿는순간 파괴되는것으로 하겠다

     

    이름 : HEnemy1

    치유 반경 : 7

    치유 속도 : 10

    특징 : 전투 불가, 서포터 유닛

     

    그리고 갑자기 떠오른게 하나 있어 그것까지 더 추가하겠다

     

     

    이름 : HEnemy2

    치유 반경 : 25

    치유 속도 : 10

    특징 : 전투 불가, 서포터 유닛 + 그라운드 내 모든 유닛 치유

     

    디자인과 치유 반경만 변경해 새로운 컨셉의 유닛으로 만들어보았다

     

     

Designed by Tistory.