공부/Game Bootcamp

[멋쟁이사자처럼 부트캠프 TIL] 유니티 게임 개발 3기 : Animation, Light, UI - Text 등

Ail_ 2024. 11. 28. 16:06

캐릭터 걷기 애니메이션

Right Log에서 Create Empty 추가

기존 RightLeg와 동일한 위치에 축이 생성됨

다리 object 끝까지 위로 올려주기

그럼 현재 저 GameObject의 위치는 부모 오브젝트 기준으로 잡혀있다고 보면 됨

복사하여 Left Leg에 넣은 GameObject도 부모 오브젝트로부터 동일하게 위치하면 됨

하지만 지금 Right Leg의 GameObject와 같은 위치에 있기 때문에 위치가 다르게 뜸 -> 동일하게 0, 1, 0으로 맞춰줄 것

X축을 0으로 수정해주면 Left Leg로 잘 위치함

강사님이 만드신 캐릭터 은근 귀여움ㅋㅋㅋ눈의 중요성인가

계층 구조를 반대로 변경 필요

저번 문처럼 되어야 함 - Pivot 기준으로 Right Leg, Left Leg 각각 들어가야 함

 

Right Leg(Prefab)를 이동하려고 하면 메세지가 뜸

Prefab : 원본 데이터

계층 구조(부모-자식) 변경하려고 하니 원본 데이터가 있어서 안된다고 막는 것

Prefab 해제

 

이제 계층 구조 잡고 Pivot으로 조절 가능

당차게 앞으로 나갈 수 있음

 

애니메이션 녹화 키고 현재 상태 Add Key

 

30프레임쯤 동작 추가

 

1:30에 동작 추가

-26 => 26

26 => -26으로

 

2:00에 멈춤 동작 추가

 

속도 조절

모두 드래그하고 생기는 막대를 조절

 

결과물

지금은 아무것도 안눌러도 계속 걷고 있음

 

키 입력 이벤트일 때 걷기

키 입력 이벤트가 나올 때만 걸어야 하기 때문에 빈 애니메이션이 Default가 되어야 함

 

한번만 실행 / 누르는 동안 실행

한번만 누르는 건 Any State

누르는 동안(반복적으로)은 Entry

 

Entry는 하나밖에 연결 못함

New State에서 Character Move로 왔다갔다 해야함

실행해보면 계속 화살표를 따라 왔다갔다함

-> Parameter Key 값 필요

 

Parameter

Parameter 쓰는 법

 

우리가 필요한 것은 키 입력 상태에 대한 Boolean 값

키를 누름 : True

키를 누르지 않음 : False

isWalk로 bool parameter 생성

 

Condition에 각각 추가

 

스크립트 수정

스크립트 상에서는 h, v가 0일 때가 바로 키를 안누른 상태임

	private float h = 0f;
	private float v = 0f;

	private void Move()
    {
        h = Input.GetAxis("Horizontal");// 좌우 이동
        v = Input.GetAxis("Vertical"); // 앞뒤 이동

        Vector3 dir = new Vector3(h, 0, v).normalized; // 입력한 값으로 Vector3 선언 및 할당

        transform.position += dir * Time.deltaTime * moveSpeed; // 입력한 값으로 이동 기능

        if (h != 0 || v != 0) // h나 v 둘 중 하나를 눌렀을 때
        {
            // 캐릭터가 이동하려는 방향을 바라보게 하는 코드
            Vector3 targetPos = transform.position + dir; // 목표 위치
                                                          //                현재 위치(자기 자신의 위치) + 입력 값에 의한 방향
            transform.LookAt(targetPos); // 목표 위치를 바라보는 코드
        }
    }

 

Input.GetAxis()를 썼기 때문에 다음처럼 값이 바뀜

 

따라서 아래처럼 스크립트 수정

    public Animator anim;

    private void Move()
    {
		if (h == 0 && v == 0) // 아무런 키도 누르지 않았을 때
		{
		    anim.SetBool("isWalk", false); // 멈추기
		}
		else // 이동키 중 어떤 키라도 눌렀을 경우
		{
		    anim.SetBool("isWalk", true); // 걷기
		}
    }

 

Anim에 Animator 넣기

 

결과물

1. 키를 눌렀을 때 바로 안움직임

2. 키에서 손을 뗐을 때 바로 안 멈춤

3. 걷는 속도가 느림

속도 수정

 

Has Exit Time

transition 누르면 나오는 항목

남은 애니메이션을 기다려줄 지 여부

