3 minute read

1. GameManager ๋งŒ๋“ค๊ธฐ


ํ”Œ๋ ˆ์ดํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์˜ ID, ํด๋ฆฌ์–ด ํ•œ ์Šคํ…Œ์ด์ง€ ๊ฐœ์ˆ˜, ํ”Œ๋ ˆ์ด์–ด ์ ์ˆ˜, DeathCount๋“ฑ์„ ๊ธฐ๋กํ•˜๊ธฐ ์œ„ํ•œ SingleTon์˜ GameManager๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.
์ด๋ฅผ ์œ„ํ•˜์—ฌ GameManager์ด๋ฆ„์˜ Script๋ฅผ ๋งŒ๋“ค์–ด ์ค€ ๋’ค ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

public static Bounce_GameManager instance = null;
public string ID;
public int Current_Stage;
public int Clear_Stage;
public int Current_Score;
public int Score;
public int Death_Count;

private void Awake()
{
    if (instance == null) //instance๊ฐ€ null. ์ฆ‰, ์‹œ์Šคํ…œ์ƒ์— ์กด์žฌํ•˜๊ณ  ์žˆ์ง€ ์•Š์„๋•Œ
    {
        instance = this; //๋‚ด์ž์‹ ์„ instance๋กœ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.
        DontDestroyOnLoad(gameObject); //OnLoad(์”ฌ์ด ๋กœ๋“œ ๋˜์—ˆ์„๋•Œ) ์ž์‹ ์„ ํŒŒ๊ดดํ•˜์ง€ ์•Š๊ณ  ์œ ์ง€
    }
    else
    {
        if (instance != this) //instance๊ฐ€ ๋‚ด๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ด๋ฏธ instance๊ฐ€ ํ•˜๋‚˜ ์กด์žฌํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์˜๋ฏธ
            Destroy(this.gameObject); //๋‘˜ ์ด์ƒ ์กด์žฌํ•˜๋ฉด ์•ˆ๋˜๋Š” ๊ฐ์ฒด์ด๋‹ˆ ๋ฐฉ๊ธˆ AWake๋œ ์ž์‹ ์„ ์‚ญ์ œ
    }
}


์ด์ œ ๊ฒŒ์ž„ ํ”Œ๋ ˆ์ด ๋„์ค‘ Scene์ด ๋ฐ”๋€Œ๋”๋ผ๋„ ์ด ์˜ค๋ธŒ์ ํŠธ๋Š” ์œ ์ง€๋˜๊ฒŒ ๋œ๋‹ค.
์ด์ œ ์ฃฝ์—ˆ์„์‹œ DeathCount๋ฅผ ์นด์šดํŠธ ํ•˜๊ธฐ ์œ„ํ•˜์—ฌ ์œ„ํ•˜์—ฌ Player Script์— ๋Œ์•„๊ฐ€์„œ public GameObject Game_Manager;๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋’ค ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด๋‘”๋‹ค.

void Death()
{
    rigid.velocity = rigid.velocity * 0;
    transform.position = Start_Point;
    Game_Manager.GetComponent<Bounce_GameManager>().Death_Count += 1;
    Game_Manager.GetComponent<Bounce_GameManager>().Current_Score = 0;

    for (int i = 0; i < Coins.transform.childCount; i++){
        Coins.transform.GetChild(i).gameObject.SetActive(true);
    }
    for (int i = 0; i < Weak_Floors.transform.childCount; i++)
    {
        Weak_Floors.transform.GetChild(i).gameObject.SetActive(true);
    }
}


2. ์ฝ”์ธ ์ƒํ˜ธ์ž‘์šฉ ๊ตฌํ˜„ํ•˜๊ธฐ

์ฝ”์ธ์„ ๋จน์—ˆ์„์‹œ ์ ์ˆ˜๊ฐ€ ์˜ค๋ฅด๊ณ  ์ฝ”์ธ ์˜ค๋ธŒ์ ํŠธ๋Š” ์ž ์‹œ ๋น„ํ™œ์„ฑํ™”๊ฐ€ ๋˜์—ฌ์•ผ๋งŒ ํ•œ๋‹ค. ๋˜ํ•œ ์ฃฝ์—ˆ์„๋•Œ ๋จน์€ ์ ์ˆ˜๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๊ณ , ์ฝ”์ธ์ด ๋‹ค์‹œ ํ™œ์„ฑํ™”๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค.

