팀스파르타 내일배움캠프

[사전캠프 2일차] Unity 활용해보기

creator2041 2025. 3. 18. 17:41


1. 오늘 학습 키워드
    강력한 게임엔진 Unity를 활용해. 빗물받는 르탄이 만들어 보기!


2. 오늘 학습 한 내용을 나만의 언어로 정리하기

    1) Unity 기본 구성 활용(씬, 하이라키, 프로젝트, 인스펙터, 게임화면 구성 변경, 윈도우 구성 변경, 오브젝트 추가 등)
    2) 코딩을 활용한 캐릭터 움직임 구현

          - 컴포넌트or스크립트 붙이기

          - x y 등 값을 바꾸는걸 연산을 통한 벽과의 충돌 구현.

          - 스프라이트 랜더러를 통한 플립 전환.

          - 마우스 클릭에 반응하는 르탄이 만들기(Input.GetMouseButtonDouw(0) = 마우스 좌클릭. 1이면 우클릭!)

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

public class Rtan : MonoBehaviour
{
    float direction = 0.05f;

    SpriteRenderer renderer;

    // Start is called before the first frame update
    void Start()
    {
        Application.targetFrameRate = 60;
        renderer = GetComponent<SpriteRenderer>();
        //Getcomponent는 코드가 붙어있는 오브젝에 포함되는 컴포넌트만 가져온다. 즉, 다른 오브젝트의 컴포넌트를 가져올 수 없다.
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            direction *= -1;
            renderer.flipX = !renderer.flipX;
        }

        if(transform.position.x > 2.6f)
        {
            renderer.flipX = true;
            direction = -0.05f;
        }
        if (transform.position.x < -2.6f)
        {
            renderer.flipX = false;
            direction = 0.05f;
        }
            transform.position += Vector3.right * direction;
        //1,0,0 * 0.05f . = 모든 자리에 0.05f를 곱해준다.
    }
}

제목 : Rtan 코드

 

    3)하늘에서 떨어지는 빗방울 구현         

          - 유니티 기본 컴퍼넌트 Rigidbody2D(리지드바디)를 통한 물리에 필요한 다양한 힘(중력, 마찰력, 무게값 등) 구현;

          - 유니티 기본 컴퍼넌트 Colider2D(콜라이더)를 통한 충돌의 구현;

          - private void OnCollisionEnter2D(Collision2D collision) 을 통한 컴퍼넌트상 충돌의 코드 구현;

          - 오브젝트에 태그를 만들고 적용시키기. 코드에서 태그 불러오기(CompareTag)(Ground를 태그화. 혼동없게);

          - Random 키워드로 임위의 범위(Range)에 생성하게 만들기(void Start);

          - 임의 크기의 빗방울 만들기(Type1, 2, 3) if - else if 통해 랜덤한 크기와 색깔도 가지게 만들기.

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

public class Rain : MonoBehaviour
{
    float size = 1.0f;
    int score = 1;

    SpriteRenderer renderer;

    // Start is called before the first frame update
    void Start()
    {
        renderer = GetComponent<SpriteRenderer>();
        float x = Random.Range(-2.4f, 2.4f);
        float y = Random.Range(3.0f, 5.0f);

        transform.position = new Vector3(x, y, 0);

        int type = Random.Range(1, 4);/*1,2,3 중 하나의 값을 랜덤으로 뽑는다. 최대값은 포함되지 않음*/
        if (type == 1)
        {
            size = 0.8f;
            score = 1;
            renderer.color = new Color(100 / 255f, 100 / 255f, 1f, 1f);
        }
        else if(type == 2)
        {
            size = 1.0f;
            score = 2;
            renderer.color = new Color(130 / 255f, 130/ 255f, 1f, 1f);
        }
        else if (type == 3)
        {
            size = 1.2f;
            score = 3;
            renderer.color = new Color(150 / 255f, 150 / 255f, 1f, 1f);
        }

        transform.localScale = new Vector3(size, size, 0);
    }

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

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.CompareTag("Ground"))
        {
            Destroy(this.gameObject);
        }
        //충돌한 오브젝트가 Ground 태그를 가지고 있다면 지금 이 오브젝트를 파괴한다.
    }
}

