일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- ability task
- gas
- attribute
- ret2libc
- map design
- rpc
- 언리얼 엔진
- local prediction
- UI
- gravity direction
- 게임 개발
- Unreal Engine
- photon fusion2
- 언리얼엔진
- animation
- Replication
- unity
- listen server
- gameplay effect
- os
- CTF
- gameplay tag
- MAC
- Multiplay
- 게임개발
- Aegis
- gameplay ability system
- 유니티
- nanite
- dirty cow
- Today
- Total
Replicated
[Unity6 Tutorial] #1 프로젝트 생성, 애셋 스토어, 유니티 물리, 유니티 생명 주기, 뉴 인풋 본문
[Unity6 Tutorial] #1 프로젝트 생성, 애셋 스토어, 유니티 물리, 유니티 생명 주기, 뉴 인풋
라구넹 2025. 3. 29. 15:41https://github.com/Lagooneng/Unity6Tutorial
GitHub - Lagooneng/Unity6Tutorial: Unity6 Tutorial
Unity6 Tutorial. Contribute to Lagooneng/Unity6Tutorial development by creating an account on GitHub.
github.com
25-1, 단국대학교 Aegis 유니티 엔진을 이용한 게임개발 4기 스터디 자료
1. 프로젝트 만들기

NewProject

Universal 2D,
Project 이름은 마음에 드는대로
Create Project
하면 생김
(폴더 설정 등등은 하고 싶은 곳에다가)

와우! 엔진이 켜졌다!
2. 유니티 애셋 다운로드
근데 문제는 뭘로 만들 것이냐..

애셋 스토어라는게 있다
들어가보자

들어가면 애셋을 사고 파는 공간이 등장

유니티 설치할 때 만들었던 ID로 로그인

Pixel Adventure 검색

왼쪽 거 누르면

이런 게 뜬다
이건 무료니까 내 에셋에 추가하기

다시 유니티로 돌아와서 My Assets 누르기

Pixel Adventure1 Download

하고 import까지

Import 누르기

그럼 Assets에 추가된다

Hierarchy에서 CreateEmpty


저 중에 Run 마우스로 잡아 끌어다가

Player에 끌어다가 붙이면 붙음

이름은 PlayerSprite로 바꿔주자

그리고 위치가 안맞을 수 있는데, 0, 0, 0으로 설정

위에 있는 플레이 버튼을 누르면 실행된다
근데 카메라가 너무 멀리 있는 거 같다!
- 단축키. 뷰포트 이동: 우클릭한 채로 이동,

카메라 누르고

Size를 1.5로 해주자
근데 플레이 버튼 누를 때마다 한참 걸린다!

Edit → Project Settings → Editor
들어가서 밑으로 쭉 내리고 저거 설정하면 빨라진다!

카메라 크기도 적당하고, 실행도 빨리 된다
3. 물리 적용
근데 게임에는 물리가 반드시 필요하다!
RigidBody2D → 유니티2D 물리 (속도, 힘 등)
BoxCollider2D → 2D 충돌 처리
이 두개를 같이 써야 함

Player를 선택하고 RigidBody2D를 누른다

근데 실행을 하니 개구리가 뚝 떨어진다
물리를 추가해서 중력이 적용되기 때문
이제 충돌 처리로 바닥을 만들어보자

저기서 풀숲 처럼 생긴 가운데를 가져와보자

단축키: w: 이동 e: 회전 r: 확대, 축소

저기에 BoxCollider 추가

근데 이대로 실행하면? Player의 충돌 판정은 없어서 떨어진다

자식에 빈 오브젝트 만들고 이름 Collision이라 설정

BoxCollider를 추가하는데, 크기가 안맞는다
(빈 오브젝트에 추가해서 그렇다. 바닥에는 스프라이트에 추가해서 자동으로 크기가 맞음)

저거 누르거나 Size, Offset을 조정해서 크기, 위치를 바꿔야 한다

이정도로 바꾼다.

4. 뉴인풋 적용해서 움직이기
근데 이제 캐릭터를 움직이고 싶다
이러면 사용자한테 인풋을 받아야 한다.
근데 왜 뉴 인풋이지?
예전 버전의 인풋이 있는데, 확장성 관련해서 문제가 있어서 새로운 인풋이 생김