Player์Šคํฌ๋ฆฝํŠธ์— ๋“ค์–ด๊ฐ„ํ›„ public GameObject Coins; ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

์ด๋ฅผ ์œ„ํ•˜์—ฌ ๋ฐฉ๊ธˆ์ „์— ๋งŒ๋“  Deathํ•จ์ˆ˜์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋„ฃ๋Š”๋‹ค.

    for (int i = 0; i < Coins.transform.childCount; i++){
        Coins.transform.GetChild(i).gameObject.SetActive(true);
    }


์ดํ›„ Coin Scripts๋ฅผ ๋งŒ๋“ค์–ด์ค€ํ›„ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋„ฃ๋Š”๋‹ค.

public GameObject Game_Manager;
private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.gameObject.CompareTag("Player"))
    {
        gameObject.SetActive(false);
        Game_Manager.GetComponent<Bounce_GameManager>().Current_Score += 1;
    }
}

Unity์— ๋Œ์•„๊ฐ€์„œ Create Empty๋ฅผ ๋งŒ๋“ ํ›„ ์ด๋ฆ„์„ Coins๋กœ ๋ฐ”๊พผํ›„ ๋ชจ๋“  Coin์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค. ๊ฐ๊ฐ์— Coin๋“ค์—๊ฒŒ ์œ„ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค. ๋˜ Player ์˜ค๋ธŒ์ ํŠธ์˜ Coins ๋ณ€์ˆ˜์— Coins ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋Œ์–ด๋‹ค๊ฐ€ ๋„ฃ์–ด์ค€๋‹ค.


3. ๋ชฌ์Šคํ„ฐ AI ๊ตฌํ˜„ํ•˜๊ธฐ

๋ชฌ์Šคํ„ฐ๋Š” ๊ฐ€๋งŒํžˆ ๋ฉˆ์ถฐ ์žˆ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ์Šค์Šค๋กœ ์ƒ๊ฐ์„ ๊ฐ€์ง€๊ณ  ์›€์ง์—ฌ์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด 3๊ฐ€์ง€๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ํ•˜์˜€๋‹ค.

  • 2์ดˆ๋งˆ๋‹ค ์•ž์œผ๋กœ ๊ฐ€๊ธฐ, ์ •์ง€, ๋’ค๋กœ๊ฐ€๊ธฐ
  • ์ง„ํ–‰๋ฐฉํ–ฅ์— ๋ฐœํŒ์ด ์—†์„ ๊ฒฝ์šฐ ๋ฐฉํ–ฅ ์ „ํ™˜ํ•˜๊ธฐ
  • ๋ฐฉํ–ฅ์„ ์ „ํ™˜ํ•˜๊ฑฐ๋‚˜ ๋’ค๋กœ ๊ฐˆ ๋•Œ, ์บ๋ฆญํ„ฐ๊ฐ€ ์ขŒ์šฐ๋ฐ˜์ „ ๋˜๊ฒŒ ํ•˜๊ธฐ


์ด๋ฅผ ์œ„ํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Raycast๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋™๋ฐฉํ–ฅ์— ๋ฐœํŒ์ด ์žˆ๋Š”์ง€ ์ฒดํฌํ•˜์˜€๊ณ , Coroutine๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, 2์ดˆ๋งˆ๋‹ค Random.range์œผ๋กœ -1, 0, 1์˜ ๋ฐฉํ–ฅ์ด ๋ฌด์ž‘์œ„๋กœ ๋‚˜์˜ค๋„๋ก ํ•˜์˜€๋‹ค.

Rigidbody2D rigid;
public int next_Move;

float currnetRotation;
SpriteRenderer spriteRenderer;
// Start is called before the first frame update
void Start()
{
    currnetRotation = -1;
    rigid = GetComponent<Rigidbody2D>();
    spriteRenderer = GetComponent<SpriteRenderer>();
    StartCoroutine(Think());
    StartCoroutine(Monster_Move());
    StartCoroutine(turn());
}

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

