유니티의 렌더 파이프라인

LWRP, URP

 

 

 

렌더링 파이프라인은 3D 데이터들이 2D 이미지로 구성되어 그려지는 일련의 과정을 뜻한다. 

 

◎ 렌더링 파이프라인

렌더링 파이프라인에서 데이터를 처리하는 과정을 간략하게 나눠 보자면 다음과 같다.

 

실제 파이프라인은 더 많은 과정을 거치고 플랫폼마다 다를 수 있지만 공통적이고 핵심적인 과정만 뽑자면 이 세 단계를 거치게 된다.

 

플리케이션 스테이지

애플리케이션 스테이지는 애플리케이션 상에서 처리되는 단계를 의미한다.

그래픽스 렌더링 파이프라인은 보통 GPU 파이프라인을 의미하므로 CPU에서 연산되는 애플리케이션 스테이지는 포함되지 않지만 본격적인 렌더링 파이프라인 진입 전 CPU에서 필요한 연산들을 처리해야 하므로 큰 의미로는 렌더링 파이프라인의 일부분이 된다. 

ex) 플레이어의 매 프레임마다의 움직임, 애니메이션 정보와 뼈대 위치 연산 및 메시의 버텍스에 반영 등

 

현재 프레임에서 렌더링 가능한 오브젝트들이 컬링 연산에 의해 구별된다. 

이 컬링 단계에서 효율적으로 오브젝트들이 선별되어 렌더링 되는 오브젝트 수를 줄이면 그만큼 GPU에서 처리하는 연산량이 줄게 된다. 

또한 배칭처리를 위한 연산도 GPU 파이프라인에 진입하기 전에 이루어진다. 

 

지오메트리 스테이지

이 스테이지에서는 말 그대로 지오메트리 관련 정보, 즉 지오메트리를 구성하는 요소인 버텍스와 폴리곤 처리를 담당하며 아래와 같은 과정들을 거친다.

1. 월드-뷰-프로젝션 트랜스폼
2. 클리핑
3. 버텍스 쉐이더

 

버텍스 트랜스폼(Vertex Transform)?

더보기

렌더링을 수행해야 되는 시점에 GPU가 메모리로부터 버텍스 정보를 가져와 적절한 위치에 그려주기 위해서 수행하는 트랜스폼이다. 

 

 

래스터라이저 스테이지

이 스테이지에서는 오브젝트를 그리는 픽셀들을 추리고 그 픽셀의 색을 결정한다.

버텍스 쉐이더를 거쳐서 지오메트리들이 구축되면, 화면(혹은 버퍼)의 어느 픽셀에 그려져야 하는지 결정된다.

메시의 폴리곤에 속한 영역을 픽셀로 매칭시키는 과정을 래스터라이제이션이라고 부른다. 

 

레스터라이제이션이 끝나면 최종적으로 화면에 그려져야 할 픽셀의 최종 색이 결정된다.

즉, 해당 스테이지에서는 렌더링하는 메시가 화면에 매칭되는 픽셀을 결정하고 최종 색을 입히는 과정이다.

 

뎁스 버퍼, Z-버퍼를 이용해 깊이 판정을 하고 블렌딩을 통해 최종 출력 색상을 결정한다.

 

블렌딩?

더보기

투명도를 가지는 오브젝트는 픽셀 렌더링 시 알파 블렌딩 과정을 거친다.

알파 블렌딩은 쉐이더에서 결정되는 알파값을 이용한다. 픽셀 출력의 알파값을 이용해서 해당 픽셀 위치의 컬러 버퍼의 기존 값과 적절하게 혼합해 최종 출력 색상을 결정한다. 

 

 

 

 

◎ 유니티가 제공하는 파이프라인 

유니티는 2018년부터 유니티의 렌더링 처리 방식을 C# 스크립트로 제어할 수 있는 기능인 SRP(Scriptable Render Pipeline) 기능을 제공했다.

이를 통해 전반적인 렌더링 루프를 직접 구성할 수 있으며 직접 렌더링 루프를 커스터마이징해 원하는 방식으로 렌더링을 구성할 수 있게 되었다. 

또한 SRP의 등장과 함께 유니티에 기본적으로 구현되어 있는 기본 렌더링 파이프라인빌트인(내장) 파이프라인이라고 부르게 되었다. 

 

 