제목 : Rain 코드

 

    4)게임 매니저를 통한 게임 로직 만들기      

          - 게임의 로직은 게임매니저에서 관리. 하이어라키의 빈 오브젝트를 통해 GameManager 구현.

          - 레인 오브젝트를 프리팹(Prefabs)화 시키기.

          - 게임 매니저 오브젝트에, 게임오브젝트를 등록할수있게 한뒤 Rain 프리팹을 드래그 앤 드롭.

          - 생성함수 Instantiate();
          - 함수 반복 함수 InvokeRepeating("name", time, repeatRate);

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

public class GameManager : MonoBehaviour
{
    public GameObject Rain;
    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("MakeRain", 0f, 1f);
    }

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

    void MakeRain()
    {
        Instantiate(Rain);
    }
}

제목 : Gamemanager 코드

 

    5)UI구현 및 점수에 게임 매니저 함수를 적용하기!

          - UI - 레거시 - 텍스트를 활용한 글자 UI의 구현! 카메라에 잡히지 않는 범위의 Canvas. but 게임엔 적용됨.

          - 게임 매니저에 스코어와 시간을 적용하는 함수와 변수를 적용!

          - 레인함수에 르탄이와 빗물의 충돌함수 형성!

          - using UnityEngine.UI; 를 이용한 UI관련 함수 패키지 불러오기.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//UnityEngine.UI 를 통해 UI관련 기능을 사용할 수 있게 한다.

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;
    public GameObject Rain;

    public Text totalScoreTxt;

    int totalScore = 0;

    private void Awake()
    {
        Instance = this;
    }
    // 싱글톤 = 이 프로그램의 게임 매니저라는 인스턴스가 하나만 존재하도록 하는 디자인 패턴
    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("MakeRain", 0f, 1f);
    }

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

    void MakeRain()
    {
        Instantiate(Rain);
    }

    public void AddScore(int score)
    {
        totalScore += score;
        totalScoreTxt.text = totalScore.ToString();
        //자료형의 변환! int 또는 float를 string으로 변환.
        Debug.Log(totalScore);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rain : MonoBehaviour
{
    float size = 1.0f;
    int score = 1;

    SpriteRenderer renderer;

    // Start is called before the first frame update
    void Start()
    {
        renderer = GetComponent<SpriteRenderer>();
        float x = Random.Range(-2.4f, 2.4f);
        float y = Random.Range(3.0f, 5.0f);

        transform.position = new Vector3(x, y, 0);

        int type = Random.Range(1, 4);/*1,2,3 중 하나의 값을 랜덤으로 뽑는다. 최대값은 포함되지 않음*/
        if (type == 1)
        {
            size = 0.8f;
            score = 1;
            renderer.color = new Color(100 / 255f, 100 / 255f, 1f, 1f);
        }
        else if(type == 2)
        {
            size = 1.0f;
            score = 2;
            renderer.color = new Color(130 / 255f, 130/ 255f, 1f, 1f);
        }
        else if (type == 3)
        {
            size = 1.2f;
            score = 3;
            renderer.color = new Color(150 / 255f, 150 / 255f, 1f, 1f);
        }

        transform.localScale = new Vector3(size, size, 0);
    }

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

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.CompareTag("Ground"))
        {
            Destroy(this.gameObject);
        }
        //충돌한 오브젝트가 Ground 태그를 가지고 있다면 지금 이 오브젝트를 파괴한다.
        if(collision.gameObject.CompareTag("Player"))
        {
            GameManager.Instance.AddScore(score);
            Destroy(this.gameObject);
        }
        //르탄이와 충돌할경우 게임매니저의 AddScore 함수를 호출하고 이 오브젝트를 파괴한다.
    }
}

