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

배근철·2022년 8월 2일
0

GoldMetal BE4

목록 보기
6/11

✍ 아이템 준비

  • 아이템을 스프라이트로 배치한 후 , 필요한 컴포넌트를 추가한다.
    • 프리펩으로 만들기 위함.
  • 아이템들의 애니메이션 적용과 , tag를 만들어 적용

✍ 아이템 충돌로직

  • 아이템을 먹었을 때 아이템의 Type에 따라 작동하는 걸 switch문으로 작성
 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;


            }
            Destroy(collision.gameObject);
        }

✍ 필살기

  • 필살기는 적과 플레이어를 가리면 안되므로 Order in Layer를 적절히 설정
  • 필살기 스프라이트를 추가한 후 안보이게 꺼두자. -> 필살기 사용 할 때 SetActive(true)

FindGameObjectsWithTag

  • 맞는 태그의 모든 오브젝트를 추출
  • GameObject.FindGameObjectsWithTag("Enemy");로 설정해주면 Scene에 존재하는 모든 Enemy 태그가 배열에 저장됨.
  • FindGameObjectsWithTag를 이용해 모든 적과 적의 총알을 배열들로 가져온다.
  • 가져온 후 , Enemy는 onDamaged함수를 실행시켜 파괴시키고,
    EnemyBullet은 Destroy시킨다.
 //#1. Effect visible
        boomEffect.SetActive(true);
        Invoke("OffBoomEffect", 3f);
 //#2. Remove Enemy
        GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
        for (int i = 0; i < enemies.Length; i++)
        {
            Enemy enemyLogic = enemies[i].GetComponent<Enemy>();
            enemyLogic.onDamaged(1000);
        }
  //#3. Remove Enemy Bullet
        GameObject[] bullets = GameObject.FindGameObjectsWithTag("EnemyBullet");
        for (int i = 0; i < bullets.Length; i++)
            Destroy(bullets[i]);

  • 필살기 스프라이트는 Invoke로 시간차 비활성화
  • 필살기도 power와 같이 개수를 정하고, Life처럼 UI로 나타냄.

✍ 아이템 드랍

  • 적을 처치했을 때 랜덤한 확률로 아이템이 드랍되게 구현
  // # Item Drop
            int ran = Random.Range(0, 10);
            if (ran < 3) // 30% 
                Debug.Log("Not Item");
            else if (ran < 6) // 30% coin
                Instantiate(itemCoin, transform.position, itemCoin.transform.rotation);
            else if (ran < 8) // 20% power
                Instantiate(itemPower, transform.position, itemPower.transform.rotation);
            else if (ran < 10) // 20% boom
                Instantiate(itemBoom, transform.position, itemBoom.transform.rotation);

Random.Range()

  • int형이면 min에서 max-1값까지
  • float형이면 min에서 max값까지 (꼭 숫자옆에f를 붙여주자)

✍ 전체코드

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 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[] enemies = GameObject.FindGameObjectsWithTag("Enemy");

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

      //#3. Remove Enemy Bullet
      GameObject[] bullets = GameObject.FindGameObjectsWithTag("EnemyBullet");

      for (int i = 0; i < bullets.Length; i++)
          Destroy(bullets[i]);


  }
  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 = Instantiate(BulletA, transform.position, transform.rotation);
              Rigidbody2D rigid = Bullet.GetComponent<Rigidbody2D>();
              rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
              break;
          case 2:
              // Power 2
              GameObject BulletR = Instantiate(BulletA, transform.position + Vector3.right*0.1f, transform.rotation);
              GameObject BulletL = Instantiate(BulletA, transform.position + Vector3.left*0.1f, transform.rotation);
              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 = Instantiate(BulletA, transform.position + Vector3.right*0.35f, transform.rotation);
              GameObject BulletCC = Instantiate(BulletB, transform.position, transform.rotation);
              GameObject BulletLL = Instantiate(BulletA, transform.position + Vector3.left*0.35f, transform.rotation);
              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);
          Destroy(collision.gameObject);
      }

      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;


          }
          Destroy(collision.gameObject);
      }
  }

  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. GameManager.cs

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

public class GameManager : MonoBehaviour
{
  public GameObject[] 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;

  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 = Instantiate(enemyObjs[randomEnemy], spawnPoints[spawnPoint].position, spawnPoints[spawnPoint].rotation);

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

      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);
  }

}

3. Item.cs

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

public class Item : MonoBehaviour
{
  public string type;
  Rigidbody2D rigid;
  void Awake()
  {
      rigid = GetComponent<Rigidbody2D>();
      rigid.velocity = Vector2.down * 1;
  }

  
}

4. Bullet.cs

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

public class Bullet : MonoBehaviour
{

  public int dmg;
  private void OnTriggerEnter2D(Collider2D collision)
  {
      if(collision.gameObject.tag == "BorderBullet")
      {
          Destroy(gameObject);
      }
  }
}

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 GameObject BulletA;
  public GameObject BulletB;
  public GameObject itemCoin;
  public GameObject itemPower;
  public GameObject itemBoom;
  public GameObject player;

  SpriteRenderer spriteRenderer;


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

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

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

  void Fire()
  {

      if (curShotDelay < maxShotDelay)
          return;


     if(enemyName == "S")
      {
          GameObject Bullet = Instantiate(BulletA, transform.position, transform.rotation);
          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 = Instantiate(BulletB, transform.position + Vector3.right * 0.3f, transform.rotation);
          GameObject BulletL = Instantiate(BulletB, transform.position + Vector3.left * 0.3f, transform.rotation);
          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
              Instantiate(itemCoin, transform.position, itemCoin.transform.rotation);
          else if (ran < 8) // 20% power
              Instantiate(itemPower, transform.position, itemPower.transform.rotation);
          else if (ran < 10) // 20% boom
              Instantiate(itemBoom, transform.position, itemBoom.transform.rotation);

          Destroy(gameObject);
      }
  }

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

  private void OnTriggerEnter2D(Collider2D collision)
  {
      if (collision.gameObject.tag == "BorderBullet")
          Destroy(gameObject);

      else if(collision.gameObject.tag == "PlayerBullet")
      {
          Bullet bullet = collision.gameObject.GetComponent<Bullet>(); // collision.gameObject에서 GetComponent한다
          onDamaged(bullet.dmg);
          Destroy(collision.gameObject);
      }
  }
}

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

0개의 댓글