1. HDRP (High Definition Render Pipeline)

하이엔드나 PC 콘솔 등을 고려해서 고품질의 비주얼 구현에 적합한 파이프라인이다.

포워드 렌더링, 디퍼드 렌더링을 모두 지원하며 컴퓨터 쉐이더 기술과 GPU 하드웨어를 사용한다. 

하지만 기본적으로 요구되는 하드웨어 스펙이 높아서 모바일 게임용으로는 적합하지 않다.

 

2. URP (Universal Render Pipeline)

Unity 2019.3 버전부터 LWRP(Lightweight Render Pipeline)이 유니버설 렌더 파이프라인으로 변경되었다. 

 

LWRP는 모든 모바일 디바이스에서 고품질 그래픽스를 구현하는 빠르고 확장 가능한 파이프라인이다. 

URP는 기본 빌트인 렌더 파이프라인보다 유연하고 확장성이 좋으며 다양한 플랫폼에 최적화된 그래픽을 제공한다.

싱글 패스 포워드 렌더링과 셰이더 그래프, VFX 그래프를 지원한다. 

https://blog.unity.com/kr/technology/how-the-lightweight-render-pipeline-is-evolving

 

 

 

참고 자료;

유니티 그래픽스 최적화 스타트업 (저; 오지현(오즈라엘), 출판사; 비엘북스, 감수; 정종필) 

니티 그래픽스 최적화 스타트업(;비엘북스)을 읽고 정리한 내용입니다.

유니티 그래픽스 최적화 스타트업

렌더링 파이프라인




렌더링 파이프라인은 간단히 말하면 3D 이미지를 2D 래스터 이미지로 표현하기 위한 단계적 방법을 말한다.

◎ 게임 루프

빠르게 이미지를 생성 해 이미지 하나하나가 화면에 보이는 것을 프레임이라고 하며, 1초에 몇 프레임이 렌더링 되는지를 FPS(Frames per second)라는 단위로 나타낸다.
화면 구성 요소들(배경, 애니메이션 포즈, 위치 등)은 각 프레임마다 조금씩 다르다.
이 화면 구성 요소들은 각 프레임마다 관련된 연산을 수행한 후 렌더링 되어야 할 요소들의 현재 모습이 결정된 후에 화면에 그려지는 것이다.
만약 60FPS라고 한다면 1초에 60 프레임, 1/60초에 한 번씩 화면에 새로 그려지게 된다.

매 프레임마다 연산이 이루어지는 요소들은 다양하다.
예를 들어 게임 내 오브젝트들의 상호 작용을 위한 물리 연산, 다양한 입출력 장치의 신호, 게임 로직 처리 연산, 캐릭터 애니메이션 처리, 네트워크 처리, 오디오 처리 등이 있다.

이런 과정을 묶어 보면 게임은 다음과 같은 과정으로 나뉘어 수행된다.


Update 단계에서는 Physics(물리), Input(입력), Logic(로직 계산), Animation(애니메이션 계산) 등이 이루어지며 Render과정에서는 씬(Scene), GUI 등을 그린다.
업데이트 과정이 처리된 후에 렌더링이 이루어지며 이러한 업데이트와 렌더링 과정이 매 프레임마다 반복된다.

더 자세한 순서는 유니티의 공식 메뉴얼에 나와있다.

◎ 렌더링 파이프라인

한 프레임의 렌더링은 프레임이 시작되면 화면에 그려야 할 오브젝트들을 하나씩 순차적으로 그리고 그려야 할 모든 오브젝트가 화면에 그려지고 나면 비로소 프레임이 끝나고 화면에 출력된다.
이때 화면에 오브젝트를 그리기 위해서는 많은 데이터가 필요하다.
이 데이터들은 (Mesh, Texture, Shader, Transform 등) 하나의 오브젝트가 렌더링 되는 과정, 그래픽스 파이프라인에서 사용한다.





참고 자료;
URL

 

Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption 

 

GameObject obj = Resources.Load<GameObject>("Prefabs/Item");
obj.transform.parent = content.transform;

 

코드에서 프리팹을 불러온 후 인스턴스화된 게임 오브젝트로 바꿔주지 않고 바로 parent를 변경하면 에러가 발생한다.

 

