[골드메탈 BE4] 따라하기 8

배근철·2022년 8월 5일
0

GoldMetal BE4

목록 보기
8/11
post-thumbnail

✍ 오브젝트 풀링으로 최적화하기

  • Instantiate와 Destroy는 생성, 삭제하면서 조각난 메모리가 계속해서 쌓이는데,
    게임 도중 GC가 실행되면 렉이 심하게 걸린다.
    • GC(Garbage Collector) : 쌓인 조각난 메모리를 비우는 기술
  • 게임 도중 GC가 실행되면서 렉이 심하게 걸릴 수 있기때문에 최적화를 위해 오브젝트 풀링 사용

오브젝트 풀링

  • 미리 생성해둔 풀에서 활성화/비활성화로 사용
  • 게임상 보이는건 이전과 같지만, 내부 로직이 다르다.

풀 생성

  • ObjectManager 스크립트와 오브젝트를 생성
  • 많은 양을 담기 때문에 public이 아닌 private으로 생성
    (public으로 생성 시 인스펙터 창에 굉장히 많은 배열이 등장)
  • 프리펩을 생성하여 저장할 배열 변수를 생성함.
  • 한번에 등장가능한 개수를 고려해서 배열 길이를 할당
  • Instantiate를 사용하려면 프리펩이 필요하므로 프리펩 변수를 꼭 생성해준다.
  • Instantiate를 사용해 생성한 인스턴스를 배열에 저장해 준다.
    • 프리펩 이름만 써서 생성하고 저장, 위치와 회전은 입력하지 않음.
    • 생성하면 좌표0,0,0에 모두 생성되므로 모두 비활성화
  • 보통 첫 로딩시간에 장변 배치와 오브젝트 풀 생성을 진행함.
 void Generate()
    {
        // #. Enemy

        for(int i=0; i<enemyL.Length; i++)
        {
            enemyL[i] = Instantiate(enemyL_Prefab);
            enemyL[i].SetActive(false);
        }

        for (int i = 0; i < enemyM.Length; i++)
        {
            enemyM[i] = Instantiate(enemyM_Prefab);
            enemyM[i].SetActive(false);
        }

        for (int i = 0; i < enemyS.Length; i++)
        {
            enemyS[i] = Instantiate(enemyS_Prefab);
            enemyS[i].SetActive(false);
        }


        // #. Item

        for(int i=0; i<itemBoom.Length; i++)
        {
            itemBoom[i] = Instantiate(itemBoom_Prefab);
            itemBoom[i].SetActive(false);
        }

        for (int i = 0; i < itemCoin.Length; i++)
        {
            itemCoin[i] = Instantiate(itemCoin_Prefab);
            itemCoin[i].SetActive(false);
        }

        for (int i = 0; i < itemPower.Length; i++)
        {
            itemPower[i] = Instantiate(itemPower_Prefab);
            itemPower[i].SetActive(false);
        }


        // #. Bullets

        for(int i=0; i<playerBulletA.Length; i++)
        {
            playerBulletA[i] = Instantiate(playerBulletA_Prefab);
            playerBulletA[i].SetActive(false);
        }

        for (int i = 0; i < playerBulletB.Length; i++)
        {
            playerBulletB[i] = Instantiate(playerBulletB_Prefab);
            playerBulletB[i].SetActive(false);
        }

        for (int i = 0; i < enemyBulletA.Length; i++)
        {
            enemyBulletA[i] = Instantiate(enemyBulletA_Prefab);
            enemyBulletA[i].SetActive(false);
        }

        for (int i = 0; i < enemyBulletB.Length; i++)
        {
            enemyBulletB[i] = Instantiate(enemyBulletB_Prefab);
            enemyBulletB[i].SetActive(false);
        }

    }