Assets에서 우클릭해서 폴더 생성
이름은 Input

해당 폴더로 가서 Input Actions 생성
이름은 PlayerControlInput


들어가면 이런게 나옴
- 인풋 시스템 이름을 중간에 바꿔서 이 화면이랑 다를 수 있는데(스샷엔 그냥 Player), 파일 이름은 PlayerControlInput으로 하는게 더 이름이 적절함.
Map → 각각 상황에 맞는 입력 처리 설정 가능, InputAction 파일이랑 이름 달라야 함
Action → 어떤 행동을 할 것인가

들어가서 Player Map이랑 Actions Move 생성(이름 변경은 더블 클릭)

UpDownLeftRight 선택, 이름 MoveInput로 변경

- 하다가 이름 바꿔서 WASD로 되어 있는데, 이름을 MoveInput 으로 하는게 적절.
이제 저기에 키를 엮어줘야 함

각각 선택하고 Path를 누른 뒤 Listen, a와 같이 연결 시키고 싶은 키를 눌러주면 인식함
인식되면 저거 클릭

업, 다운은 안 쓸 거라서 냅둬두기

창 닫고 Inspector에서 C# 클래스 생성

이제 C#으로 인풋 받는 시스템이 생성되었다
이제 저걸 어떻게 플레이어에 적용 시킬까?
이제 코딩을 해야 한다.

Scripts 폴더를 만들고

들어가서 PlayerController 클래스 생성
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Rigidbody2D rb;
private PlayerControlInput inputActions;
private Vector2 inputVector;
private float moveSpeed = 5.0f;
void Awake()
{
rb = GetComponentInChildren<Rigidbody2D>();
inputActions = new PlayerControlInput();
inputActions.Player.Move.performed += ctx => inputVector = ctx.ReadValue<Vector2>();
inputActions.Player.Move.canceled += ctx => inputVector = Vector2.zero;
}
void FixedUpdate()
{
rb.linearVelocityX = inputVector.x * moveSpeed;
}
private void OnEnable()
{
inputActions.Enable();
}
private void OnDisable()
{
inputActions.Disable();
}
}
코드 설명 전, 개념 설명
유니티 생명 주기
게임 시작 → Awake() → Start() → FIxedUpdate(), Update()→ LateUpdate()
오브젝트 활성화 시 → OnEnable()
오브젝트 비활성화 시 → OnDisable()
Update()
- 입력 처리 등 (이번 예제에선 EventListener 방식이라 Update에서 이루어지지 않음)
- 매 프레임마다 호출
- → 불규칙한 호출 주기 (프레임 호출에 따라 달라짐)
FixedUpdate()
- 고정된 시간마다 호출
- 물리 연산 등 처리
LateUpdate()
- Update()가 끝나면 호출
- 후속 처리가 필요한 경우
함수
|
설명
|
Awake()
|
오브젝트가 생성되자마자 호출. 다른 컴포넌트 참조 설정에 적합.
|
OnEnable()
|
오브젝트가 활성화될 때마다 호출. 비활성→활성 될 때도 다시 호출됨.
|
Start()
|
첫 프레임 업데이트 전에 1번만 호출. 초기화 완료 후 시작할 때 사용.
|
함수
|
설명
|
Update()
|
매 프레임마다 호출. 입력 처리, 일반 로직 여기에 작성.
|
FixedUpdate()
|
고정된 간격마다 호출. 물리 연산 관련 처리 (Rigidbody 등).
|
LateUpdate()
|
모든 Update 후 호출. 카메라 따라가기 같은 후처리에 사용.
|
함수
|
설명
|
OnDisable()
|
오브젝트가 비활성화될 때 호출.
|
OnDestroy()
|
오브젝트가 삭제되기 직전에 호출. 자원 정리 등에 사용.
|
실수
|
설명
|
Start 에서 컴포넌트 참조하기
|
Awake에서 최우선적으로 초기화하고, 의존성 설정같은 걸 해주고 Start에서 본격적으로 시작하기 전에 그밖의 요소들을 초기화한다고 생각
|
물리 연산을 Update에 처리함
|
물리는 FixedUpdate에서 해야 버그 안 생김.
|
카메라 따라가기를 Update에 둠
|
LateUpdate로 옮겨야 흔들림 없다.
|
그림으로 정리