GameObject obj = Instantiate(Resources.Load<GameObject>("Prefabs/Item"));
obj.transform.parent = content.transform;

 

 

 

애니메이션 2

애니메이터 컨트롤러의 스테이트 머신

 

 

 

애니메이터 컨트롤러 = 스테이트 머신 + 애니메이션 클립

애니메이터는 컴포넌트가 아닌 '애셋'이다. 따라서 게임 오브젝트에 직접 적용할 수 없고 애니메이터의 프로퍼티에 있는 애니메이터 컨트롤러로 링크를 설정해 사용한다. 

애니메이터를 만들고 애니메이터 컴포넌트에 연결하는 방법

 

 

◎ 스테이트 머신

스테이트 머신은 동작 표현 방법의 하나이다. FSM(유한 상태 머신)이라 불리는 모델을 바탕으로 기호를 사용해 동작을 표현할 수 있는 것이 큰 특징이다. 유니티에선 애니메이션 동작의 표현을 위해 스테이트 머신을 사용한다.

 

Animator 창에서 오른쪽 클릭으로 생성한 empty state

 

Animator 창에서는 표현된 상태를 잇는 화살표 기호로 상태간의 트랜지션, 즉 전이를 표현한다.

컨트롤러를 만들면 처음 시작은 Entry이며 이 상태에서 빈 Empty State를 추가하면 Entry -> New State 사이의 화살표가 생긴다

 

 

Animator 창에서 state를 선택하면 보이는 해당 state의 inspector창

 

스테이트 인스펙터 창 기능

Motion : 애니메이션 클립

Speed : 재생 속도 (1.0이 기본 속도)

Multiplier : 재생 속도에 애니메이션 파라미터의 값을 곱한다.

Mirror : 애니메이션의 좌우 반전

Cycle Offset : 반복 재생 시키는 경우의 시작 위치 (재생 시간의 비율은 0과 1사이)

Foot IK : 스테이트 안에 IK 계산에서 발이 땅에 붙도록 자동 보정

Write Defaults : 스테이트를 시작할 때 키 없는 프로퍼티에 기본값을 설정

 

 

 

◎ 애니메이션 클립

애니메이션 클립은 컴포넌트가 아닌 애셋이다. 따라서 단독으로는 다룰 수 없다.

State의 인스펙터에 애니메이션 클립 애셋으로 링크를 연결해 그 스테이트의 상태일 때 애니메이션 클립이 재생되는 구조이다.

 

 

애니메이션 클립을 해당 State에 적용하는 방법은 간단하다. hierarchy 창에서 해당 animation 클립을 드래그앤 드랍으로 Motion에 넣어주면 된다.

 

아니면 아직 스테이트를 생성하지 않은 경우에는 Animator 창에서 오른쪽 버튼을 클릭해서 [From Selected Clip]을 선택하면 애니메이션 클립이 연결된 State를 생성할 수 있다. 

 

애니메이션 재생을 현재 Idle 상태에서 걷기로 바꾸고 싶다면 Idle 스테이트에서 Walk 스테이트로 화살표(트랜지션)를 이어준다. 

 

 

 

 

참고 자료;

유니티 게임 프로그래밍 바이블 (김은철, 유세라 옮김 ; 위키북스) 

 

 

애니메이션 1

애니메이터 컨트롤러

 

 

 

유니티의 애니메이션 시스템은 메카님(Mecanim)이라고 한다.

메카님을 구성하는 요소들은? 애니메이터, 아바타, 애니메이션 클립, 애니메이터 컨트롤러 등이 있다.

이 메카님을 이용하는데 가장 먼저 필요한 것이 바로 Animator Component이다. 

 

 

애니메이터 컨트롤러 만드는 법

 

 

 

◎ 애니메이터 컨트롤러 

 

화살표가 트랜지션, 네모 박스가 스테이트이다.

애니메이터 컨트롤러는 'state machine(스테이트 머신)'과 거기에 연결된 'animation clip(애니메이션 클립)'을 갖는 애셋이다.

 

컴포넌트가 아닌 애셋이므로 게임 오브젝트에 직접 적용할 수가 없다.