풀 활용

  • 오브젝트 풀에 접근할 수 있는 함수를 생성해서, 게임오브젝트를 반환시켜준다.
  • activeSelf -> 활성화되었으면 true, 비활성화되었으면 false 반환
   public GameObject MakeObj(string type)
    {
        switch(type)
        {
            case "EnemyL":
                targetPool = enemyL;
                break;

            case "EnemyM":
                targetPool = enemyM;
                break;

            case "EnemyS":
                targetPool = enemyS;
                break;

            case "ItemBoom":
                targetPool = itemBoom;
                break;

            case "ItemCoin":
                targetPool = itemCoin;
                break;

            case "ItemPower":
                targetPool = itemPower;
                break;

            case "PlayerBulletA":
                targetPool = playerBulletA;
                break;

            case "PlayerBulletB":
                targetPool = playerBulletB;
                break;

            case "EnemyBulletA":
                targetPool = enemyBulletA;
                break;

            case "EnemyBulletB":
                targetPool = enemyBulletB;
                break;

        }

        for(int i=0; i<targetPool.Length; i++)
        {
            if(!targetPool[i].activeSelf)
            {
                targetPool[i].SetActive(true);
                return targetPool[i];
            }
        }
        return null;
    }
  • 반환값이 없으면 함수에서 에러가 나므로 모든 상황에서 반환을 꼭 해줘야함.
  • 기존의 Instantiate들을 모두 오브젝트 풀링으로 교체
  • 위치와 각도는 인스턴스 변수에서 적용하고 Destroy는 SetActive(false)로 바꾼다.![]

로직정리

  • 좌,우에서 나오는 Enemy들이 위에서 생성될때도 옆을 보고 생성됨
  • Quaternion.identity -> 기본 회전값 = 0;
    • transform.rotation = Quaternion.identity;을 이용해서 회전값 초기화
  • 아이템 생성 시 아래로 떨어지지 않는 버그
    • OnEnable() 함수에서 구현
      private void OnEnable()
       {
           rigid.velocity = Vector2.down * 1.5f;
       }
  • 히트가 안되는 버그
    • 이미 한번 잡으면 HP가 0이되어서 Hit가 되질 않는다.
    • OnEnable에서 hp를 다시 풀로 채워준다.
    private void OnEnable()
      {
          switch (enemyName)
          {
              case "L":
                  health = 15;
                  break;
              case "M":
                  health = 5;
                  break;
              case "S":
                  health = 3;
                  break;
          }
      }
  • OnEnable() : 컴포넌트가 활성화 될 때 호출되는 생명주기 함수

Find함수 제거

  • 오브젝트를 직접 찾는 Find 계열 함수는 성능 부하를 유발시킨다.
  • 지정한 오브젝트 풀을 가져오는 함수를 추가해서 Find 계열 함수를 오브젝트 풀링으로 교체
   public GameObject[] GetPool(string type)
    {
        switch (type)
        {
            case "EnemyL":
                targetPool = enemyL;
                break;

            case "EnemyM":
                targetPool = enemyM;
                break;

            case "EnemyS":
                targetPool = enemyS;
                break;

            case "EnemyBulletA":
                targetPool = enemyBulletA;
                break;

            case "EnemyBulletB":
                targetPool = enemyBulletB;
                break;

        }

        return targetPool;
    }
  • 풀 비활성화

  • 풀 활성화

  • 게임진행


바뀐 코드

1. Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public bool isTouchTop;
    public bool isTouchBottom;
    public bool isTouchLeft;
    public bool isTouchRight;

    public int score;
    public int health;
    public float speed;
    public int boom;
    public int maxBoom;
    public int power;
    public int maxPower;
    public float curShotDelay;
    public float maxShotDelay;
    public bool isHit;
    public bool isBoom;

    public ObjectManager objectManager;
    public GameObject boomEffect;
    public GameManager gameManager;
   /* public GameObject BulletA;
    public GameObject BulletB;
*/
    Animator anim;

    private void Awake()
    {
        anim = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        Move();
        Fire();
        Reload();
        Boom();
    }


    void Boom()
    {
        if (!Input.GetButton("Fire2"))
            return;

        if (isBoom)
            return;

        if (boom == 0)
            return;

        boom--;
        isBoom = true;
        gameManager.UpdateBoom(boom);

        //#1. Effect visible
        boomEffect.SetActive(true);
        Invoke("OffBoomEffect", 3f);
        //#2. Remove Enemy
        GameObject[] enemiesL = objectManager.GetPool("EnemyL");
        GameObject[] enemiesM = objectManager.GetPool("EnemyM");
        GameObject[] enemiesS = objectManager.GetPool("EnemyS");

        for (int i = 0; i < enemiesL.Length; i++)
        {
            if (enemiesL[i].activeSelf)
            {
                Enemy enemyLogic = enemiesL[i].GetComponent<Enemy>();
                enemyLogic.onDamaged(1000);
            }
        }

        for (int i = 0; i < enemiesM.Length; i++)
        {
            if (enemiesM[i].activeSelf)
            {
                Enemy enemyLogic = enemiesM[i].GetComponent<Enemy>();
                enemyLogic.onDamaged(1000);
            }
        }

        for (int i = 0; i < enemiesS.Length; i++)
        {
            if (enemiesS[i].activeSelf)
            {
                Enemy enemyLogic = enemiesS[i].GetComponent<Enemy>();
                enemyLogic.onDamaged(1000);
            }
        }

        //#3. Remove Enemy Bullet
        GameObject[] bulletsA = objectManager.GetPool("EnemyBulletA");
        GameObject[] bulletsB = objectManager.GetPool("EnemyBulletB");
        for (int i = 0; i < bulletsA.Length; i++)
            if(bulletsA[i].activeSelf)
                bulletsA[i].SetActive(false);

        for (int i = 0; i < bulletsB.Length; i++)
            if (bulletsB[i].activeSelf)
                bulletsB[i].SetActive(false);



    }
    void Reload()
    {
        curShotDelay += Time.deltaTime;
    }

    void Fire()
    {
        if (!Input.GetButton("Fire1")) // Fire1은 마우스좌클릭
            return;

        if (curShotDelay < maxShotDelay)
            return;


        switch(power)
        {
            case 1:
                // Power 1
                GameObject Bullet = objectManager.MakeObj("PlayerBulletA");
                Bullet.transform.position = transform.position;
                Rigidbody2D rigid = Bullet.GetComponent<Rigidbody2D>();
                rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;
            case 2:
                // Power 2
                GameObject BulletR = objectManager.MakeObj("PlayerBulletA");
                GameObject BulletL = objectManager.MakeObj("PlayerBulletA");
                BulletR.transform.position = transform.position + Vector3.right * 0.1f;
                BulletR.transform.position = transform.position + Vector3.left * 0.1f;
                Rigidbody2D rigidR = BulletR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidL = BulletL.GetComponent<Rigidbody2D>();
                rigidR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;
            case 3:
                // Power 3
                GameObject BulletRR = objectManager.MakeObj("PlayerBulletA");
                GameObject BulletCC = objectManager.MakeObj("PlayerBulletB");
                GameObject BulletLL = objectManager.MakeObj("PlayerBulletA");
                BulletRR.transform.position = transform.position + Vector3.right * 0.35f;
                BulletCC.transform.position = transform.position;
                BulletLL.transform.position = transform.position + Vector3.left * 0.35f;
                Rigidbody2D rigidRR = BulletRR.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidCC = BulletCC.GetComponent<Rigidbody2D>();
                Rigidbody2D rigidLL = BulletLL.GetComponent<Rigidbody2D>();
                rigidRR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidCC.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                rigidLL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;

        }
        

        curShotDelay = 0;
    }

    void Move()
    {
        float h = Input.GetAxisRaw("Horizontal");
        if ((isTouchRight && h == 1) || (isTouchLeft && h == -1))
            h = 0;
        float v = Input.GetAxisRaw("Vertical");

        if ((isTouchTop && v == 1) || (isTouchBottom && v == -1))
            v = 0;

        Vector3 curPos = transform.position;
        Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;

        transform.position = curPos + nextPos;

        // Animation

        if (Input.GetButtonUp("Horizontal") || Input.GetButtonDown("Horizontal"))
        {
            anim.SetInteger("Input", (int)h);

        }
    }

    public void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Border")
        {
            switch(collision.gameObject.name)
            {
                case "Top":
                    isTouchTop = true;
                    break;
                case "Bottom":
                    isTouchBottom = true;
                    break;
                case "Left":
                    isTouchLeft = true;
                    break;
                case "Right":
                    isTouchRight = true;
                    break;
                   
            }
        }

        else if(collision.gameObject.tag == "Enemy" || (collision.gameObject.tag == "EnemyBullet"))
        {
            if (isHit)
                return;

            isHit = true;
            health--;
            gameManager.UpdateLife(health);
            if (health == 0)
                gameManager.GameOver();
            else
                gameManager.RespawnPlayer();

            gameObject.SetActive(false);
            collision.gameObject.SetActive(false);
        }

        else if(collision.gameObject.tag == "Item")
        {
            Item item = collision.gameObject.GetComponent<Item>();
            string itemtype = item.type;

            switch(itemtype)
            {
                case "Coin":
                    score += 1000;
                    break;
                case "Power":
                    if (power == maxPower)
                        score += 500;
                    else 
                        power++;
                    break;
                case "Boom":
                    if (boom == maxBoom)
                        score += 500;
                    else
                    {
                        boom++;
                        gameManager.UpdateBoom(boom);
                    }
                    break;


            }
            collision.gameObject.SetActive(false);
        }
    }

    void OffBoomEffect()
    {
        boomEffect.SetActive(false);
        isBoom = false;
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Border")
        {
            switch (collision.gameObject.name)
            {
                case "Top":
                    isTouchTop = false;
                    break;
                case "Bottom":
                    isTouchBottom = false;
                    break;
                case "Left":
                    isTouchLeft = false;
                    break;
                case "Right":
                    isTouchRight = false;
                    break;

            }
        }
    }
}

2. ObjectManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectManager : MonoBehaviour
{
    GameObject[] enemyL;
    GameObject[] enemyM;
    GameObject[] enemyS;
    GameObject[] itemBoom;
    GameObject[] itemCoin;
    GameObject[] itemPower;
    GameObject[] enemyBulletA;
    GameObject[] enemyBulletB;
    GameObject[] playerBulletA;
    GameObject[] playerBulletB;
    GameObject[] targetPool;

    // #. Prefabs

    public GameObject enemyL_Prefab;
    public GameObject enemyM_Prefab;
    public GameObject enemyS_Prefab;
    public GameObject itemBoom_Prefab;
    public GameObject itemCoin_Prefab;
    public GameObject itemPower_Prefab;
    public GameObject enemyBulletA_Prefab;
    public GameObject enemyBulletB_Prefab;
    public GameObject playerBulletA_Prefab;
    public GameObject playerBulletB_Prefab;


    void Awake()
    {
        enemyL = new GameObject[10];
        enemyM = new GameObject[10];
        enemyS = new GameObject[10];
        
        itemCoin = new GameObject[20];
        itemBoom = new GameObject[20];
        itemPower = new GameObject[20];

        playerBulletA = new GameObject[100];
        playerBulletB = new GameObject[100];
        enemyBulletA = new GameObject[100];
        enemyBulletB = new GameObject[100];

        Generate();
    }

    void Generate()
    {
        // #. Enemy

        for(int i=0; i<enemyL.Length; i++)
        {
            enemyL[i] = Instantiate(enemyL_Prefab);
            enemyL[i].SetActive(false);
        }

        for (int i = 0; i < enemyM.Length; i++)
        {
            enemyM[i] = Instantiate(enemyM_Prefab);
            enemyM[i].SetActive(false);
        }

        for (int i = 0; i < enemyS.Length; i++)
        {
            enemyS[i] = Instantiate(enemyS_Prefab);
            enemyS[i].SetActive(false);
        }


        // #. Item

        for(int i=0; i<itemBoom.Length; i++)
        {
            itemBoom[i] = Instantiate(itemBoom_Prefab);
            itemBoom[i].SetActive(false);
        }

        for (int i = 0; i < itemCoin.Length; i++)
        {
            itemCoin[i] = Instantiate(itemCoin_Prefab);
            itemCoin[i].SetActive(false);
        }

        for (int i = 0; i < itemPower.Length; i++)
        {
            itemPower[i] = Instantiate(itemPower_Prefab);
            itemPower[i].SetActive(false);
        }


        // #. Bullets

        for(int i=0; i<playerBulletA.Length; i++)
        {
            playerBulletA[i] = Instantiate(playerBulletA_Prefab);
            playerBulletA[i].SetActive(false);
        }

        for (int i = 0; i < playerBulletB.Length; i++)
        {
            playerBulletB[i] = Instantiate(playerBulletB_Prefab);
            playerBulletB[i].SetActive(false);
        }

        for (int i = 0; i < enemyBulletA.Length; i++)
        {
            enemyBulletA[i] = Instantiate(enemyBulletA_Prefab);
            enemyBulletA[i].SetActive(false);
        }

        for (int i = 0; i < enemyBulletB.Length; i++)
        {
            enemyBulletB[i] = Instantiate(enemyBulletB_Prefab);
            enemyBulletB[i].SetActive(false);
        }

    }

    public GameObject MakeObj(string type)
    {
        switch(type)
        {
            case "EnemyL":
                targetPool = enemyL;
                break;

            case "EnemyM":
                targetPool = enemyM;
                break;

            case "EnemyS":
                targetPool = enemyS;
                break;

            case "ItemBoom":
                targetPool = itemBoom;
                break;

            case "ItemCoin":
                targetPool = itemCoin;
                break;

            case "ItemPower":
                targetPool = itemPower;
                break;

            case "PlayerBulletA":
                targetPool = playerBulletA;
                break;

            case "PlayerBulletB":
                targetPool = playerBulletB;
                break;

            case "EnemyBulletA":
                targetPool = enemyBulletA;
                break;

            case "EnemyBulletB":
                targetPool = enemyBulletB;
                break;

        }

        for(int i=0; i<targetPool.Length; i++)
        {
            if(!targetPool[i].activeSelf)
            {
                targetPool[i].SetActive(true);
                return targetPool[i];
            }
        }
        return null;
    }
    
    public GameObject[] GetPool(string type)
    {
        switch (type)
        {
            case "EnemyL":
                targetPool = enemyL;
                break;

            case "EnemyM":
                targetPool = enemyM;
                break;

            case "EnemyS":
                targetPool = enemyS;
                break;

            case "EnemyBulletA":
                targetPool = enemyBulletA;
                break;

            case "EnemyBulletB":
                targetPool = enemyBulletB;
                break;

        }

        return targetPool;
    }
}