FixedUpdate가 한 프레임에 여러 번 호출되면?
while (fixedTime <= currentTime) {
FixedUpdate();
fixedTime += Time.fixedDeltaTime;
}
애초에 이런 식으로 호출되서 Update 전에 여러번 실행하게 될 수도 있고, 아닐 수도 있고 별다른 문제는 없음.
코드 설명
void Awake()
{
rb = GetComponentInChildren<Rigidbody2D>();
inputActions = new PlayerControlInput();
inputActions.Player.Move.performed += ctx => inputVector = ctx.ReadValue<Vector2>();
inputActions.Player.Move.canceled += ctx => inputVector = Vector2.zero;
}
자식 오브젝트에서 RigidBody2D를 가져오고,
인풋 액션을 생성
inputActions.Player.Move.performed
- inputActions는 Input Action Asset에서 만든 C# 클래스 인스턴스
- Player는 그 안에 정의된 Action Map.
- Move는 Player Action Map 안에 있는 Input Action.
- .performed는 입력이 실제로 발생했을 때 호출되는 이벤트
- 예: 키보드 방향키, 왼쪽 스틱 조작 등
+= ctx => inputVector = ctx.ReadValue<Vector2>();
- 람다식 이벤트 핸들러 등록
- ctx는 CallbackContext 객체로, 입력에 대한 다양한 정보를 담고 있음.
- ctx.ReadValue<Vector2>()는 입력값을 Vector2 형태로 읽는다는 뜻.
- → 방향키나 스틱 입력이면 (-1, 0) 이런 식의 방향 벡터가 나옴.
- 이걸 inputVector 변수에 저장하고 있는 것
람다식을 보면, ctx를 매개변수로 받아 inputVector = ctx.ReadValue<Vector2>()을 실행함.
언제? Move가 performed 되었을 때
cancled도 마찬가지의 방식
void FixedUpdate()
{
rb.linearVelocityX = inputVector.x * moveSpeed;
}
위에서 이벤트 리스너 방식으로 등록해놓아서 InputVector는 계속해서 알아서 업데이트됨
그 값을 FixedUpdate에서 읽고, moveSpeed랑 곱해서 속도를 결정
- 좌우로만 움직일 거라 linearVelocityX 사용
private void OnEnable()
{
inputActions.Enable();
}
private void OnDisable()
{
inputActions.Disable();
}
오브젝트가 활성화/비활성화 되었을 땐 인풋 액션을 켜주고 꺼주기
그리고 이렇게 만든 스크립트를 Player에 붙여주자

이 상태로 실행하면?
키를 누르니 움직인다!
근데, 잘 보면 움직이고 떨어지니 회전을 해버린다

그럼 RigidBody2D로 가서 Freeze Rotation 해주면 된다.
인풋 추가 설명

Input Action의 Action Properties를 살펴보자
Action
Action Type