애니메이터의 프로퍼티에 있는 애니메이터 컨트롤러로 링크를 설정해서 사용한다. 

 

스테이트 머신은 동작 표현 방법의 하나이다.

유한 상태 머신이라 불리는 모델을 바탕으로 기호를 사용해서 동작 표현이 가능한 것이 큰 특징이다.

애니메이터 창에서는 스테이트를 표현하고 스테이트를 잇는 화살표 기호로 스테이트 간의 트랜지션을 표현한다. 

 

 

 

◎ 애니메이터 컴포넌트

애니메이션 기능을 추가하고 싶은 오브젝트의 inspector창에서 Add Component를 하면 Animator Component를 추가할 수 있다.

 

컴포넌트를 추가 후 생성해 놓은 애니메이터를 끌어다 놓으면 된다.

 

1. Controller

애니메이터 컨트롤러로 매카님의 핵심인 스테이트 머신과 애니메이션 클립을 가진다.

 

2. Avatar (아바타)

3D툴(ex, 3dMax, Blender)이 출력한 모델 파일을 유니티에서 다룰 수 있게 연결된 테이터

 

3. Update Mode

애니메이션의 계산을 언제 시행할지 결정하는 것이 Update Mode이다.

update mode에는 세 가지 종류가 있다.

 

 

첫 번째로 Normal

애니메이터 계산의 갱신이 스크립트의 Update 메서드와 같은 횟수로 호출돼 타임 스케일의 영향을 받는다
애니메이션과 Update 메서드의 계산을 완전히 동기화시킬 수 있다. (Update 메서드에서 Time 클래스의 값을 사용하는 것이 조건이다)

 

두 번째로는 Animate Physics

업데이트가 Fixed Update 메서드와 같은 횟수로 호출된다.
유니티가 다루는 물리 계산과 애니메이션을 동기화시킬 수 있다

 

마지막은 Unscaled Time

갱신은 Update 메서드와 같은 횟수인데, 타임 스케일의 영향을 받지 않는다. 메뉴 화면처럼 게임이 슬로우 모션 중일 때에도 정상적으로 애니메이션 시키고자 할 때 도움이 된다. 

 

 

4. Cull Mode

애니메이션 계산의 컬링 모드 설정이다. 컬링 판정운 카메라 밖에 있을 때의 프러스텀 (카메라) 컬링. 쉴드에 가려져 있을 때의 오클루젼 컬링 등이 있다. 대량으로 애니메이션 하는 오브젝트가 존재하는 경우 등에 불필요한 계산을 생략해 절약할 수 있다. 

이 컬모드에도 세 가지 종류가 있다.

 

 

첫 번째로는 Always Animate

컬링을 하지 않고 항상 애니메이션 계산을 한다.

 

두 번째로는 Cull Update Transforms

컬링 대상이 있을 때 애니메이션 계산의 일부 (리타깃, IK, Transform으로의 반영 등)을 생략한다.

 

세 번째로는 Cull Completely

컬링 대상일 때 모든 애니메이션 계산을 생략한다. 

 

 

 

◎ 루트모션

애니메이터 컴포넌트를 적용한 게임 오브젝트 자체는 Animator에서 보면 루트가 된다.

루트 위치에 대한 애니메이션은 게임의 설계에 따라 애니메이션으로 동작하고 싶은 경우도 있고 스크립트나 물리 계산 등으로 동작하고자 할 때도 있다.

 

유니티에서는 애니메이션 클립에 루트 위치의 이동을 포함했을 때도 애니메이터 컴포넌트의 루트 모션 (Apply Root Motion) 활성화 (on/off)를 설정해서 루트 위치의 이동을 반영하지 않게 설정할 수 있다.

 

이 설정이 있으면 루트 모션의 유무에 따라 애니메이션 클립을 각각 만들 필요가 없으므로 애니메이션의 재이용성이 높아진다

 

 

 

 

 

 

 

참고 자료;

유니티 게임 프로그래밍 바이블 (김은철, 유세라 옮김 ; 위키북스) 

 

 

2020.3 버전을 다운받았다.

너무 오랜만에 켜서 이것저것 찾아보다가 Device Simulator라는 기능을 써보고 싶어 추가하려는데 난 도저히 찾을 수 없었다.

 

그러다가 발견했다.

 