IEnumerator Monster_Move()
{
    while (true)
    {
        rigid.velocity = new Vector2(next_Move * 2, rigid.velocity.y);

        //Platform Check
        Vector2 frontVec = new Vector2(rigid.position.x + next_Move, rigid.position.y);
        Debug.DrawRay(frontVec, Vector3.down, new Color(0, 1, 0)); //์ดˆ๋ก์ƒ‰
        RaycastHit2D rayHit = Physics2D.Raycast(frontVec, Vector3.down, 1, LayerMask.GetMask("platform"));
        if (rayHit.collider == null)
        {
            next_Move = -1 * next_Move;
        }
        yield return null;
    }
}

IEnumerator Think()
{
    while (true)
    {
        next_Move = Random.Range(-1, 2);
        yield return new WaitForSeconds(2);
    }
}

IEnumerator turn()
{
    while (true)
    {
        spriteRenderer.flipX = next_Move == 1;
        yield return null;
    }
}


4. ์•ฝํ•œ ๋ฐœํŒ ๊ตฌํ˜„ํ•˜๊ธฐ

์•ฝํ•œ ๋ฐœํŒ ๊ฐ™์€ ๊ฒฝ์šฐ ๋ฐŸ์œผ๋ฉด ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์‚ฌ๋ผ์ง€๊ณ , Death๊ฐ€ ๋ฐœ๋™ ์‹œ ๋‹ค์‹œ ์ƒ๊ฒจ์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ Coin๊ณผ ๋น„์Šทํ•˜๊ฒŒ Player ์Šคํฌ๋ฆฝํŠธ์— public GameObject Weak_Floors;๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

์ดํ›„ Deathํ•จ์ˆ˜์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

for (int i = 0; i < Weak_Floors.transform.childCount; i++){
    Weak_Floors.transform.GetChild(i).gameObject.SetActive(true);
}


Weak Floors Set์ด๋ฆ„์œผ๋กœ Empty Object๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค. ์ดํ›„ ๋ชจ๋“  Weak Floor๋ฅผ Weak Floors Set์— ๋„ฃ์–ด์ค€๋‹ค. Player ์˜ค๋ธŒ์ ํŠธ์˜ Weak_Floors๋ณ€์ˆ˜์— Weak Floors Set์„ ๋„ฃ์–ด์ค€๋‹ค. public GameObject Weak_Floors;


์ƒˆ๋กœ์šด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ ํ›„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค€๋’ค Weak FloorTop์˜ค๋ธŒ์ ํŠธ์— ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

private void OnCollisionEnter2D(Collision2D collision)
{
    if(collision.collider.CompareTag("Player")){
        gameObject.transform.parent.gameObject.SetActive(false);
    }
}


5. ์›€์ง์ด๋Š” ๋ฐœํŒ ๊ตฌํ˜„ํ•˜๊ธฐ

์ƒˆ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“  ํ›„ Moving Floor์— ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.
๋ชฌ์Šคํ„ฐ์—์„œ ์‚ฌ์šฉํ•œ Raycast๋ฅผ ๋ณ€ํ˜•ํ•˜์—ฌ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

Rigidbody2D rigid;
public float next_Move;
void Start()
{
    rigid = GetComponent<Rigidbody2D>();
    next_Move = 1;
    StartCoroutine(Move());
}

IEnumerator Move()
{
    while (true)
    {
        rigid.velocity = new Vector2(next_Move * 2, rigid.velocity.y);

        //Platform Check
        Vector2 frontVec = new Vector2(rigid.position.x + next_Move / 1.8f, rigid.position.y);
        Debug.DrawRay(frontVec, Vector3.right * next_Move, new Color(0, 1, 0)); //์ดˆ๋ก์ƒ‰
        RaycastHit2D rayHit = Physics2D.Raycast(frontVec, Vector3.down, 1, LayerMask.GetMask("platform"));
        if (rayHit.collider != null)
        {
            next_Move = -1 * next_Move;
        }
        yield return null;
    }
}


6. ๊ตฌ๋™ ํ™”๋ฉด

์ดํ›„ ์ •์ƒ์ ์œผ๋กœ ์ž˜ ๊ตฌ๋™๋˜๋Š” ๋ชจ์Šต์ด๋‹ค.

gameScreen



๊ฐœ์ธ ๊ณต๋ถ€ ๊ธฐ๋ก์šฉ ๋ธ”๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
ํ‹€๋ฆฌ๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ์ œ๋ณดํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.๐Ÿ˜