우리는 유투브 강의를 보고 따라서 Vampire Survivor라이크류 게임을 만들어보았다. 이제 우리만의 스테이지와 몹을 만들고 이를 통해 데이터를 모아서 AI모델을 통해 유저의 생존시간과 시도 횟수를 예측해보기로 하였다.
 
1. 우리만의 스테이지
기존의 강의에서는 스테이지가 하나밖에 없어서 여러 스테이지를 깨고 그 다음스테이지를 예측해야하는 우리에게는 여러가지 스테이지가 필요했다. 그렇게 여러 스테이지를 생성하는 법을 공부하였는데 이때 사용하는 것이 맵을 게임오브젝트로 만들어 두고 GameManager에서 Stages라는 Gameobject 배열로 만들고 이곳에 여러 스테이지를 저장한 뒤 기존의 스테이지가 끝나면 스테이지맵의 게임오브젝트 Active를 false로 바꿔주고 다음  스테이지맵의 게임 오브젝트 Active를 true로 만들어 주면 된다. 
Stages[stageIndex].SetActive(false);
stageIndex++;
Stages[stageIndex].SetActive(true);
 
이러한 코드를 GameManager 코드에 NextStage() 메서드로 구현해두었다.  또한 Player의 위치를 다시 원점으로 돌려서 스테이지를 플레이할 수 있게 
player.transform.position = Vector3.zero;
 
이 코드도 함께 넣어 구현해 주었다. 

Backyard Top-Down Tileset(FREE)
https://assetstore.unity.com/packages/2d/environments/backyard-top-down-tileset-53854

 

Backyard Top-Down Tileset | 2D 주변환경 | Unity Asset Store

Elevate your workflow with the Backyard Top-Down Tileset asset from Kittens and Elves at Work. Find this & more 주변환경 on the Unity Asset Store.

assetstore.unity.com

https://assetstore.unity.com/packages/2d/characters/top-down-2d-rpg-assets-pack-188718

 

Top-Down 2D RPG Assets Pack | 2D 캐릭터 | Unity Asset Store

Elevate your workflow with the Top-Down 2D RPG Assets Pack asset from Goldmetal. Find this & more 캐릭터 on the Unity Asset Store.

assetstore.unity.com

 
 
골드메탈님의 강의에서 무한맵처럼 보이게 맵을 이동하는 것을 코드로 구현했었는데 이 코드는 그대로 사용하고 각 스테이지별 기존 맵과 동일한 크기의 타일맵을 생성하여서 스테이지가 달라지는 것을 알 수 있도록 구현하였다. 
타일맵을 생성하는데에는 위의 두 Asset을 활용하여 만들었다.
 
private void OnTriggerExit2D(Collider2D collision)
{
 
    switch (transform.tag)
    {
        case "Ground":
            float diffX = playerPos.x - myPos.x;
            float diffY = playerPos.y - myPos.y;
            float dirX = diffX < 0 ? -1 : 1;
            float dirY = diffY < 0 ? -1 : 1;
            diffX=Mathf.Abs(diffX);
            diffY=Mathf.Abs(diffY);
            if (diffX > diffY)
            {
                transform.Translate(Vector3.right * dirX * 40);
            }
            else if (diffX < diffY)
            {
                transform.Translate(Vector3.up * dirY * 40);
            }
            break;
    }

}

만약 플레이어 밑에 있는 Area 오브젝트가 Ground의 끝을 만났을때 맵을 그 길이만큼 왼쪽이나 오른쪽 또는 위 아래로 움직여주는 코드이다. 
 
2.우리만의 몹 만들기
기존의 강의에서는 몹이 2개만 생성가능했기 때문에 우리는 총 4개의 스테이지에 맞는 여러 몬스터를 더 넣고자 했다. 

https://assetstore.unity.com/packages/2d/characters/2d-monster-undead-spum-premium-addon-pack-200884

 

2D Monster Undead - SPUM Premium Addon Pack | 2D 캐릭터 | Unity Asset Store