Edit >Project Settings > Package Manager에 들어가서 이 두 개를 체크해줘야 Package Manager에서 Device Simulator가  보인다.

 

 

 

 

이제 Package Manager를 켜보면 (밑에 refresh list를 누르면) 이렇게 Device Simulator를 찾을 수 있다. 

 

 

 

 

 

 

 

참고 자료;

패키지 매니저의 변경사항 in Unity 2020.1 - IndieGameMaker (unity3dstudy.com)

 

패키지 매니저의 변경사항 in Unity 2020.1

유니티 2020.1 버전에서 많은 변화중 Package Manager는 몇가지 소소한 변화가 있다. 에셋스토어 뷰의 통합 유니티 2020 버전부터는 에셋스토어에서 구매한 에셋들을 Package Manager에서 직접 다운로드 및

unity3dstudy.com

 

 

 

 

타이머가 필요 없어졌다가 다시 공부해야겠다고 생각하니까 다시 필요해졌다. 

그래서 반년 하고도 2개월만에 다시.. 유니티를 켰다.

시간이 왜이렇게 빠른지 모르겠다. 세상에나

 

 


 

 

 

우선 버튼의 이미지를 바꿔줄 예정이다. 

이왕이면 예쁜 게 좋으니까 타이머를.. 꾸며 줄 것이다.

 

 

애셋스토어에서 귀여운 픽셀 아이콘을 가져왔다.

이 아이콘들로 버튼의 이미지를 대신할 것이다!

 

 

요 친구를 사용했다. 무료 아이콘 팩인데 구성물이 아주 귀엽다

 

 

혹시나 에셋스토어 들어가는 법?

더보기

 

상단 메뉴 바에 Window > Asset Store를 누르면 asset들을 구매하고 다운받을 수 있는 store에 들어갈 수 있다. 

 

 추가하면 이런식으로 창이 뜨는데 얘를 우측 클릭해서 maximize를 클릭하면 크게 볼 수 있다. 

물론 maximize는 다른 창들도 마찬가지로 적용된다. 

 

 

 

우선 버튼의 Image Component에서 기본 리소스로 설정된 UISprite이 아닌 내가 설정하고 싶은 아이콘인 이미지로 바꿔준다. 

 

 

 

 

 

아주 귀여워졌다

 

 

 

 

이제 Button Component에서는 마우스를 버튼에 올려 놓은 상태클릭이 끝난 상태, 기본 상태 이렇게 세 가지 상태로 나누어서 이미지를 설정할 것이다! 

 

 

Transition 부분을 보면 현재 default값은 Color Tint이지만 버튼의 상태에 따라서 sprite를 바꿔줄 생각이니 옵션 중 Sprite Swap으로 바꾼다. 

 

 

 

Highlighted : 마우스가 버튼 위에 올라가 있는 상태 (버튼을 누르지는 않고 있는 중) 

Pressed : 마우스가 클릭 된 상태 (버튼 누르고 있는 중)

Selected : 버튼이 클릭 된 상태 (버튼을 누르고 있지는 않는 중)

Disabled : 버튼이 비활성화된 상태

 

 

 

 

이렇게 나눠서 설정하고 나면 다음과 같은 버튼이 완성된다.

아주 귀엽다. 

 

 

마우스가 보이지 않는 것입니당. 테두리가 없으면 마우스가 올라가 있거나 버튼 누르고 있는 상태에요

 

 

이건 물론 스크립트로 해도 되고 EventTrigger라는 Component도 있지만 이 정도는 Button Component로도 충분하다. 

 

 

 

 

다음으로 하고 싶은 건 Stop 버튼을 눌렀을 때 밑에 내가 공부 타이머를 멈춘 로그를 찍고 싶다.

이 얘기는 무슨 얘기냐면 내가 만약 a월 b일 오후 3시부터 공부를 시작했다가 2시간 30분이 흐른 후 5시 반에 공부를 잠깐 쉬기 위해 stop을 눌렀다면 밑에 로그에는 다음과 같이 기록이 남았으면 좋겠다.

 

> a월 b일 오후 3시 ~ 5시 30분

 

이런식으로 로그가 계속 쌓이는 것이다. 내가 reset을 누르기 전까지!