3. item.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Item : MonoBehaviour
{
    public string type;
    Rigidbody2D rigid;
    private void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
    }

    private void OnEnable()
    {
        rigid.velocity = Vector2.down * 1.5f;
    }

}

4. GameManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine;

public class GameManager : MonoBehaviour
{

    string[] enemyObjs;

    public Transform[] spawnPoints;

    public GameObject player;

    public float maxSpawnDelay;
    public float curSpawnDelay;

    public Text scoreText;
    public Image[] lifeImage;
    public Image[] boomImage;
    public GameObject gameOverSet;
    public ObjectManager objectManager;

    private void Awake()
    {
        enemyObjs = new string[] { "EnemyL", "EnemyM", "EnemyS" };
    }

    void Update()
    {
        curSpawnDelay += Time.deltaTime;
        
        if(curSpawnDelay > maxSpawnDelay)
        {
            SpawnEnemy();
            maxSpawnDelay = Random.Range(0.5f, 3f);
            curSpawnDelay = 0;
        }

        // UI Score Update

        Player playerLogic = player.GetComponent<Player>();
        scoreText.text = string.Format("{0:n0}", playerLogic.score);


    }

    void SpawnEnemy()
    {
        int randomEnemy = Random.Range(0, 3);
        int spawnPoint = Random.Range(0, 7);

        GameObject enemy = objectManager.MakeObj(enemyObjs[randomEnemy]);
        enemy.transform.position = spawnPoints[spawnPoint].position;

        Rigidbody2D rigid = enemy.GetComponent<Rigidbody2D>();
        Enemy enemyLogic = enemy.GetComponent<Enemy>();
        enemyLogic.player = player;
        enemyLogic.objectManager = objectManager;

        if(spawnPoint == 5) // Left Spawn
        {
            enemy.transform.Rotate(Vector3.forward * 90);
            rigid.velocity = new Vector2(1, -enemyLogic.speed);
        }

        else if(spawnPoint == 6) // Right Spawn
        {
            enemy.transform.Rotate(Vector3.back * 90);
            rigid.velocity = new Vector2(-1, -enemyLogic.speed);
        }

        else // Front Spawn
        {
            rigid.velocity = new Vector2(0, -enemyLogic.speed);
        }
    
    }

    public void RespawnPlayer()
    {
        Invoke("RespawnPlayerExe", 2f);
    }

    public void RespawnPlayerExe()
    {
        Player playerLogic = player.GetComponent<Player>();
        playerLogic.isHit = false;
        player.transform.position = Vector3.down * 4f;
        player.SetActive(true);
    }

    public void UpdateLife(int Life)
    {
        // #. UI Init Disable
        for (int i = 0; i < 3; i++)
            lifeImage[i].color = new Color(1, 1, 1, 0);

        // #. Life Active
        for (int i = 0; i < Life; i++)
            lifeImage[i].color = new Color(1, 1, 1, 1);
    }
    public void UpdateBoom(int boom)
    {
        // #. UI Init Disable
        for (int i = 0; i < 3; i++)
            boomImage[i].color = new Color(1, 1, 1, 0);

        // #. Life Active
        for (int i = 0; i < boom; i++)
            boomImage[i].color = new Color(1, 1, 1, 1);
    }
    public void GameOver()
    {
        gameOverSet.SetActive(true);
    }

