[골드메탈 BE2 실습]

배근철·2022년 7월 5일

GoldMetal BE2

목록 보기
2/2

✍ BE2 플랫포머게임 완성

알아둘 점

  • 물리적충돌이 없는것들은 OnTrigger 사용

    • ex) 아이템 획득, 목적지 도착
  • 물리적충돌이 있는것들은 OnCollision 사용

    • ex) 몬스터 충돌
  • transform은 값을 담고 있는 객체

  • collision.gameObject.name.Contains(비교문);
    대상 문자열에 비교문이 있으면 true 반환

     bool isBronze = collision.gameObject.name.Contains("Bronze");
               bool isSilver = collision.gameObject.name.Contains("Silver");
               bool isGold = collision.gameObject.name.Contains("Gold");
    ``
  • collision.attachedRigidbody.velocity = Vector2.zero;
    -> 충돌체에 붙어있는 리지드바디의 속력을 0으로 만든다.

  • 스테이지 부피에 따라 스테이지가 작으면 오브젝트로 컨트롤하고 스테이지가 크다면 Scene으로 구분해서 컨트롤 한다.

  • Time.timeScale = 0 (시간 멈추게하기)
    Time.timeScale = 1 (시간 흐르게하기)

  • Button은 GameObject변수로 Button안의 Text를 가져올때는 GetComponentInChildren으로 가져온다.

  • 사운드가 겹칠 때는 PlayOneShot(clip)을 사용한다.


✍ 플레이 화면

데미지를 입었을 때 UI가 투명해지는 모습

코인을 먹었을 때 점수 확인

다음 스테이지에서의 UI 확인

사망했을 때 재시작 버튼 활성화!

게임 클리어 버튼

✍ 전체 코드

1. Player.cs

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

public class Player : MonoBehaviour
{
    public int JumpPower;
    public int mxSpeed;
    public AudioClip Jump;
    public AudioClip Item;
    public AudioClip Die;
    public AudioClip Finish;
    public AudioClip Damaged;
    public AudioClip Attack;

    public GameManager gameManager;
    CapsuleCollider2D capCollider;
    Rigidbody2D rigid;
    SpriteRenderer spriteRenderer;
    Animator anim;
    AudioSource audioSource;
   
    // Start is called before the first frame update