그리고 save 버튼을 누르면 내 로그들이 txt파일로 저장되게 만들 것이다. 

 

이건 빠른 시일 내에 추가로 만들어야 하니까 (공부할 거면?ㅎ) (3) 포스팅으로 따로 올려야겠다. 

 

 

 

 

 

요즘 Direct를 공부해서 거의 반년만에 유니티를 처음 켜봤더니 어떻게 쓰는지 까먹을 것 같아서 뭐라도 하기로 했다.

내 입맛에 맞는 공부 시간 측정 타이머가 필요하기도 했고 쉽게 만들고 싶으면서도 유니티 내용을 기본부터 포스팅하고 싶어서 타이머로 결정하게 되었다.  


 

타이머의 크기는 300x500 정도가 적당할 것 같아서 300x500으로 결정했다.

 

기본 화면에 300x500 사이즈에 맞는 Image(흰색)를 깔아놓은 상태

 

더보기

Text UI 추가 방법

Hierarchy 창에서 오른쪽 클릭 후 UI->Text를 추가하면 Canvas안에 text가 생성 된다. 

 

우선 기본적으로 Text를 추가해서 다음과 같이 설정해두었다. 

시, 분, 초로 Text를 나누고 다운받아놨던 글씨체도 추가해두었다. 

 

 

이제 기본 세팅을 끝냈으니 버튼을 누르면 시간을 계산하는 기능을 추가할 것이다.

버튼은 Text를 추가하는 방법과 동일하게 Hierarchy 창을 오른쪽 클릭해서 UI->Button을 눌러 생성하거나 상단바의 GameObject->UI->Button으로 추가해도 된다.

 

 

 

 

버튼을 추가하면 위와 같은 기본 버튼이 하나 생성된다. 개인적으로 유니티는 UI 중 버튼이 너무 유용하다는 생각을 했었다. 사용방법이 무궁무진하기 때문이다. 

 

 

그 이유는 위 사진을 보면 알 수 있는데 가장 기본적인 사용방법으로는 마우스가 버튼 위에 있는지 아닌지에 따라서 Color도 쉽게 바꿀 수 있고 Color Tint를 Sprite Swap으로 바꾸면 버튼의 이미지를 바꿀 수도 있고 Animation으로 설정하면 Animation 효과도 넣을 수 있기 때문이다. 참 좋은 기능이다.

 

 

이제 Button 기능과 Script를 연결해야 한다.

우선 Script를 하나 만들어서 함수를 만들어준다. 나중에 추가할 기능들을 위해서 시간을 Manager로 관리해주긴 할 거지만 버튼이 눌렸는지 확인하는 '버튼'용 스크립트를 만든다. 들어가야 하는 기능은 Button을 누르면 Start가 되고 한 번 더 누르면 Stop(멈춤) 상태가 되어야 한다. 

그 스크립트를 끌어다 Button에 넣어주고 아래와 같은 함수를 추가해준다.

 

bool ButtonActive; // 버튼이 눌렸는지 안눌렸는지 확인하는 상태

public void ClickButton()
{
	if(!ButtonActive)
    {
    	ButtonActive = true;
    }
    else
    {
    	ButtonActive = false;
    }
}

 

 

Button의 OnClick() 은 처음에는 List is Empty 상태, 즉 비어있지만 + 를 누르게 되면 아래와 같이 변한다.

 

 

 

이렇게 바뀐 부분의 None(Object)에 hierarchy창의 해당 버튼 오브젝트를 드래그해서 넣어준다. 그러면 Function 부분을 선택할 수 있게 되고 눌러보면 아래와 같이 내가 추가한 스크립트가 나온다. 그 안에 함수의 목록들도 나오게 되는데 그 중 ClickButton()을 눌러주면 버튼의 클릭과 해당 함수가 연결 된다. 

 

 

 

버튼을 연결했으니 이제 시간초만 계산해주면 된다. 타이머 매니저를 만들기 위해 빈 오브젝트를 하나 추가해 주고 매니저용 스크립트도 하나 만들어 준다. 

 

public class TimerCountManager : MonoBehaviour
{

    bool TimerOn; // Timer가 돌아가고 있는지 

    void Start()
    {
        TimerOn = false;
    }

    void Update()
    {

    }