-> 기본값 on인데 off로 변경

결과물

아까보단 나은데 아직 좀 딜레이가 있음

Transition Duration

화살표 지나가는 시간

0으로 설정

 

Curves

애니메이션을 자동으로 Blend 해줌

 

확인해보면 멈출 때 속도가 느려짐

 

수정해보기

보라색 선 누르고 보라색 포인트 누르고 기울기 조절해주기

 

오른쪽과 비슷하게 기울기 조절

전 -> 후

 

자연스러워짐

 

 

라이트 Light

빛 효과

 

Directional Light

직선의 모든 범위를 비추는 light

 

위치 상관 없음

 

Point Light

구체 Sphere모양 범위 ex. 전구

 

Spot Light

Cone 모양의 범위 ex. 손전등

 

Area Light

Bake 전용(빛을 미리 만들어 놓는 용도)

사각형 || 타원 모양의 범위 -> Static 설정 필요

 

Bake(정적) <-> Realtime(실시간, 동적)

 

태양 구현

스크립트 작성

낮고 밤, 즉 해가 넘어가는 느낌을 구현해보자

-> 어떤 대상(Directional Light)을 계속 회전시키는 기능

 

LightRotation.cs 생성

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

public class LightRotation : MonoBehaviour
{
    public float rotSpeed = 10f;
    void Update()
    {
        this.transform.Rotate(Vector3.right * rotSpeed * Time.deltaTime); // this 생략 가능
    }
}

 

코드 설명

 

Vctor3.right : DL이 x축 기준으로 돌아야함

 

결과물

 

손전등 만들기

에셋 Improt해서 적당한 위치에 넣어주기

 

이제 손전등을 생각해보면

손전등 불빛이 on/off가 되어야 함(존재 on/off)

 

스크립트 생성

FlashLight.cs

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

public class FlashLight : MonoBehaviour
{
    public GameObject spotLight;
    void Update()
    {
        spotLight.SetActive(true); // 존재 On
        spotLight.SetActive(false); // 존재 Off
    }
}

 

GameObject로 하는 이유

Spotlight라는 Light Component에서는 아래 항목 수정 가능

  • 빛의 세기
  • 빛의 범위
  • 빛의 거리
  • 빛의 색상 등

지금 필요한 건 light On/Off라 게임오브젝트 존재를 on/off하면 됨

 

안 좋은 코드

보면서 a = !a로 하면 되는 거 아니야? 했는데 맞았음

 

코드 최종본

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

public class FlashLight : MonoBehaviour
{
    public GameObject spotLight;

    public bool isFlashLight = false;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            isFlashLight = !isFlashLight;
            spotLight.SetActive(isFlashLight);
        }
    }
}

 

Flashlight에 Spot Light 추가

 

Spot Light가 제대로 비추도록 회전

 

Light 속성값 설명

  • Range : 길이
  • Spot Angle : 범위
  • Color : 색상
  • Intensity : 강도

 

스크립트 설정

Flashlight 오브젝트에 작성한 FlashLight 스크립트 넣고 Spot Light에 Spot Light 넣어주기

맨 처음에 IsFlashLight가 off로 초기값 줬기 때문에 Spot Light도 꺼야함

 

이제 F키 누르면 켜짐

빛 레이어 처리하면 좀더 리얼해짐

 

저 상태에선 벽을 빛이 뚫는데 Shader 바꿔주면 됨

 

라이트에 창문 그림자 등 텍스처 효과 넣는 법

 

리소스 받아서 Texture Type Cookie로 변경

변경 안해도 내부 처리로 되긴 할텐데 공식 문서에서는 Cookie로 변경을 권장

수정하고 Apply

 

Spot Light의 Cookie에 넣어주면 됨

 

텍스처 Wrap Mode

Clamp : 늘이기(확대)

Repeat : 격자 느낌

 

 

Skybox

Cube Map 방식

 

6 Sided 방식

Panorama 방식

요즘 젤 많이 사용함

 

Light, Sky 정보

 

 Skybox Material 항목 변경

그냥 하늘로 드래그해도 됨

 

Skybox Inspector

Tint Color, Exposure 등 설정 가능

Rotation으로 하늘 돌아가는 느낌 연출 가능

 

환경광 바꾸기

 

결과물

 

Flappy Bird 만들기

2D 전환

 

UI - Canvas 추가

유저 인터페이스 User Interface

사용자가 프로그램의 정보를 보거나 상호작용 할 수 있는 기능