Elevate your workflow with the 2D Monster Undead - SPUM Premium Addon Pack asset from soonsoon. Find this & more 캐릭터 on the Unity Asset Store.

assetstore.unity.com

Undead Survivor에 맞게 좀비 Asset을 찾아서 넣어주었다. 가격은 $9.99정도이다. 이 Asset을 처음 받았을 때 기존에 강의에서 활용하던 몬스터 Asset과 구조가 많이 달라서 사용법을 찾는데 오래 걸렸다. 기존에 Asset은 제일 상위 오브젝트에 Animator을 붙이고 이를 통해 Animation이 작동했었는데 이 Asset은 하위에 UnitRoot가 있고 이 아래에 몬스터의 몸을 이루는 부분들이 있어서 이 UnitRoot를 통해 해당 몬스터의 Animation이 작동하는 것을 알았다. 그래서 이 UnitRoot에 기존에 가지고 있던 Animator에 Hit라는 Trigger과 Dead라는 Bool 값을 넣어서 만약 유저에게 데미지를 입었을때의 Animation과 몬스터의 체력이상의 공격을 당했을 때 Dead에 해당하는 Animation이 작동하도록 했다.
void OnTriggerEnter2D(Collider2D collision)
{
    if (!collision.CompareTag("Bullet"))
        return;
    health -= collision.GetComponent<Bullet>().damage;
    StartCoroutine(KnockBack_1());
    if (health > 0)
    {
        anim.SetTrigger("Hit");
        AudioManager.instance.PlaySfx(AudioManager.Sfx.Hit);
    }
    else
    {
        isLive = false;
        coll.enabled = false;
        rigid.simulated = false;
        anim.SetBool("Dead", true);
        StartCoroutine(Dead());
        GameManager.instance.kill++;
        GameManager.instance.GetExp();

        if (GameManager.instance.isLive)
            AudioManager.instance.PlaySfx(AudioManager.Sfx.Dead);
    }
}
 
여기서 Bullet은 유저의 무기이다. 

 
 
Enemy에 들어갈 Animator도 수정하였다. 또한 Spawner에 spawn 메서드를 통해 몬스터가 생성되는데 Stage에 따라 시작 몬스터와 몇초마다 다른 몬스터가 생성되는지를 코드로 구현하여 스테이지마다 몬스터가 바뀔수 있도록 구현하였다.
 
 void spawn()                        //0번째부터시작 1,2번째는 총알이라 놔두기 
 {
     GameObject enemy;
     if (GameManager.instance.stageIndex == 0)           //1스테이지는 레벨에 따라
     {
         if (level == 0)
         {
             enemy = GameManager.instance.pool.Get(level);    //SpawnData 인스펙터창
         }
         else
         {
             enemy = GameManager.instance.pool.Get(level + 2);    //SpawnData 인스펙터창
         }
         enemy.transform.position = spawnPoint[Random.Range(1, spawnPoint.Length)].position;
         enemy.GetComponent<Enemy_new>().Init(spawnData[level]);
     }
     else
     {                                                           //2스테이지부터는 레벨+스테이지 인덱스번째의 몹부터 소환
         if (level == 0)
         {
             enemy = GameManager.instance.pool.Get(level+2+GameManager.instance.stageIndex);    //SpawnData 인스펙터창
         }
         else
         {
             enemy = GameManager.instance.pool.Get(level +2+ GameManager.instance.stageIndex-1);    //SpawnData 인스펙터창
             if((level + 2 + GameManager.instance.stageIndex) == GameManager.instance.pool.prefabs.Length)
             {
                 enemy = GameManager.instance.pool.Get(GameManager.instance.pool.prefabs.Length-1);    //SpawnData 인스펙터창
             }
         }
         enemy.transform.position = spawnPoint[Random.Range(1, spawnPoint.Length)].position;
         enemy.GetComponent<Enemy_new>().Init(spawnData[level]);
     }
 }
 
또한 몬스터마다 체력, 스폰시간, 체력, 속도등을 정하여 입력해 주었다. 

 

+ Recent posts