    public void SetTimerOn()
    {
        TimerOn = true;
    }

    public void SetTimerStop()
    {
        TimerOn = false;
    }


}

 

 

위의 스크립트는 추가한 매니저에 넣고 버튼이 눌렸을 때 Manager에 전달해 주기 위해서 Button 스크립트도 아래와 같이 수정한다.

 

 

public class TimerCtrlButton : MonoBehaviour
{
    bool ButtonActive; // 지금 숫자 세고 있는지
    public GameObject TimerManager;
    TimerCountManager Tm;

    void Start()
    {
        ButtonActive = false;
        Tm = TimerManager.GetComponent<TimerCountManager>();
    }

    void Update()
    {
        
    }

    public void ClickButton()
    {
        if(!ButtonActive)
        {
            // 시작해야 되는 부분
            Tm.SetTimerOn();
            ButtonActive = true;
        }
        else
        {
            // STop
            Tm.SetTimerStop();
            ButtonActive = false;
        }
    }
}
더보기

 혹시몰라서 설명

TimerManager를 직접 Button의 해당 스크립트로 드래그해서 가져다 놓으면 해당 오브젝트의 스크립트(위 코드의 Tm부분)를 찾아서 쓰기 위해 Start에서 처음 시작할 때 스크립트를 찾아 놓는 것이다. 

 

 

보통 Find를 많이 쓰는데 성능 저하가 심한 대표적 기능이라고 해서 안쓰게 된 이후로 간단한 것들은 Find를 안하고 직접 메타를 연결해 주고 있다. 그러니까 Hierarchy창에 있는 TimerManager를 Button에 드래그로 연결해 준다.

 

 

 

 

이렇게 하면 이제 Button을 클릭할 때 마다 Button이 눌렸다고 Manager에게 전달하게 된다. 

전달이 됐으면 이제 시간 계산이 남아있다.

 

 

시간 계산을 위해서 Text를 연결해야 한다.

Text는 time을 Manager가 가지고 있게 할 거라서 시간을 바로 계산해서 한번에 하려고 Manager에서 같이 관리하도록 할 것이다. 

 

 

Text 추가를 위해서 우선 해야 할 것이 있다. 스크립트에서 UI 관련한 부분을 사용할 것이라고 알려주기 위해

 

using UnityEngine.UI;

 

이것을 위에 추가해주어야 한다. 그래야 text를 비롯한 image, sprite 등 UI와 관련한 부분을 스크립트에서 변경할 수 있다. 

 

 

 

이것을 추가했으면 Manager에 text와 time을 추가해 준다.

   public Text[] ClockText; // Text
    float time;  // 시간 계산 

 

Text는 text component를 연결하는 형식이고 hour, minute, second 이 세 개를 배열로 관리하려고 배열 형식으로 선언해 놨다. 

 

이렇게 선언해 놨으면 이제 Manager의 해당 스크립트 부분으로 가서 0으로 되어 있는 size를 3으로 변경해 주고 0번 부터 text인 hour, minute, second 순으로 넣어준다.

 

 

 

이제 이 연결된 text로 계산만 하면 된다. 

 

Manager의 Update부분에 타이머가 눌렸으면 시간이 추가 되게 하고 추가된 시간을 기준으로 시간, 분, 초를 계산해 낸다. 

 

더보기

혹시 몰라서 시간 계산

1 시간은 3600초 이므로 time 을 3600으로 나누고

1 분은 60초 이므로 time을 60으로 나눈 몫의 값이다. 근데 1시간이 됐을 때 60이상으로 넘어가면 안되니까 60으로 한 번 더 나머지 계산을 해준다. 

1 초는 60초가 모이면 1분이 되어야 하므로 time을 60으로 나눴을 때 나머지 값이 된다. 

 

    void Update()
    {
        if (TimerOn)
        {
            time += Time.deltaTime;
            ClockText[0].text = ((int)time / 3600).ToString();
            ClockText[1].text = (((int)time / 60 % 60)).ToString();
            ClockText[2].text = ((int)time % 60).ToString();
        }
    }

 

 

이렇게 추가하고 play를 눌러보면 Button을 눌렀을 때 시간 계산이 잘 되고 있는 것을 볼 수 있다.

 

 

 

 

 

 

+ Recent posts