    private void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        anim = GetComponent<Animator>();
        capCollider = GetComponent<CapsuleCollider2D>();
        audioSource = GetComponent<AudioSource>();

    }
    void Start()
    {
        
    }


    // Update is called once per frame
    void Update()
    {

        if (Input.GetButtonDown("Jump") && !anim.GetBool("isJumping"))
        {
            Playsound("JUMP");
            rigid.AddForce(Vector2.up * JumpPower, ForceMode2D.Impulse);
            anim.SetBool("isJumping", true);
        }

        if (Input.GetButtonUp("Horizontal"))
            rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
        

        if (rigid.velocity.x < 0)
            spriteRenderer.flipX = true;
        else
            spriteRenderer.flipX = false;

        // Mathf 수학관련 함수를 제공하는 클래스 
        if (Mathf.Abs(rigid.velocity.x) > 0.5f)
            anim.SetBool("isWalking", true);
        else
            anim.SetBool("isWalking", false);
    }

    private void FixedUpdate()
    {
        float x = Input.GetAxisRaw("Horizontal");
        rigid.AddForce(Vector2.right * x, ForceMode2D.Impulse);


        if (rigid.velocity.x > mxSpeed)
            rigid.velocity = new Vector2(mxSpeed, rigid.velocity.y);
        else if (rigid.velocity.x < -mxSpeed)
            rigid.velocity = new Vector2(-mxSpeed, rigid.velocity.y);


        if (rigid.velocity.y < 0)
        {

            Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0));

            RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1, LayerMask.GetMask("Platform"));

            if (rayHit.collider != null)
            {
                if (rayHit.distance < 0.5f)
                    anim.SetBool("isJumping", false);
            }
        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "Trap")
        {
            if (collision.gameObject.tag == "Enemy" && rigid.velocity.y < 0 && rigid.transform.position.y > collision.transform.position.y)
            {
                OnAttack(collision.transform);
                Playsound("ATTACK");
            }
            else
            {
                OnDamaged(collision.transform.position);
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Item")
        {
            Playsound("ITEM");
            // Point Up
            bool isBronze = collision.gameObject.name.Contains("Bronze");
            bool isSilver = collision.gameObject.name.Contains("Silver");
            bool isGold = collision.gameObject.name.Contains("Gold");

            if (isBronze)
                gameManager.stagePoint += 50;
            else if (isSilver)
                gameManager.stagePoint += 100;
            else if (isGold)
                gameManager.stagePoint += 300;

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

        else if(collision.gameObject.tag == "Finish")
        {
            Playsound("FINISH");
            // NextStage
            gameManager.NextStage();
        }

    }

    void Playsound(string s)
    {
        switch(s)
        {
            case "JUMP":
                audioSource.clip = Jump;
                audioSource.Play();
                break;
            case "ATTACK":
                audioSource.clip = Attack;
                audioSource.Play();
                break;
            case "ITEM":
                audioSource.clip = Item;
                audioSource.Play();
                break;
            case "DAMAGED":
                audioSource.PlayOneShot(Damaged);
                break;
            case "FINISH":
                audioSource.clip = Finish;
                audioSource.Play();
                break;
            case "DIE":
                audioSource.PlayOneShot(Die); // 죽을 때 데미지입는 소리와 중첩되도록 OneShot사용
                break;
        }
    }


    void OnAttack(Transform _enemy)
    {
        gameManager.stagePoint += 150;
        rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
        Enemy enemy = _enemy.GetComponent<Enemy>();
        enemy.OnDamaged();
    }
    void OnDamaged(Vector2 target)
    {
        gameManager.HealthDown();
        Playsound("DAMAGED");
        gameObject.layer = 11;
        anim.SetTrigger("Damaged");
        spriteRenderer.color = new Color(1, 1, 1, 0.5f);
        int dir = transform.position.x - target.x > 0 ? 1 : -1;

        rigid.AddForce(new Vector2(dir, 1) * 7, ForceMode2D.Impulse);

        Invoke("OffDamaged", 1);
        
    }

    void OffDamaged()
    {
        gameObject.layer = 10;
        spriteRenderer.color = new Color(1, 1, 1, 1);
    }


    public void OnDie()
    {
        Playsound("DIE");
        spriteRenderer.color = new Color(1, 1, 1, 0.5f);
        spriteRenderer.flipY = true;
        rigid.AddForce(Vector2.up * 5, ForceMode2D.Impulse);
        capCollider.enabled = false; // 콜라이더 비활성화
       
    }

    public void VelocityZero()
    {
        rigid.velocity = Vector2.zero;
    }
}

2. Enemy.cs

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

public class Enemy : MonoBehaviour
{

    public int nextMove;
    SpriteRenderer  spriteRenderer;
    Rigidbody2D rigid;
    CapsuleCollider2D capCollider;
    Animator anim;

    private void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        capCollider = GetComponent<CapsuleCollider2D>();
        Invoke("Think", 5);
    }
    // Update is called once per frame
    void FixedUpdate()
    {
        rigid.velocity = new Vector2(nextMove, rigid.velocity.y);


        Vector2 vec = new Vector2(rigid.position.x + nextMove*0.3f, rigid.position.y);
        Debug.DrawRay(vec, Vector3.down, new Color(0, 1, 0));
        RaycastHit2D rayHit = Physics2D.Raycast(vec, Vector3.down, 1, LayerMask.GetMask("Platform"));

        if (rayHit.collider == null)
        {
            nextMove *= -1;
            spriteRenderer.flipX = (nextMove == 1);
            CancelInvoke();
            Invoke("Think", 2);
        }
    }

    void Think()
    {
        nextMove = Random.Range(-1, 2);

        float nextTime = Random.Range(2f, 6f);

        anim.SetInteger("Walk", nextMove);


        Invoke("Think", nextTime);
        if (nextMove != 0)
            spriteRenderer.flipX = (nextMove == 1);
    }

    public void OnDamaged()
    { 
        spriteRenderer.color = new Color(1, 1, 1, 0.5f);
        spriteRenderer.flipY = true;
        rigid.AddForce(Vector2.up * 5, ForceMode2D.Impulse);
        capCollider.enabled = false; // 콜라이더 비활성화
        Invoke("EnableMonster", 5);
    }

    void EnableMonster()
    {
        gameObject.SetActive(false);
    }
}

3. GameManager.cs

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

public class GameManager : MonoBehaviour
{

    public int totalPoint;
    public int stageIdx;
    public int stagePoint;
    public int health;
    public GameObject[] stages;
    public Player player;
    public Image[] images;
    public Text Stagetext;
    public Text Pointtext;
    public GameObject RetryBtn; // Button은 GameObject

    private void Start()
    {
        Stagetext.text = "STAGE" + (stageIdx + 1).ToString();
    }

    private void Update()
    {
        Pointtext.text = (totalPoint + stagePoint).ToString();
    }
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            HealthDown();

            if (health > 0)
            {
                Reposition();
            }

            else
            {
                player.OnDie();
                Time.timeScale = 0;
                RetryBtn.SetActive(true);
            }
            
        }

    }

    public void NextStage()
    {
        if (stageIdx < stages.Length-1)
        {
            stages[stageIdx].SetActive(false);
            stageIdx++;
            stages[stageIdx].SetActive(true);
            Reposition();
            Stagetext.text = "STAGE " + (stageIdx + 1).ToString();
        }

        else
        {
            Time.timeScale = 0;
            RetryBtn.SetActive(true);
            Text btnText = RetryBtn.GetComponentInChildren<Text>();
            btnText.text = "게임 클리어!";
            stageIdx = 0;
        }
        totalPoint += stagePoint;
        stagePoint = 0;
          
    }

    public void HealthDown()
    {
        if (health > 1)
        {
            health--;
            images[health].color = new Color(1, 1, 1, 0.5f);
        }
        else
        {
            images[0].color = new Color(1, 1, 1, 0.5f);
            player.OnDie();
            RetryBtn.SetActive(true);
            Time.timeScale = 0;
        }

    }

    public void Restart()
    {
        Time.timeScale = 1;
        SceneManager.LoadScene(0);
    }
    void Reposition()
    {
        player.VelocityZero();
        player.transform.position = new Vector3(-4, 1, 0);
    }

   
}

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

0개의 댓글