내일배움캠프/TIL

[내배캠][Unity6기][TIL] 2. 풍선을 지켜라(1~11)

binary는 호남선 2024. 9. 5. 22:35

Preview

- 게임 화면 마우스와 사용자 마우스 동기화
-- ScreenToWorldPoint()
- Shadow
- Panel 만들기
- GameManager 싱글톤화(+추가)
- Update()와 호출된 함수 시간 보정
- PlayerPrefs
- 애니메이션 만들기
-- 게임오브젝트 상태 반복적으로 바꾸는 애니메이션
-- 플레이 중 조건에 따라 상태 바꾸는 애니메이션


게임 화면 마우스와 사용자 마우스 동기화

- 사용자가 마우스를 움직이면 마우스로 설정된 오브젝트도 똑같이 움직이도록 만들기

ScreenToWorldPoint()

- 인자로 들어온 좌표값을 World Space의 좌표값으로 변환

- 2D이므로 Vector2를 이용해 x, y만 사용해도 무관

void Update()
{
    // 마우스 위치의 벡터값(x, y) 받아오기
    // 화면에 입력된 마우스 위치를 월드스페이스 좌표값으로 변환하여 가져오기
    Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    // 마우스로 설정된 오브젝트의 위치와 마우스 위치를 동기화
    transform.position = mousePos;
}

Shadow

- Text 또는 Image 등의 그래픽 컴포넌트에 단순한 아웃라인 효과를 추가하는 컴포넌트

프로퍼티 기능
Effect Color 그림자 색상
Effect Distance 벡터로 표현된 그림자의 오프셋, 그림자의 방향과 크기를 설정

참고 : https://docs.unity3d.com/kr/2022.3/Manual/script-Shadow.html

Panel 만들기

- 화면에 나타나는 하나의 기능 묶음을 이루는 창(게임 종료 안내창, 출석체크 창 등...)을 패널 단위로 만들기

- 하나의 패널 아래에 UI 요소들을 자식 오브젝트로 넣어 하나로 관리

- 부모가 되는 Panel은 Canvas의 자식으로 CreateEmpty하여 생성

- 기본 컴포넌트인 Rect Transform만 가지고 있음

ex) EndPanel

GameManager 싱글톤화 (+추가)

- GameManager를 싱글톤화 할 때 싱글톤화 된 인스턴스가 없을 때만 실행

- 인스턴스의 유일성을 보장하기 위해 null 체크로 중복 생성을 방지

public static GameManager Instance;

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

Update()와 호출된 함수 시간 보정

- timeScale을 0으로 설정해도 Update()는 계속 실행

- Update 내용이 실행되지 않도록하여 시간 차이 보정

타이머의 값과 점수판의 값 불일치, 로그로 확인해도 일치 x

bool isPlay= true;

void Update()
{
    // 게임이 실행상태일 때만 수행
    if (isPlay)
    {
        time += Time.deltaTime;
        timeTxt.text = time.ToString("N2");
    }
}
// Square에서 충돌감지하면 호출됨
public void GameOver()
{
    isPlay= false;    // 실행 중지
    Time.timeScale = 0.0f;
    thisScoreTxt.text = time.ToString("N2");
    endPanel.SetActive(true);
}

조건을 만족할 때만 Update() 수행하도록 변경

PlayerPrefs

- 플레이어가 플레이한 게임 세션의 정보를 저장하는 클래스

- 사용자의 로컬 레지스트리에 암호화 없이 저장되므로 민감한 정보에 사용 지양함

- 활용 메서드)

DeleteAll 저장된 모든 키와 값을 삭제. 사용시 주의 필요.
DeleteKey 인자로 주어진 키를 삭제
GetFloat 인자로 주어진 키가 존재하면 키의 값을 반환
GetInt
GetString
HasKey 인자로 주어진 키가 있는지 확인, 있으면 true, 없으면 false 반환
Save 모든 수정된 환경설정을 저장
SetFloat 첫번째 인자를 키, 두번째 인자를 값(float)으로 저장
SetInt 첫번째 인자를 키, 두번째 인자를 값(Int)으로 저장
SetString 첫번째 인자를 키, 두번째 인자를 값(string)으로 저장

 

ex) 게임 종료시 최고점을 화면에 표시하기

int score = 0;	// 현재 점수
string key = "bestScore";	// 오타 방지