옵션
|
설명
|
Value
|
값 기반 입력. 예: 조이스틱 위치 (Vector2), 트리거 압력 (float). → 값이 계속 변화하는 입력에 사용.
|
Button
|
누름/뗌 이벤트 처리. 예: 키보드 키, 마우스 클릭. → Pressed, Released, Held 같은 버튼 상태 감지에 적합.
|
Pass Through
|
입력을 필터링 없이 그대로 전달. → Interactions 무시됨. 복잡한 로직 없이 입력 값을 그대로 받고 싶을 때 사용. 예: 여러 입력 소스를 합칠 때.
|
- Value는 보통 연속적 데이터 처리용.→ 이동은 버튼보단 Value로 처리하는게 나음.
- → 버튼 클릭엔 적합하지 않음.
- Button은 단발성 이벤트 처리에 강함.
- → 스킬 발동 같은 거..
Contol Type
- 입력 장치에서 어떤 데이터 타입을 받을지를 지정하는 거
Control Type
|
설명
|
Any
|
어떤 타입이든 허용. 유연하지만 비권장 (명확성 떨어짐).
|
Axis
|
단일 축 입력 (-1 ~ 1) → 예: A/D 키, 좌우 방향
|
Analog
|
부드러운 연속 값 → 예: 트리거나 아날로그 스틱
|
Integer
|
정수 값 (거의 안 씀)
|
Digital
|
0 또는 1 → 버튼 입력 (누름/안 누름)
|
Double
|
고정밀 float (드물게 사용)
|
Vector2
|
2D 방향 → 예: 조이스틱, WASD 이동, 마우스 이동
|
Vector3
|
3D 방향 또는 위치 (VR 등에서 자주 씀)
|
Delta
|
변화량 정보 (마우스 이동량 등)
|
Quaternion
|
회전 정보 (3D 회전)
|
Stick
|
아날로그 스틱 (X, Y 축 포함된 복합 타입)
|
Dpad
|
방향 패드 (Up/Down/Left/Right)
|
Touch
|
터치 입력
|
Pose
|
위치 + 회전 (VR/AR)
|
Bone / Eyes
|
XR 장비 전용 – 본 위치, 시선 추적 등
|
그냥 예제에선 기본값 Any 쓰긴 했는데 Vector2로 바꾸면 좋음
목적
|
추천 Control Type
|
키보드 이동
|
Vector2
|
마우스 이동량
|
Delta
|
점프 키 입력
|
Digital
|
트리거 압력
|
Axis or Analog
|
VR 손 위치
|
Pose
|
Interactions 사용자가 버튼을 어떻게 눌렀는지에 따라 입력 조건을 세밀하게 조정
이름
|
설명
|
Hold
|
버튼을 지정된 시간 이상 누르고 있어야 입력 발생. 기본값은 0.4초. 예: 차지 공격, 장전 유지 등
|
Multi Tap
|
버튼을 빠르게 여러 번 눌렀을 때 입력 발생. 기본은 더블탭.
|
Press
|
버튼을 누를 때 발생. 기본 press 동작보다 세부 제어 가능 (press point 설정 등).
|
Slow Tap
|
버튼을 느리게 눌렀다 뗄 때 입력 발생. Tap보다 오래 눌러야 함.
|
Tap
|
버튼을 빠르게 눌렀다 뗄 때 입력 발생. 예: 회피, 점프
|
커스터마이징 가능
각 Interaction은 매개변수를 줄 수 있음
- 1초 이상 눌러야 작동 등..
주의사항
Interaction이 제대로 작동하려면 Action Type이 Button 이어야 함.
Processors
입력 값을 가공/수정해서 원하는 형태로 바꾸는 데 사용
이름
|
설명
|
Axis Deadzone
|
1D 입력의 민감도 조절. 작은 값은 무시. (예: 트리거나 방향키)
|
Clamp
|
입력 값이 일정 범위를 넘지 않도록 제한. 예: -1~1로 고정
|
Invert
|
입력 값을 반대로 뒤집음. (예: 1 → -1)
|
Invert Vector 2 / 3
|
벡터 축 단위로 반전. 예: X축만 반전 가능
|
Normalize / Normalize Vector 2 / 3
|
입력 벡터를 크기 1로 정규화 (방향만 유지, 크기 제거)
|
Scale / Scale Vector 2 / 3
|
입력 값을 곱해서 민감도 조절. 예: 2배 빠르게 이동
|
Stick Deadzone
|
아날로그 스틱의 중심 주변 미세 입력 무시. 스틱 기본 값 떠 있는 현상 제거
|
근데 Actions에 여러 종류 있던데 그건 뭔가요?

메뉴 항목
|
설명
|
Add Binding
|
단일 키나 버튼을 바로 바인딩함.
|
Add Positive/Negative Binding
|
두 키를 1D 축(+/-)으로 바인딩. 예: A(-1), D(+1) → Axis로 처리
|
Add Up/Down/Left/Right Composite
|
4방향 입력을 Vector2로 처리. WASD나 방향키 같은 이동 입력용.
|
Add Up/Down/Left/Right/Forward/Backward Composite
|
6방향 입력을 Vector3로 처리. 3D 이동 입력에 사용.
|
Add Binding With One Modifier
|
조합 키 하나를 포함한 바인딩. 예: Shift + E
|
Add Binding With Two Modifiers
|
조합 키 두 개를 포함한 바인딩. 예: Ctrl + Shift + F
|
좌 우 이동은??
- 했던 것처럼 Vector2에서 좌우만 쓰거나
- Positive, Negative Binding 하거나..