GameManager 과 Rain함수의 변경을 통해 르탄이에 대한 충돌값과, 스코어 변경+UI와의 연동을 만들어낸다.

 

     6)시간값의 변화에 따른 게임종료와 재시작 구현하기!

          - Time.deltaTime; 모든 기기들이 같은 시간값을 가질수있도록 해주는 것.(=프레임 값 대비)
          - Tostring(N0); 0의 자리까지만 표시해달라는 요청.

          - Time.timeScale = 0f; 게임의 다음 프레임까지의 시간을 0으로 만들어버림. 즉 게임정지.

          - .SetActive(true || fales) => 비활성화된 오브젝트의 활성화 여부.

          - 컴퍼넌트에는 버튼 기능도 지원! (확실히 게임엔진의 유무가 게임개발의 편의성을 가른다는 반증!)

          - using UnityEngine.SceneManagement; 씬에 관련된 관리 툴도 패키징 되어있다. 

          - 버튼 클릭시 어떤 함수를 불러올지도 선택할수있다. 와...배워보니 더 편한 툴이었다.

          - 엥? 빗물과 시간이 굳음. 이것도 초기화 해야된다고 함. GameManager 에서 Awake에 타임초기화

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//UnityEngine.UI 를 통해 UI관련 기능을 사용할 수 있게 한다.

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;
    public GameObject Rain;
    public GameObject EndPannel;
    public Text totalScoreTxt;
    public Text timeTxt;
    //게임 매니저의 인스턴스를 만들어서 다른 스크립트에서도 사용할 수 있게 한다.
    //즉, 해당 변수에 다른 오브젝트가 접근할 수 있게 한다. + 접근한 오브젝트를 아래 함수에서 활용

    int totalScore = 0;


    float TotalTime = 30.0f;

    private void Awake()
    {
        Instance = this;
        Time.timeScale = 1.0f;
    }
    // 싱글톤 = 이 프로그램의 게임 매니저라는 인스턴스가 하나만 존재하도록 하는 디자인 패턴
    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("MakeRain", 0f, 1f);
    }

    // Update is called once per frame
    void Update()
    {
        if(TotalTime>=0)
        {
            TotalTime -= Time.deltaTime;
        }
        else
        {
            TotalTime = 0f;
            EndPannel.SetActive(true);
            //게임이 끝나면 EndPannel을 활성화한다.
            Time.timeScale = 0;
        }

        timeTxt.text = TotalTime.ToString("N2");
        //N1 소수점 1자리. N2 소수점 둘째 자리.
    }

    void MakeRain()
    {
        Instantiate(Rain);
    }

    public void AddScore(int score)
    {
        totalScore += score;
        totalScoreTxt.text = totalScore.ToString();
        //자료형의 변환! int 또는 float를 string으로 변환.
        Debug.Log(totalScore);
    }
}

1차 적으로 GameManager에 Awake(시작)시 타임을 초기화 해주도록 하였다.

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

public class RetryButton : MonoBehaviour
{
    public void Retry()
    {
        SceneManager.LoadScene("MainScene");
    }
}

놀라운건. 이렇게 간단하게 MainScene만 로드하게 하고. 유니티에서 자체적으로 함수를 호출하게 할수있다는 것!


3. 학습하며 겪었던 문제점 & 에러
 - 문제&에러에 대한 정의

     1)C#이 처음이라 당황했다 정도. 다만, 솔로런으로 그래도 나름 기초는 다졌다고 쏙쏙 이해가 되었다.

     2)다만 유니티에서 다뤄본건 처음인데다가, 유니티의 언어에 대한 기반이 부족해 살짝 해맨다.
 - 내가 한 시도
     1) 솔로런 복습

     2) 유니티 언어에 대한 검색 및 블로그 정리
 - 새롭게 알게 된 점

     1) 유니티는 생각보다 굉장히 편한 툴이라는것. 언리얼 엔진의 블루프린트 만큼 강력함을 자랑한다는것.

     2) 생각보다, 게임개발에 너무 도움되는 강의였다는것!
4. 내일 학습 할 것은 무엇인지

  - 풍선 지키기 게임 만들기!! 이를 통해 유니티를 극도로 심화할수 있도록 하는것!