void Update()
{
    score++;	// 프레임마다 점수가 증가(테스트용)
}
public void GameOver()
{
    // 키와 일치하는 값이 있으면
    if (PlayerPrefs.HasKey(key))
    {
        // 키에 저장된 값을 최고점으로 가져오기
        int best = PlayerPrefs.GetInt(key);
        // 현재 점수가 최고점보다 높으면
        if(best < score)
        {
                // 현재 점수를 최고점으로 설정하여 저장
                PlayerPrefs.SetInt(key, score);
        }
    }
    // 키와 일치하는 값이 없으면
    else
    {
            // 현재 점수를 최고점으로 설정하여 저장
            PlayerPrefs.SetInt(key, score);
    }
    // 최고점을 텍스트로 변환
    bestScore.text = best.ToString();
}

참고 : https://docs.unity3d.com/ScriptReference/PlayerPrefs.html

애니메이션 만들기

게임오브젝트의 상태를 반복적으로 바꾸는 애니메이션

1. Animation을 만들고 Loop Time true로 체크, 적용할 오브젝트에 Drag

2. 오브젝트에 Animator 컴포넌트 생성된 것 확인

3. 애니메이션 창에서 녹화(빨간)버튼 누르고 변경되기를 원하는 시간으로 하얀 선 끌어당기기

4. 오브젝트를 변경하고 다시 녹화버튼 눌러 애니메이션을 저장

=> Loop Time이 true이므로 반복해서 저장된 애니메이션 실행, 2가지 상태가 계속 전환되는 것처럼 보임

플레이 중 조건에 따라 상태를 바꾸는 애니메이션

[ 충돌하면 풍선이 터지는 애니메이션 만들기 ]

1. Balloon_Die Animation을 만들고 Loop Time false로 체크, 적용할 오브젝트에 Drag

* true로 설정하면 커졌다 작아졌다를 반복, 터진 상태 유지하도록 false로 설정하기

2. 오브젝트에 Animator 컴포넌트 생성된 것 확인

3. 애니메이션 창에서 녹화(빨간)버튼 누르고 변경되기를 원하는 시간으로 하얀 선 끌어당기기

4. 오브젝트를 변경(풍선 터진 상태로 만들기)하고 다시 녹화버튼 눌러 애니메이션을 저장

5. Animator 창에서 bool 형식 parameter로 isDie을 추가

6. Balloon_Idle(기본 상태로 설정됨) 우클릭하여 Make Transition

7. 화살표를 Balloon_Die으로 연결

8. 화살표 클릭하여 Inspector에서 설정

8.1. Has Exit Time은 false로 설정

8.2. Fixed Duration은 true로 설정

8.3. Transition Duration은 0으로 설정

8.4. Transition Offset은 0으로 설정

* 위 사항은 애니메이션 간 전화 시 지연시간에 관한 설정들, 이 예제에서는 지연 없이 바로 애니메이션 전환하므로 위와 같이 설정 (자세한 설명은 참고 링크 참조하기)

9. GameManager.cs에 중단 시간 지연하여 애니메이션 실행되도록 스크립트 작성

public static GameManager Instance;
public Animator anim;	// 애니메이션 가져오기

public void GameOver()
{
    // 애니메이션 매개변수 isDie의 값을 true로 설정
    anim.SetBool("isDie", true);
    // 바로 시간을 중지하면 애니메이션 실행 x
    // Time.timeScale = 0f;
    // 0.5초 지연 후에 시간 중지하는 함수 호출해 조절하기
    Invoke("TimeStop", 0.5f);
}
void TimeStop()
{
    Time.timeScale = 0f;
}

참고 : https://docs.unity3d.com/kr/2022.3/Manual/class-Transition.html


추가로 궁금해서 공부한 내용...

Sprite Renderer의 Order in Layer 속성과 collision

Q. 같은 layer에 있는 오브젝트끼리만 충돌이 발생하는가?

A. No! Order in Layer와 collision은 연관 x

Order in Layer는 랜더링과 관련된 속성값이고 collision은 Collider 컴포넌트 설정에 따름

출처 : 직접 테스트 해봄 & Unity Discussion에서 staff 답변 참조

https://discussions.unity.com/t/2d-player-collides-with-objects-on-other-sorting-layers/755786