사람들이 컴퓨터, 시스템, 기기 등 그 사이에서 일어나는 상호작용(Interaction)을 매개하는 것

 

기본 UI

 

PC, Mobile 게임의 UI / 화면에 딱 붙은 UI / 오버레이(Overlay) UI

 

VR의 UI / 공간에 존재하는 UI / 월드(World) UI

 

토막상식

예전에 Unity가 만든 UI가 넘 구려서 어떤 개발자가 만든 NGUI 에셋이 대중화되어 쓰이다가 Unity에서 그 개발자 불러서 UGUI가 만들어짐

새로 나온 UI Toolkit도 있는데 유니티 웹개발용 느낌이라 좀 애매함 아직 사용하기엔 불편함

 

새로 만든 Canvas는 Overlay UI임

=> GameView에 맞춰서 만들어짐

 

다른 Render Mode

 

GameView 사이즈를 FullHD로 변경

 

캔버스 Canvas

UI를 배치할 수 있는 2D 도화지의 개념

UI는 무조건 Canvas 안에 만들어짐

image 추가

그냥 바로 image 추가해도 자동으로 Canvas 아래에 만들어짐

 

그러면 이렇게 원본이 들어옴

 

Anchor Presets

기준점(Pivot, Anchor)에 따라 이미지의 위치를 옮기거나 기준점을 바꾸는 것

Anchor의 이동을 확인할 수 있음

 

저거 누르면 기준점이 분리됨

 

alt + click하면 stretch됨

 

Canvas Scaler 변경

Scale With Screen Size로 변경(화면 크기에 따라 조정되도록)

1920x1080으로 변경

 

Text(TMP) 추가

Text - TextMeshPro(TMP) 사용하면 됨

 

Text(TMP)와 Text(Legacy)의 차이점

Text는 흐릿함 -> 압축하고 크기 키워서 썼었음

 

한글 치면 TMP는 제대로 안나옴

Legacy는 폰트 파일 그대로 사용해서 잘 뜸

TMP는 폰트를 가공한 Font Asset을 사용함 -> 바로 안 뜸

 

우리는 새로 나온 TMP를 사용하자

 

Font Asset

리소스에 폰트 파일 넣어주고나서

Font Asset으로 변환해줘야함

변환하면 SDF 파일이 생김

TMP에 적용해주면 잘 나옴

Font Asset Creator

여는 법 1번

 

여는 법 2번

 

다국어의 경우 필요에 따라 Character Sequence 값 수정하여 폰트 에셋 추가 필요

시간이 오래 걸리기 때문에 유의

최대 8000까지 되는데 간단하게 하면 1000(1k)면 충분함

 

TMP 속성

Auto Size : 다국어할 때 사이즈 자동 조절

 

대충 만들어본 제목

미국 옛날 카툰 스타일의 어쩌구를 생각하며...

 

 

사담

손전등을 들고 움직이는 캐릭터 구현이라니 재밌어...

뭔가 나날이 에셋의 중요성을 알게 되는 것 같다ㅋㅋ

영상 편집할 때처럼...

개발할 때 라이브러리 찾아보던 것 처럼...

역시 사람은 함께 가야 더 멀리 가나보다. 여기서도 나름 적용되는 말인듯

좋은 기능 만든 사람 영입해서 새로 기능 다듬는 유니티도 신기하다

저러니까 이렇게 롱런하는구나

 

자습 시간에 만들어본 점프랑 손 애니메이션

손이랑 다리 애니메이션을 따로 분리하고 싶었는데

진행이 Entry - 기본자세 State - 다리 모션으로만 가고,

똑같이 bool 조건의 다른 팔 모션으로는 안갔다...아마 안꼬이게 하나에 하나씩만 되는 듯?

그래서 그냥 다리+팔 모션 하나로 만들고 점프 모션은 Any State에서 받으니까 따로 빼서 Trigger 넣어서 했다

한번 실행되고 다시 기본자세 하면 되니까 이으면 되나? 하고 이었는데 됐다 굿

    private void Jump()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isGround == true) // 스페이스바를 눌렀을 때 && 땅에 닿았을 때
        {
            animJump.SetTrigger("isJump");
            // 자기 자신의 Rigidbody Component에 접근해서 AddForce 기능 사용
            GetComponent<Rigidbody>().AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
            // = 자기 자신의 Rigidbody에 접근해서 AddForce로 힘을 가함(위쪽으로 jumpPwer만큼 힘을 가함)
                                               // ForceMode : 지속적인 힘, 순간적인 힘
        }
    }

 

재밌었다!