๐ŸŽฎ Unity Study/Unity

[Unity Associate Programmer ์ž๊ฒฉ์ฆ ์ค€๋น„] 5๊ฐ•. ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค - ํด๋ฆญ ๊ฒŒ์ž„ ๋งŒ๋“ค๊ธฐ

ibelieveinme 2023. 5. 28. 02:15
728x90
 

5.1๊ฐ• - ๋งˆ์šฐ์Šค ํด๋ฆญ - Unity Learn

๊ฐœ์š”: ์ด์ œ ๋งˆ์ง€๋ง‰ ๋‹จ์›์ž…๋‹ˆ๋‹ค. ๋จผ์ € ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹œ์ž‘ ํŒŒ์ผ์„ ์ž„ํฌํŠธํ•œ ํ›„ ๊ฒŒ์ž„์˜ ๋ทฐ๋ฅผ 2D๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ํด๋ฆญํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€๊ฒŸ ์˜ค๋ธŒ์ ํŠธ์˜ ๋ชฉ๋ก์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

learn.unity.com


1. Bad, Good Object ๋งŒ๋“ค๊ธฐ

ํด๋ฆญ์‹œ ๊ฐ ์˜ค๋ธŒ์ ํŠธ๋งˆ๋‹ค ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด Collider๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ , ์œ„๋กœ ์˜ฌ๋ผ๊ฐ”๋‹ค๊ฐ€ ๋–จ์–ด์ง€๋Š” ํšจ๊ณผ๋ฅผ ์œ„ํ•ด Rigidbody๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

 

2. ๊ฐ์ฒด๋ฅผ ๋ฌด์ž‘์œ„๋กœ ๊ณต์ค‘์— ๋˜์ง€๊ธฐ

public class Target : MonoBehaviour{ 

    private Rigidbody targetRb;

    private float minSpeed = 12;
    private float maxSpeed = 16;
    private float maxTorgue = 10;
    private float xRange = 4;
    private float ySpawnPos = -3;

    void Start() {
        targetRb = GetComponent<Rigidbody>();
        targetRb.AddForce(RangeForce(), ForceMode.Impulse);
        targetRb.AddTorque(RandomTorgue(), RandomTorgue(), RandomTorgue(), ForceMode.Impulse);

        transform.position = RandomSpawnPos();
    }

    private Vector3 RangeForce() {
        return Vector3.up * Random.Range(minSpeed, maxSpeed);
    }

    private float RandomTorgue() {
        return Random.Range(-maxTorgue, maxTorgue);
    }

    private Vector3 RandomSpawnPos() {
        return new Vector3(Random.Range(-xRange, xRange), ySpawnPos);
    }
}

๊ฐ์ฒด ํšŒ์ „์„ ์œ„ํ•œ rigidbody.AddTorgue(Vector vector, ForceMode mode = ForceMode.Force) ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.

์ด ๋•Œ, AddTorgue ์ธ์ž์˜ vector๋Š” ํšŒ์ „ ๋ฐฉํ–ฅ์„ ์˜๋ฏธํ•œ๋‹ค.

 

3. ๊ฒŒ์ž„ ๋งค๋‹ˆ์ €์™€ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ์„ ์œ„ํ•œ ์ฝ”๋ฃจํ‹ด ๋งŒ๋“ค๊ธฐ

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

public class GameManager : MonoBehaviour
{
    [SerializeField] private List<GameObject> targets;
    private float spawnRate = 1.0f;

    void Start() {
        StartCoroutine(SpawnTarget());
    }

    IEnumerator SpawnTarget() {
        while (true) {
            yield return new WaitForSeconds(spawnRate);
            int index = Random.Range(0, targets.Count);
            Instantiate(targets[index]);
        }
    }
}

Hierarchy์— GameManager ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์œ„ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์—ฐ๊ฒฐํ•ด์ค€ ํ›„ targets ๋ฆฌ์ŠคํŠธ์— target ๊ฐ์ฒด๋“ค์„ ์—ฐ๊ฒฐํ•ด์ฃผ๋ฉด ์ž๋™์œผ๋กœ 1์ดˆ๋‹น ์ƒ์„ฑ๋˜์–ด ํŠ€์–ด์˜ค๋ฅด๋Š” target ๊ฐ์ฒด๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

4. ํด๋ฆญ ์‹œ, Sensor ํ†ต๊ณผ์‹œ ๊ฐ์ฒด ํŒŒ๊ดดํ•˜๊ธฐ

    //๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ
    private void OnMouseDown() {
        Destroy(gameObject);
    }

Target ์Šคํฌ๋ฆฝํŠธ์— OnMouseDown() ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. ์ฆ‰, target ๊ฐ์ฒด์— ๋งˆ์šฐ์Šค ํด๋ฆญ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ ๊ฐ์ฒด๋Š” ์‚ญ์ œ๋œ๋‹ค.

