본문 바로가기

Unity 공부/Unity_2D

[Day 4] 소환 레벨 적용

[ 소환 레벨 적용 ] --> 시간에 따라 점점 강해지는 몬스터 소환

  • 기존의 GameManager 스크립트에 코드 추가 
    ㅡ아래는 완성된 코드ㅡ
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager instance;

    public float gameTime; // 게임 시간을 저장 할 gameTime 변수 생성&초기화
    public float maxGameTime = 2 * 10f; // maxGameTime 변수 생성&초기화

    public PoolManager pool;
    public Player player;

    private void Awake()
    {
        instance = this;
    }

    void Update()
    {
        gameTime += Time.deltaTime;

        if (gameTime > maxGameTime) // gameTime과 maxGameTime을 비교
        {
            gameTime = maxGameTime; // 최대를 넘어갈 수 없음
        }
    }

}
  • 기존의 Spawner 스크립트에 코드 추가
    ㅡ아래는 완성된 코드ㅡ
using System.Collections;
using System.Collections.Generic;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public Transform[] spawnPoint;
    public SpawnData[] spawnData; 

    int level;
    float timer;

    private void Awake()
    {
        spawnPoint = GetComponentsInChildren<Transform>();
    }

    void Update()
    {
        timer += Time.deltaTime;
        level = Mathf.FloorToInt(GameManager.instance.gameTime / 10f); // 시간에 따라 증가하는 level

        if (timer > (level == 0 ? 0.5f : 0.2f)) // 레벨에 따라 스폰시간이 달라짐
        {
            timer = 0;
            Spawn();
        }
    }

    void Spawn()
    {
        GameObject enemy = GameManager.instance.pool.Get(level); // 레벨에 따라 몬스터가 선택됨
        enemy.transform.position = spawnPoint[Random.Range(1, spawnPoint.Length)].position;
    }
}

[System.Serializable] // 개체를 저장&전송하기 위해 직렬화
public class SpawnData // 몬스터가 소환 될 때 데이터
{
    public float spawnTime; // 몬스터 스폰 시간
    public int spriteType; // 몬스터 스프라이트 타입
    public int hp; // 몬스터 체력
    public float speed; // 몬스터 속도
}
  • Prefabs의 몬스터를 1마리만 남기고 삭제
  • 기존의 Enemy 스크립트에 코드 추가
    ㅡ아래는 완성된 코드ㅡ
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    public float speed;
    public float hp;
    public float maxHp;
    public RuntimeAnimatorController[] animCon; 
    // 애니메이터 컨트롤러 변수 생성, inspector에 애니메이션 컨트롤러 드래그&드랍으로 초기화
    public Rigidbody2D target;

    bool isLive;

    Rigidbody2D rigid;
    Animator anim;
    SpriteRenderer spriter;

    void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
        spriter = GetComponent<SpriteRenderer>();
    }

    private void FixedUpdate(){

        if (!isLive){
            return;
        }

        Vector2 dirVec = target.position - rigid.position;
        Vector2 nextVec = dirVec.normalized * speed * Time.fixedDeltaTime;
        rigid.MovePosition(rigid.position + nextVec);
        rigid.velocity = Vector2.zero;
    }

    private void LateUpdate()
    {
        if (!isLive){
            return;
        }
        spriter.flipX = target.position.x < rigid.position.x;
    }

    private void OnEnable()
    {
        target = GameManager.instance.player.GetComponent<Rigidbody2D>(); // 필드에 있는동안, 플레이어를 타겟으로 정함
        isLive = true; 
        hp = maxHp; // 체력을 가득 채움
    }

    public void Init(SpawnData data)
    {
        anim.runtimeAnimatorController = animCon[data.spriteType]; // 애니메이션 컨트롤러를 받은 sprite로 바꿈
        speed = data.speed; // speed 초기화
        maxHp = data.hp; // maxHp 초기화
        hp = data.hp; // hp 초기화
    }
}
  • PoolManager 빈 데이터 삭제
  • 기존의 Spawner 스크립트에 코드 추가
    ㅡ아래는 완성된 코드ㅡ
using System.Collections;
using System.Collections.Generic;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;

public class Spawner : MonoBehaviour
{
    public Transform[] spawnPoint;
    public SpawnData[] spawnData; 

    int level;
    float timer;

    private void Awake()
    {
        spawnPoint = GetComponentsInChildren<Transform>();
    }

    void Update()
    {
        timer += Time.deltaTime;
        level = Mathf.Min(Mathf.FloorToInt(GameManager.instance.gameTime / 10f), spawnData.Length - 1);
        // 인덱스 에러는 레벨 변수 계산 시 Min 함수를 사용하여 막음
        
        if (timer > spawnData[level].spawnTime) // 소환 시간 조건을 소환데이터로 변경
        {
            timer = 0;
            Spawn();
        }
    }

    void Spawn()
    {
        GameObject enemy = GameManager.instance.pool.Get(0); // PoolManager에 데이터가 하나밖에 없기 때문에 Get(0)
        enemy.transform.position = spawnPoint[Random.Range(1, spawnPoint.Length)].position;
        enemy.GetComponent<Enemy>().Init(spawnData[level]); // 새롭게 작성한 함수 호출 & 소환데이터 인자값 전달
    }
}

[System.Serializable]
public class SpawnData
{
    public float spawnTime;
    public int spriteType;
    public int hp;
    public float speed;
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

★Slow and Steady★