    public void Retry()
    {
        SceneManager.LoadScene(0);
    }

}

5. Enemy.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    public string enemyName;
    public float speed;
    public int enemyScore;
    public int health;
    public float curShotDelay;
    public float maxShotDelay;

    public Sprite[] sprites;

    public ObjectManager objectManager;
    /*public GameObject BulletA;
    public GameObject BulletB;
    public GameObject itemCoin;
    public GameObject itemPower;
    public GameObject itemBoom;
    */
    public GameObject player;
    
    SpriteRenderer spriteRenderer;


    void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
    }

    private void OnEnable()
    {
        switch (enemyName)
        {
            case "L":
                health = 15;
                break;
            case "M":
                health = 5;
                break;
            case "S":
                health = 3;
                break;
        }
    }

    void Update()
    {
        Fire();
        Reload();
    }

    void Reload()
    {
        curShotDelay += Time.deltaTime;
    }

    void Fire()
    {

        if (curShotDelay < maxShotDelay)
            return;


       if(enemyName == "S")
        {
            GameObject Bullet = objectManager.MakeObj("EnemyBulletA");
            Bullet.transform.position = transform.position;
            Rigidbody2D rigid = Bullet.GetComponent<Rigidbody2D>();

            Vector3 dirVec = player.transform.position - transform.position;
            rigid.AddForce(dirVec.normalized * 10, ForceMode2D.Impulse);
        }

       else if(enemyName == "L")
        {
            GameObject BulletR = objectManager.MakeObj("EnemyBulletB");
            GameObject BulletL = objectManager.MakeObj("EnemyBulletB");
            BulletR.transform.position = transform.position+ Vector3.right * 0.3f;
            BulletL.transform.position = transform.position + Vector3.left * 0.3f;
      
            Rigidbody2D rigidR = BulletR.GetComponent<Rigidbody2D>();
            Rigidbody2D rigidL = BulletL.GetComponent<Rigidbody2D>();
            Vector3 dirVecR = player.transform.position - (transform.position + Vector3.right * 0.3f);
            Vector3 dirVecL = player.transform.position - (transform.position + Vector3.left * 0.3f);
            rigidR.AddForce(dirVecR.normalized * 4, ForceMode2D.Impulse);
            rigidL.AddForce(dirVecL.normalized * 4, ForceMode2D.Impulse);
        }


        curShotDelay = 0;
    }


    public void onDamaged(int dmg)
    {

        if (health <= 0)
            return;

        health -= dmg;
        spriteRenderer.sprite = sprites[1];
        Invoke("ReturnSprite", 0.1f);

        if (health <= 0)
        {
            Player playerLogic = player.GetComponent<Player>();
            playerLogic.score += enemyScore;

            // # Item Drop
            int ran = Random.Range(0, 10);

            if (ran < 3) // 30% 
                Debug.Log("Not Item");
            else if (ran < 6) // 30% coin
            {
                GameObject itemCoin = objectManager.MakeObj("ItemCoin");
                itemCoin.transform.position = transform.position;
            }
            else if (ran < 8) // 20% power
            {
                GameObject itemPower = objectManager.MakeObj("ItemPower");
                itemPower.transform.position = transform.position;
            }
            else if (ran < 10) // 20% boom
            {
                GameObject itemBoom = objectManager.MakeObj("ItemBoom");
                itemBoom.transform.position = transform.position;
            }
            gameObject.SetActive(false);
            transform.rotation = Quaternion.identity; 
        }
    }

    void ReturnSprite()
    {
        spriteRenderer.sprite = sprites[0];
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "BorderBullet")
        {
            gameObject.SetActive(false);
            transform.rotation = Quaternion.identity;
        }
        else if (collision.gameObject.tag == "PlayerBullet")
        {
            Bullet bullet = collision.gameObject.GetComponent<Bullet>(); // collision.gameObject에서 GetComponent한다
            onDamaged(bullet.dmg);
            collision.gameObject.SetActive(false);
        }
    }
}

출처 - https://www.youtube.com/c/GoldMetal

0개의 댓글