OnMouseDown() ํ•จ์ˆ˜๋Š” Unity์—์„œ ์ œ๊ณตํ•˜๋Š” ์ž์ฒด ํ•จ์ˆ˜๋กœ Mouse ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ์ง์ ‘ ๋ฐ›์•„์„œ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

    //ํŠธ๋ฆฌ๊ฑฐ ์ด๋ฒคํŠธ
    private void OnTriggerEnter(Collider other) {
        Destroy(gameObject);
    }

๋˜ํ•œ Prototype5 ์”ฌ์— ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ ธ์žˆ๋˜ Sensor์— Box Collider ๊ฐ€ ๋‹ฌ๋ ค์žˆ์œผ๋ฏ€๋กœ Collider ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ์ด์šฉํ•ด์„œ ์ด๊ณณ์„ ์ง€๋‚˜๋Š” ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•˜์ž.

 

5. ๊ฐ์ฒด ํด๋ฆญ์‹œ ์ ์ˆ˜ ์ถ”๊ฐ€

 

//Target.cs

    private float ySpawnPos = -3;

    //๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ
    private void OnMouseDown() {
        Destroy(gameObject);
        GameManager.gameManger.UpdateScore(pointValue);
    }

๊ฐ Target ๊ฐ์ฒด๋งˆ๋‹ค ์ ์ˆ˜ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์„œ Prefab ์ƒ์—์„œ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

 

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

public class GameManager : MonoBehaviour
{
    [SerializeField] private List<GameObject> targets;
    [SerializeField] private TextMeshProUGUI scoreText;
    private float spawnRate = 1.0f;
    private int gameScore = 0;

    public static GameManager gameManger;

    void Awake() {
        if (gameManger == null) gameManger = this;
    }

    void Start() {
        StartCoroutine(SpawnTarget());
        UpdateScore(0);
    }

    IEnumerator SpawnTarget() {
        while (true) {
            yield return new WaitForSeconds(spawnRate);
            int index = Random.Range(0, targets.Count);
            Instantiate(targets[index]);
        }
    }

    public void UpdateScore(int scoreToAdd) {
        gameScore += scoreToAdd;
        scoreText.text = "Score: "+ gameScore.ToString();
    }
}

GameManager ํด๋ž˜์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๊ณ  UpdateScore(int scoreToAdd) ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ ์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ค€๋‹ค.

 

6. ํด๋ฆญ์‹œ ํ„ฐ์ง€๋Š” Particle ์ถ”๊ฐ€

    [SerializeField] private ParticleSystem explosionParticle;

    //๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ
    private void OnMouseDown() {
        Destroy(gameObject);
        GameManager.gameManger.UpdateScore(pointValue);
        Instantiate(explosionParticle, transform.position, explosionParticle.transform.rotation);
    }

Target ๊ฐ์ฒด์— ParticleSystem ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๊ณ  Particle ์„ ์—ฐ๊ฒฐํ•ด์ค€๋‹ค.

๊ฐ์ฒด์— ํด๋ฆญ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, particle์„ ํ•ด๋‹น ์œ„์น˜์— ์ƒ์„ฑํ•ด์ค€๋‹ค.

 

7. GameOver, Restart ๊ธฐ๋Šฅ ์ถ”๊ฐ€

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

public class GameManager : MonoBehaviour
{
    [SerializeField] private List<GameObject> targets;
    [SerializeField] private TextMeshProUGUI scoreText;
    [SerializeField] private GameObject gameOverWindow;
    private float spawnRate = 1.0f;
    private int gameScore = 0;

    public static GameManager gameManger;

    void Awake() {
        if (gameManger == null) gameManger = this;
    }

    void Start() {
        Time.timeScale = 1;
        StartCoroutine(SpawnTarget());
        UpdateScore(0);
    }

    IEnumerator SpawnTarget() {
        while (true) {
            yield return new WaitForSeconds(spawnRate);
            int index = Random.Range(0, targets.Count);
            Instantiate(targets[index]);
        }
    }

    public void UpdateScore(int scoreToAdd) {
        gameScore += scoreToAdd;
        scoreText.text = "Score: "+ gameScore.ToString();

        if (gameScore < 0){
            gameOverWindow.SetActive(true);
            Time.timeScale = 0;
        }
    }

    public void RestartGame() {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }
}

๋‚˜๋Š” gameScore ๊ฐ€ ์Œ์ˆ˜๊ฐ’์ด ๋˜์—ˆ์„ ๋•Œ, TimeScale์„ 0์œผ๋กœ ๋งŒ๋“ค๋ฉด์„œ GameOver ๋˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

Restart ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด RstartGame() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋„๋ก ์—ฐ๊ฒฐํ•˜์˜€์œผ๋ฉฐ, SceneManger.LoadScene(SceneManger.GetActiveScene().name) ํ•จ์ˆ˜๋กœ ํ˜„์žฌ ํ™œ์„ฑํ™” ๋˜์–ด ์žˆ๋Š” ์”ฌ์„ ์žฌ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค.

728x90