- Published on
섹션 2: 장애물 피하기 1
#전체 목차
- Unity C# 강의 2: Start와 Update 메서드 완전 정복
- 유니티 C# 강의 정리: 변수와 움직임 수정하기
- 유니티 C# 강의 정리: 변수를 직렬화하여 인스펙터에서 조작하기
- Unity 이동 시스템 강의 정리
- Time.deltaTime과 속도 조절하기
- 시네머신(Cinemachine)으로 추적 카메라 구현하기
- Cinemachine 옵션 상세 정리
- 벽 추가와 충돌 시스템 이해하기
#🎮{ Unity C# 강의 2: Start와 Update 메서드 완전 정복 }
Unity 스크립팅의 핵심인 Start와 Update 메서드의 차이점을 이해하고, 게임 오브젝트를 이동시키는 첫 번째 코드를 작성해보겠습니다.
#📋 목차
- 프로젝트 준비하기
- Start와 Update 메서드 이해하기
- Transform 컴포넌트와 Translate 메서드
- 코드 작성 실습
- 매개변수와 인수 개념
- Float와 Double 자료형
- 프레임과 게임 루프
- 실행 결과 확인하기
#🚀 프로젝트 준비하기
#1. 새 Unity 프로젝트 생성
// 프로젝트 설정
1. Unity Hub 실행
2. 새 프로젝트 (New Project) 클릭
3. Universal 3D 템플릿 선택
4. 프로젝트 이름: "Obstacle Dodge"
5. Unity Cloud 비활성화
6. Create Project 클릭
#2. 기본 게임 오브젝트 생성
// 지면 평면 생성
Hierarchy 우클릭 → 3D Object → Plane
이름을 "Ground"로 변경
// 플레이어 큐브 생성
Hierarchy 우클릭 → 3D Object → Cube
이름을 "Dodgy The Player"로 변경
#3. 프로젝트 폴더 구조 정리
// Assets 폴더에서 우클릭하여 폴더 생성
1. Materials 폴더 생성
2. Scripts 폴더 생성
#4. 머티리얼 생성 및 적용
// 지면용 어두운 머티리얼
Materials 폴더에서 우클릭 → Create → Material
이름: "Dark Color"
색상을 어둡게 설정
Smoothness를 0으로 설정 (무광 효과)
// 플레이어용 녹색 머티리얼
Materials 폴더에서 우클릭 → Create → Material
이름: "Green"
HEX 색상 코드 입력 (예: #00FF00)
#🔧 Start와 Update 메서드 이해하기
#Start 메서드의 특징
void Start()
{
// 게임이 시작될 때 한 번만 실행되는 코드
Debug.Log("게임이 시작되었습니다!");
}
Start 메서드 핵심 개념:
- 스크립트가 활성화될 때 단 한 번만 호출
- 게임 오브젝트가 씬에 존재하고 스크립트가 활성 상태일 때 실행
- 초기화 작업에 주로 사용
#Update 메서드의 특징
void Update()
{
// 매 프레임마다 실행되는 코드
Debug.Log("매 프레임마다 실행됩니다!");
}
Update 메서드 핵심 개념:
- 매 프레임마다 호출되는 메서드
- 게임이 실행되는 동안 지속적으로 반복 실행
- 움직임, 입력 처리, 상태 변화 등에 사용
#프레임(Frame)이란?
// 프레임의 개념
1프레임 = 게임이 화면을 한 번 갱신하는 단위
초당 60프레임 (60 FPS) = 1초에 60번 화면 갱신
초당 30프레임 (30 FPS) = 1초에 30번 화면 갱신
프레임이 높을수록 → 더 부드러운 움직임
프레임이 낮을수록 → 끊어지는 듯한 움직임
#🎯 Transform 컴포넌트와 Translate 메서드
#Transform 컴포넌트 이해하기
// Transform 컴포넌트는 모든 게임 오브젝트가 가지는 기본 컴포넌트
Transform 컴포넌트의 구성 요소:
- Position (위치): X, Y, Z 좌표
- Rotation (회전): X, Y, Z 축 회전값
- Scale (크기): X, Y, Z 축 크기 비율
#점 연산자(Dot Operator) 개념
// 점 연산자(.)의 의미
transform.Translate();
// ^
// 이 점이 "점 연산자"
// 의미: transform이 가지고 있는 기능들에 접근하겠다는 뜻
transform.position; // 위치에 접근
transform.rotation; // 회전에 접근
transform.localScale; // 크기에 접근
transform.Translate(); // 이동 함수 호출
#Translate 메서드 상세 분석
// Translate 메서드의 기본 구조
transform.Translate(x, y, z);
// 각 매개변수의 의미
x: X축 이동량 (좌우 이동)
y: Y축 이동량 (상하 이동)
z: Z축 이동량 (앞뒤 이동)
#💻 코드 작성 실습
#1. Mover 스크립트 생성
// Scripts 폴더에서 우클릭
Create → C# Script
이름: "Mover"
// 중요한 주의사항
파일 이름과 클래스 이름이 일치해야 함!
다른 곳을 클릭하기 전에 반드시 이름을 변경할 것!
#2. 스크립트를 게임 오브젝트에 연결
// 방법 1: 드래그 앤 드롭
Mover 스크립트를 Dodgy The Player 오브젝트로 드래그
// 방법 2: Add Component 사용
1. Dodgy The Player 선택
2. Inspector에서 Add Component 클릭
3. "Mover" 검색 후 선택
// 방법 3: Inspector에 직접 드래그
1. Dodgy The Player 선택
2. Mover 스크립트를 Inspector 빈 공간에 드래그
#3. Start 메서드에서 이동 코드 작성
using UnityEngine;
public class Mover : MonoBehaviour
{
void Start()
{
// 게임 시작 시 한 번만 이동
transform.Translate(1, 0, 0);
}
void Update()
{
// 현재는 비어있음
}
}
코드 실행 결과:
- 게임 시작 시 오브젝트가 X축으로 1만큼 이동
- 한 번만 실행되므로 순간적으로 이동
#4. Update 메서드로 코드 이동
using UnityEngine;
public class Mover : MonoBehaviour
{
void Start()
{
// 비어있음
}
void Update()
{
// 매 프레임마다 이동
transform.Translate(1, 0, 0);
}
}
코드 실행 결과:
- 매 프레임마다 X축으로 1만큼 이동
- 매우 빠르게 이동하여 화면 밖으로 사라짐
#📊 매개변수와 인수 개념
#매개변수(Parameter)와 인수(Argument)
// 메서드 정의에서는 "매개변수"
void Translate(float x, float y, float z)
{
// x, y, z는 매개변수(Parameter)
}
// 메서드 호출에서는 "인수"
transform.Translate(1, 0, 0);
// ↑ ↑ ↑
// 인수(Argument)
개념 정리:
- 매개변수: 함수를 정의할 때 사용하는 변수
- 인수: 함수를 호출할 때 전달하는 실제 값
#Transform.Translate의 매개변수
// Translate 메서드의 매개변수 상세
transform.Translate(x, y, z);
// 각 매개변수의 역할
float x: X축 이동량 (양수 = 오른쪽, 음수 = 왼쪽)
float y: Y축 이동량 (양수 = 위쪽, 음수 = 아래쪽)
float z: Z축 이동량 (양수 = 앞쪽, 음수 = 뒤쪽)
// 예시
transform.Translate(1, 0, 0); // 오른쪽으로 1만큼
transform.Translate(-1, 0, 0); // 왼쪽으로 1만큼
transform.Translate(0, 1, 0); // 위쪽으로 1만큼
transform.Translate(0, 0, 1); // 앞쪽으로 1만큼
#🔢 Float와 Double 자료형
#소수점 숫자의 자료형
// Double과 Float의 차이
double number1 = 0.01; // 높은 정밀도 (64비트)
float number2 = 0.01f; // 일반 정밀도 (32비트)
// Unity에서는 주로 float 사용
// float 표기법: 숫자 뒤에 'f' 붙이기
#자료형 변환 오류 해결
// 오류가 발생하는 코드
transform.Translate(0.01, 0, 0);
// 오류 메시지: "cannot convert double to float"
// 올바른 코드
transform.Translate(0.01f, 0f, 0f);
// 또는
transform.Translate(0.01f, 0, 0); // 정수는 자동 변환됨
float 사용 이유:
- Unity는 성능상 float를 선호
- 게임 개발에서는 극도의 정밀도가 필요하지 않음
- 메모리 사용량이 적음
#⚡ 프레임과 게임 루프
#게임 루프의 개념
// 게임 루프의 기본 구조
while (게임이 실행 중)
{
1. 입력 처리
2. 게임 로직 실행 (Update 호출)
3. 렌더링 (화면에 그리기)
4. 다음 프레임으로
}
#프레임 속도에 따른 이동 차이
// 문제가 있는 코드
void Update()
{
transform.Translate(1f, 0f, 0f); // 매 프레임마다 1만큼 이동
}
// 문제점:
// 60 FPS: 1초에 60만큼 이동
// 30 FPS: 1초에 30만큼 이동
// → 프레임 속도에 따라 이동 속도가 달라짐!
#적절한 이동 속도 설정
void Update()
{
// 느린 이동을 위해 작은 값 사용
transform.Translate(0.01f, 0f, 0f);
}
// 더 나은 방법 (시간 기반 이동)
void Update()
{
float speed = 5f; // 초당 5 유닛 이동
transform.Translate(speed * Time.deltaTime, 0f, 0f);
}
#🎮 실행 결과 확인하기
#카메라 위치 조정
// 게임 뷰에서 오브젝트를 잘 보기 위한 카메라 설정
1. Main Camera 선택
2. F키를 눌러 오브젝트에 포커스
3. 마우스 휠로 줌 조정
4. E키 + 마우스 드래그로 카메라 회전
#Start 메서드 실행 결과
void Start()
{
transform.Translate(1f, 0f, 0f);
}
// 결과:
// - 게임 시작 시 순간적으로 오른쪽으로 이동
// - 한 번만 실행되므로 이후 정지
// - Transform의 X Position이 0에서 1로 변경됨
#Update 메서드 실행 결과
void Update()
{
transform.Translate(0.01f, 0f, 0f);
}
// 결과:
// - 매 프레임마다 조금씩 오른쪽으로 이동
// - 부드럽고 지속적인 움직임
// - 게임을 정지할 때까지 계속 이동
#🔍 디버깅과 문제 해결
#자주 발생하는 실수들
// 실수 1: 저장하지 않고 실행
// 해결: Ctrl+S로 스크립트 저장 후 Unity로 돌아가기
// 실수 2: 세미콜론 누락
transform.Translate(1f, 0f, 0f) // 오류!
transform.Translate(1f, 0f, 0f); // 올바름
// 실수 3: 스크립트 연결 안 함
// 해결: 스크립트를 게임 오브젝트에 반드시 연결
// 실수 4: 컴파일 오류 무시
// 해결: Console 창에서 오류 메시지 확인 및 수정
#Transform 값 확인하기
// Inspector에서 Transform 값 실시간 확인
게임 실행 중 → Inspector → Transform → Position 값 관찰
// 코드로 현재 위치 출력
void Update()
{
transform.Translate(0.01f, 0f, 0f);
Debug.Log("현재 위치: " + transform.position);
}
#📚 핵심 개념 정리
#Start vs Update 비교표
| 구분 | Start | Update |
|---|---|---|
| 호출 빈도 | 한 번만 | 매 프레임 |
| 사용 용도 | 초기화 | 지속적 작업 |
| 실행 시점 | 게임 시작 시 | 게임 실행 중 |
| 예시 용도 | 변수 설정, 컴포넌트 가져오기 | 이동, 입력 처리, 상태 변경 |
#Transform.Translate 문법
// 기본 문법
transform.Translate(x, y, z);
// 실제 사용 예시
transform.Translate(1f, 0f, 0f); // 오른쪽 이동
transform.Translate(-1f, 0f, 0f); // 왼쪽 이동
transform.Translate(0f, 1f, 0f); // 위쪽 이동
transform.Translate(0f, -1f, 0f); // 아래쪽 이동
transform.Translate(0f, 0f, 1f); // 앞쪽 이동
transform.Translate(0f, 0f, -1f); // 뒤쪽 이동
#C# 기본 문법 요소
// 세미콜론: 문장의 끝을 표시
Debug.Log("Hello");
// 점 연산자: 객체의 멤버에 접근
transform.position;
// 괄호: 메서드 호출 시 인수 전달
Translate(1f, 0f, 0f);
// 중괄호: 코드 블록 정의
void Start()
{
// 이 안의 코드들이 하나의 블록
}
#🚀 다음 단계 미리보기
다음 강의에서는 다음 내용들을 학습할 예정입니다:
- Time.deltaTime을 활용한 프레임 독립적 이동
- Input 시스템을 이용한 플레이어 조작
- 변수(Variables) 사용법
- 조건문(if) 기초
- 충돌 감지(Collision Detection) 기초
#{ 🎮 유니티 C# 강의 정리: 변수와 움직임 수정하기 }
#📋 목차
#1. 변수란 무엇일까?
- 변수는 정보를 저장하는 상자 같은 것.
- 예:
- 이름:
hitPoints - 값:
20 - 의미: 체력(HP) 20이라는 정보가 들어 있음.
- 이름:
➡️ 값은 바뀔 수 있음 → 체력팩을 먹으면 증가, 적 공격을 받으면 감소.
#2. 변수의 자료형
변수는 데이터의 종류(타입) 에 따라 나뉩니다.
int (정수)
- 예:
int hitPoints = 20;
- 예:
float (소수점 있는 숫자)
- 예:
float speed = 0.01f; - 뒤에
f를 붙여야 함.
- 예:
bool (참/거짓)
- 예:
bool isAlive = true; - 흔히
isSomething형태로 이름 짓기 (isAlive,isEnemy).
- 예:
string (문자열: 글자 묶음)
- 예:
string name = "Rick";
- 예:
#3. 변수 선언 규칙
자료형 → 변수명 → 값 → 세미콜론(;)
int hitPoints = 20; float moveSpeed = 0.05f; bool isAlive = true; string playerName = "Rick";이름 규칙:
- 첫 글자는 소문자
- 이어지는 단어 첫 글자는 대문자 (camelCase)
- 예:
hitPoints,moveSpeed
#4. Mover.cs에 변수 적용하기
원래는 이렇게 작성했음 👇 (숫자를 직접 넣음 → 하드 코딩)
transform.Translate(0.01f, 0f, 0f);
변수로 바꾸면 👇
float xValue = 0.01f;
transform.Translate(xValue, 0f, 0f);
➡️ 이제 xValue만 수정하면 이동 속도가 바뀜.
#5. 하드 코딩 vs 변수 사용
- 하드 코딩: 숫자를 직접 넣는 방식. (나중에 수정하기 어려움)
- 변수 사용: 한 번만 수정해도 여러 곳에 적용 가능.
예:
xValue를 0.01 → 0.05로 바꾸면,- 코드 전체에서 자동으로 적용됨.
#6. 도전 과제: 공중으로 이동시키기
#🎯 과제
yValue,zValue변수를 추가- X축이 아닌 Y축 방향(공중) 으로만 이동시키기
#📝 코드 예시
float xValue = 0f;
float yValue = 0.05f;
float zValue = 0f;
void Update()
{
transform.Translate(xValue, yValue, zValue);
}
➡️ 실행하면 플레이어가 공중으로 곧바로 올라감 🚀
#7. 정리
- 변수는 정보를 담는 상자
- C#에서 자주 쓰는 자료형:
int,float,bool,string - 변수를 사용하면 코드 관리가 쉬워지고, 수정도 간편함
- 이번 실습:
xValue,yValue,zValue변수를 만들어 플레이어 이동 방향을 제어함
👉 이렇게 변수 개념을 배우고 실습하면, 앞으로 더 복잡한 프로젝트에서도 효율적인 코드 작성이 가능해집니다.
#{ 🎮 유니티 C# 강의 정리: 변수를 직렬화하여 인스펙터에서 조작하기 }
#📋 목차
#1. 플레이 모드 설정 최적화
문제: 유니티에서 재생 버튼(▶)을 누르면 매번 도메인/씬이 다시 로드됨 → 기다려야 해서 불편함.
해결 방법:
- 메뉴에서 Edit → Project Settings → Editor로 이동
- Enter Play Mode Settings에서
- Reload Domain
- Reload Scene
체크 해제 가능 - Do not reload Domain or Scene*
효과: 재생할 때마다 불필요한 초기화 과정이 줄어듦.
#2. 직렬화란 무엇일까?
- 직렬화(Serialize): 변수를 코드 안에만 두는 것이 아니라, 유니티 인스펙터(Inspector) 창에서도 볼 수 있고, 수정할 수 있도록 만드는 것.
- 왜 필요할까?
- 코드 → 수정 → 저장 → 다시 실행 → 확인 … 이 과정을 매번 반복하기 번거롭기 때문.
- 직렬화를 하면 인스펙터에서 값을 바로 수정하면서 실험할 수 있음.
#3. 변수를 직렬화하는 방법
float yValue = 0.001f;라는 변수가 있을 때,앞에
[SerializeField]를 붙이면 됨:[SerializeField] float yValue = 0.001f;이렇게 하면 스크립트 코드에는 기본값이 남아 있고,
유니티 인스펙터에서 해당 값을 직접 조정할 수 있음.
#4. 인스펙터에서 변수 조작하기
직렬화된 변수를 인스펙터에서 보면 슬라이더/숫자 입력칸으로 나타남.
장점:
- 실시간으로 값을 바꿔보고, 플레이하면서 결과를 확인 가능.
0.001 → 0.123 → -0.001같은 값 변경을 코드 수정 없이 바로 테스트 가능.
주의할 점:
- 인스펙터에서 값을 바꿔도 원본 코드 값은 변하지 않음.
- 즉, 코드에는 여전히
0.001이 남아 있음.
#5. 도전 과제: 플레이어 이동 제어하기
#🎯 과제
세 개의 변수를 모두 직렬화해서 인스펙터에서 접근 가능하게 만들기.
[SerializeField] float xValue = 0f; [SerializeField] float yValue = 0f; [SerializeField] float zValue = 0f;플레이 모드에서 플레이어가 카메라에서 멀어졌다가 다시 돌아오게 해보기.
#📝 예시 코드
[SerializeField] float xValue = 0.005f;
[SerializeField] float yValue = 0f;
[SerializeField] float zValue = 0f;
void Update()
{
transform.Translate(xValue, yValue, zValue);
}
- X값을 양수로 → 카메라에서 멀어짐
- X값을 음수로 → 카메라 쪽으로 돌아옴
➡️ 인스펙터에서 값을 실시간으로 조정하면 캐릭터 움직임을 바로 확인 가능.
#6. 정리
- 플레이 모드 설정 최적화: 불필요한 도메인/씬 리로드를 줄여서 빠르게 테스트 가능.
- 직렬화(SerializeField): 변수를 인스펙터에서 조작 가능하게 만듦.
- 장점: 코드 수정 없이 실시간 값 조절 & 테스트 가능.
- 실습: X, Y, Z 변수를 직렬화하여 플레이어가 카메라에서 멀어졌다가 다시 돌아오도록 구현.
👉 다음 강의에서는 키보드 입력을 활용해 직접 플레이어를 조종하는 방식으로 발전시켜 나갑니다.
#{ 📌 C# 포맷 원칙 정리 (Unity Mover 스크립트 예제 기반) }
#1. 주석 (Comment)
정의: 코드 실행에는 영향을 주지 않는 메모.
//뒤에 작성.용도:
- 6개월 뒤에 코드를 다시 보더라도 “내가 여기서 뭘 하려고 했지?”라는 질문에 답할 수 있도록 설명을 남김.
- 코드의 의도를 보충 설명.
주의점:
- “주석을 쓰지 말라”는 의견도 있음 → 코드 자체가 잘 읽히도록 이름을 명확하게 짓는 것이 이상적.
- 그러나 초보자라면 주석을 활용해도 좋음 → 학습 과정에서 유용.
#2. 공백 (Whitespace)
코드 실행에는 영향 없음.
→ 가독성을 높이기 위한 용도로 사용.예외: 단어를 잘못 쪼개면 오류 발생
- ✅
float yValue;(정상) - ❌
flo at yValue;(오류)
- ✅
IDE 도움:
- 잘못된 경우 빨간 물결선(에러 표시)이 나타남.
- 빨간 줄이 없다면 문법적으로 문제 없음.
#3. 중괄호 `{ }`와 들여쓰기
중괄호의 역할: 코드 블록(Block)의 시작과 끝을 정의.
스타일 차이:
void Update() { // 보통 이렇게 씀 }또는
void Update() { // 이렇게도 가능 }→ 기능적으로는 동일, 팀 스타일 가이드에 맞추는 것이 중요.
들여쓰기:
- 중괄호 안에 들어가면 한 칸 들여쓰기.
- 블록이 중첩될수록 단계적으로 들여쓰기.
#4. 클래스와 메소드의 중괄호 구조
클래스:
- 예:
class Mover { ... } - 클래스는 스크립트의 큰 틀. (Mover, Shooter, Explosion 등)
- 클래스 안에 변수, 메소드가 포함됨.
- 예:
메소드:
- 예:
void Start() { ... },void Update() { ... } - 각각의 메소드가 독립된 블록을 가짐.
- 특정 블록 안에서 선언된 것들은 다른 블록이 자동으로 알지 못함.
- 예:
#5. 변수와 스코프(Scope)
클래스 레벨 변수:
x,y,z같이 클래스 안에 선언된 변수는 여러 메소드에서 공유 가능.
메소드 안 변수:
- 특정 메소드 블록
{ }안에 선언된 변수는 그 메소드 안에서만 사용 가능.
- 특정 메소드 블록
중요한 점:
Update()가 실행될 때,x,y,z의 최신 값을 가져와 움직임에 반영해야 함.- 컨트롤러 입력을 받아 변수를 변경하면,
Update()에서 이를 알아야 캐릭터를 움직일 수 있음.
#6. 다음 강의 예고
- 목표:
Update()가 입력(왼쪽/오른쪽 이동 등)을 감지하고- 이를 바탕으로 캐릭터 이동이 가능하도록 구현.
✅ 정리 포인트:
- 주석 → 메모 용도 (초보자는 적극 활용해도 OK)
- 공백 → 가독성용 (문법만 깨지 않으면 자유롭게)
- 중괄호
{ }→ 코드 블록을 구분 (들여쓰기로 가독성 유지) - 클래스와 메소드 구조 → 스코프 개념 이해 필수
- 변수는 어디에 선언되었는지에 따라 접근 가능 범위 달라짐
#{ 🎮 Unity 이동 시스템 강의 정리 }
이 강의에서는 구 입력 시스템(Input Manager) 을 사용하여
키보드 입력으로 오브젝트를 움직이는 방법을 배웁니다.
#📋 목차
- 프로젝트 준비하기
- 구 입력 시스템과 신 입력 시스템
- Start와 Update 메서드
- 위치 이동 방법: 직접 변경 vs 물리 힘
- Input Manager와 축(Axis)
- 코드 작성 과정
- 실행 결과
- 다음 단계 예고
#1. 프로젝트 준비하기
- 이번 프로젝트에서는 간단한 이동 장면을 구현합니다.
- 오브젝트를 왼쪽, 오른쪽, 위, 아래로 움직일 수 있도록 합니다.
#2. 구 입력 시스템과 신 입력 시스템
- 구 입력 시스템(Input Manager)
- 오래된 방식이지만 간단하고 배우기 쉽습니다.
- 빠르게 결과를 보고 싶을 때 유용합니다.
- 신 입력 시스템(Input System)
- 최근에 추가된 새로운 방식.
- 더 강력하고 다양한 기능 제공.
- 이번 강의에서는 구 입력 시스템을 사용합니다.
#3. Start와 Update 메서드
Start(): 게임 시작 시 한 번만 실행됩니다.Update(): 매 프레임마다 실행됩니다.- 키보드 입력은 매 순간 바뀌므로
Update()안에서 확인해야 합니다.
- 키보드 입력은 매 순간 바뀌므로
#4. 위치 이동 방법: 직접 변경 vs 물리 힘
- Unity에서 오브젝트를 움직이는 방법은 크게 두 가지가 있습니다.
- 직접 위치 변경
- x, y, z 값을 직접 바꿔서 이동.
- 단순하고 빠름.
- 물리 힘 적용
- Rigidbody에 힘(force)을 가해 움직임.
- 중력, 마찰 같은 물리 효과를 함께 사용 가능.
- 직접 위치 변경
- 강의에서는 직접 위치 변경 방법을 사용합니다.
#5. Input Manager와 축(Axis)
- Edit → Project Settings → Input Manager 에서 확인 가능.
Horizontal(좌우)- A 키 → -1
- D 키 → +1
- 방향키 좌/우 → 동일 동작
Vertical(상하)- W 키 → +1
- S 키 → -1
- 방향키 상/하 → 동일 동작
- 입력값은 -1 ~ 1 사이의 부드러운 값을 가집니다.
#6. 코드 작성 과정
Update()안에서 키보드 입력을 받습니다.Input.GetAxis("Horizontal")→ 좌우 움직임 값 가져오기Input.GetAxis("Vertical")→ 위/아래 움직임 값 가져오기transform.Translate(x, y, z)로 위치 이동
using UnityEngine;
public class Mover : MonoBehaviour
{
void Update()
{
float xValue = Input.GetAxis("Horizontal"); // 좌우
float yValue = 0f; // 위로는 이동 안 함
float zValue = Input.GetAxis("Vertical"); // 앞뒤
transform.Translate(xValue, yValue, zValue);
}
}
#7. 실행 결과
- ▶️ 실행 후 A/D 키 또는 좌우 화살표 → 오브젝트가 좌우로 이동
- W/S 키 또는 상하 화살표 → 오브젝트가 앞뒤로 이동
- 현재는 속도가 매우 빠르며, 자연스러운 이동은 다음 단계에서 다룹니다.
#8. 다음 단계 예고
Time.deltaTime을 사용해 프레임 속도와 상관없는 일정한 움직임 구현.- 이동 속도를 조절할 수 있는 변수(
speed) 추가.
✅ 이번 강의 핵심 정리
- 구 입력 시스템(Input Manager)을 사용.
Horizontal→ 좌우 입력,Vertical→ 위/아래 입력.Update()안에서Input.GetAxis()로 입력을 감지.transform.Translate()로 오브젝트를 이동.
#{ 🎮 Time.deltaTime과 속도 조절하기 }
이번 강의에서는 Time.deltaTime과 변수를 사용해 플레이어가 컴퓨터 성능(빠른 PC, 느린 노트북 등)에 상관없이 일관된 속도로 움직이도록 만드는 방법을 배웁니다.
#📋 목차
#1. 프로젝트 준비하기
- 플레이어 오브젝트를 이동시키는 스크립트를 작성합니다.
Update()메서드를 사용해 키 입력에 따라 캐릭터를 움직이게 만듭니다.
#2. 프레임과 게임 루프
게임은 프레임 단위로 실행됩니다.
FPS(Frame Per Second, 초당 프레임 수): 컴퓨터 성능에 따라 달라집니다.
- 빠른 컴퓨터 → FPS 150
- 느린 컴퓨터 → FPS 30
문제점:
Update()는 프레임마다 실행되므로, FPS가 다르면 같은 코드라도 속도가 달라져 버립니다.
#3. Update 메서드와 문제점
예시: 키를 눌렀을 때
transform.Translate(1, 0, 0);이라고 하면- FPS 150 → 1초에 150번 이동 → 엄청 빠르게 움직임
- FPS 30 → 1초에 30번 이동 → 느리게 움직임
따라서 FPS가 다른 컴퓨터에서는 플레이어 속도가 제각각 달라지는 문제가 발생합니다.
#4. Time.deltaTime 개념
Time.deltaTime: 이전 프레임과 현재 프레임 사이에 걸린 시간(초 단위)예시:
- FPS 10 →
deltaTime = 0.1초 - FPS 100 →
deltaTime = 0.01초
- FPS 10 →
코드에
* Time.deltaTime을 곱해주면 → 프레임 속도에 상관없이 일정한 속도를 유지할 수 있습니다.
#5. 속도 조절을 위한 변수 선언
- 단순히
Time.deltaTime만 쓰면 너무 느리거나 빠를 수 있음. - 따라서 **속도 변수(moveSpeed)**를 만들어 원하는 대로 조절합니다.
- 변수 선언 방법:
[SerializeField] float moveSpeed = 10f;
SerializeField→ Unity 인스펙터 창에서 값을 직접 조절할 수 있도록 함.
#6. 코드 작성 실습
using UnityEngine;
public class Mover : MonoBehaviour
{
[SerializeField] float moveSpeed = 10f;
void Update()
{
float xValue = Input.GetAxis("Horizontal") * Time.deltaTime * moveSpeed;
float zValue = Input.GetAxis("Vertical") * Time.deltaTime * moveSpeed;
transform.Translate(xValue, 0, zValue);
}
}
Input.GetAxis("Horizontal")→ -1(왼쪽), 0(안눌림), 1(오른쪽)Input.GetAxis("Vertical")→ -1(뒤), 0(안눌림), 1(앞)Time.deltaTime→ 프레임 보정moveSpeed→ 속도 조절 가능
#7. 실행 결과 확인하기
moveSpeed = 10→ 기본 속도moveSpeed = 3→ 느리게 이동moveSpeed = 23→ 빠르게 이동- 장점:
- 빠른 PC, 느린 PC에서 모두 동일한 속도로 움직임
- 원하는 대로 속도 조절 가능
👉 이제 플레이어 이동은 프레임 독립적이 되어서, 어떤 환경에서도 일관되게 동작합니다.
#{ 🎥 시네머신(Cinemachine)으로 추적 카메라 구현하기 }
#📋 목차
- 왜 카메라가 필요할까?
- 시네머신(Cinemachine)이란?
- 프로젝트 준비하기
- 가상 카메라(Virtual Camera) 추가하기
- 플레이어 추적 설정하기
- 카메라 위치와 회전 조정하기
- Damping(감쇠) 이해하기
- 마무리와 응용
#1. 왜 카메라가 필요할까?
- 유니티 씬(Scene)에는 기본적으로 메인 카메라가 있음.
- 하지만 플레이어가 이동할 때 기본 카메라는 따라오지 않음 → 쉽게 화면 밖으로 벗어남.
- 따라서 플레이어를 자동으로 따라오는 추적 카메라가 필요함.
#2. 시네머신(Cinemachine)이란?
유니티에서 제공하는 무료 패키지.
기능:
- 여러 카메라를 쉽게 관리 (컷신, 전투, 달리기 등 상황별 카메라 전환 가능).
- 카메라 움직임(위치, 회전, 추적, 줌 등)을 코드 없이 설정 가능.
핵심 컴포넌트:
- Cinemachine Brain → 메인 카메라에 붙음, 어떤 가상 카메라를 보여줄지 결정.
- Virtual Camera → 실제로 플레이어를 따라다니거나 특정 연출을 담당.
#3. 프로젝트 준비하기
- 상단 메뉴 →
Window > Package Manager열기. Unity Registry에서 Cinemachine 검색.Install클릭 → 설치 완료 후 Project에 패키지 추가됨.
#4. 가상 카메라(Virtual Camera) 추가하기
Hierarchy(계층창)에서 우클릭 → Cinemachine → Virtual Camera 선택.생성된 Virtual Camera는
Main Camera바로 아래로 이동.- 이유: Main Camera는 화면 출력을 담당, Virtual Camera는 동작 설정 담당.
Main Camera에 자동으로 Cinemachine Brain이 추가됨.
#5. 플레이어 추적 설정하기
Virtual Camera 선택.
Inspector → Follow(Target) 에 플레이어 GameObject 드래그.
- 카메라가 플레이어를 따라감.
필요하다면 Look At(Target) 도 플레이어로 설정.
- 카메라가 항상 플레이어를 바라보게 됨.
#6. 카메라 위치와 회전 조정하기
Virtual Camera Inspector →
Body와Aim설정 가능.자주 쓰는 설정:
- Follow : 단순히 플레이어 따라오기.
- Third Person Follow : 3인칭 시점처럼 따라오기.
- Hard Look At : 항상 플레이어를 바라보게 하기.
Follow Offset 값 조절:
- Y값 ↑ : 카메라를 위로 올려 내려다보는 느낌.
- Z값 ± : 카메라를 앞뒤로 움직여 거리 조절.
#7. Damping(감쇠) 이해하기
플레이어가 움직일 때 카메라가 즉시 따라오지 않고 부드럽게 따라오는 효과.
Damping 값 조절:
- 0 → 카메라가 즉시 따라옴 (딱딱한 느낌).
- 값이 클수록 → 카메라가 천천히 따라옴 (부드럽지만 약간 지연됨).
보통
0.1 ~ 0.3사이 값이 자연스러움.
#8. 마무리와 응용
이제 플레이어가 이동할 때 카메라가 자연스럽게 따라옴.
이후에는 상황에 따라 여러 Virtual Camera를 만들어 전환 가능:
- 달리기 전용 카메라
- 컷신 전용 카메라
- 전투 전용 카메라
이번 강의는 Cinemachine의 기초 (추적 카메라 구현)에 집중.
👉 정리:
- Cinemachine 설치 → Virtual Camera 추가 → 플레이어 Follow 설정 → 위치/회전 조정 → Damping으로 부드러운 움직임 → 추적 카메라 완성 ✅
#{ 🎥 Cinemachine 옵션 상세 정리 }
#📋 목차
-
- Hard Lock To Target
- Follow
- Third Person Follow
-
- Hard Look At
- Do Nothing
#1. 🎛 Cinemachine Brain
위치: Main Camera에 자동으로 붙음.
역할: 여러 개의 Virtual Camera 중 "어떤 카메라를 현재 보여줄지" 결정.
동작 방식:
- Virtual Camera 1이 활성화되면 → Brain이 화면에 그것을 출력.
- Virtual Camera 2가 켜지면 → Brain이 자연스럽게 전환.
👉 강의에서는 Virtual Camera 하나만 사용하므로 복잡한 전환은 없음.
#2. 🎥 Virtual Camera
- 실제 카메라 움직임과 동작을 담당.
- 플레이어를 따라다니거나 특정 구도를 잡는 역할.
- Brain은 Virtual Camera가 만든 "화면"을 가져와 보여줄 뿐임.
#3. 🎯 Follow / Look At (추적 & 바라보기)
- Follow: 카메라가 대상(플레이어)을 따라다님.
- Look At: 카메라가 항상 대상(플레이어)을 바라봄.
👉 둘 다 플레이어를 드래그 앤 드롭으로 넣으면 됨.
- Follow만 넣으면 → 카메라가 따라다니긴 하지만 바라보지는 않을 수 있음.
- Look At만 넣으면 → 카메라가 바라보지만 따라오진 않음.
- 보통 둘 다 설정해야 원하는 “추적 카메라” 완성.
#4. 🧩 Body 옵션
카메라의 위치(어디에 있을지) 를 결정하는 기능.
강의에서 실험했던 것들 정리해보면:
#① Hard Lock To Target
- 카메라가 대상에 딱 붙어서 고정됨.
- 마치 대상 위에 GoPro 카메라를 붙인 것 같은 느낌.
- 단점: 너무 가까워서 전체 화면을 보기 힘듦.
#② Follow
- 카메라가 대상을 따라가되, 일정한 오프셋(거리/위치 차이)을 유지.
- 가장 기본적인 추적 방식.
- Follow Offset으로 거리/높이/각도를 조정 가능.
#③ Third Person Follow
- 3인칭 시점 게임(예: GTA, 배틀로얄 게임)에 많이 사용.
- 캐릭터 뒤쪽 위에서 따라다님.
- 기본 Follow보다 자연스러운 시야 제공.
- 단, 캐릭터에 너무 가까워질 수 있어 조정 필요.
#5. 🎯 Aim 옵션
카메라의 회전(어디를 볼지) 를 결정하는 기능.
#① Hard Look At
- 대상(플레이어)을 항상 바라봄.
- 캐릭터가 어디로 움직이든 카메라가 시선을 맞춤.
- 강의에서는 이걸 사용 → 카메라가 항상 플레이어를 보게 만듦.
#② Do Nothing
- 카메라가 바라보는 방향을 따로 지정하지 않음.
- 수동으로 회전 설정해야 할 때 사용.
#6. 📐 Follow Offset
카메라와 대상 사이의 거리/높이/앞뒤 간격을 조절하는 값.
(X, Y, Z) 값으로 조정:
- X: 좌우로 이동 (왼쪽/오른쪽 카메라 위치).
- Y: 높이 (올리면 내려다보는 느낌).
- Z: 앞뒤 거리 (플레이어와 카메라 사이 간격).
강의에서:
- Y값 올려서 → 카메라를 위로 올림.
- Z값 조절해서 → 가까운 뷰 ↔ 멀리서 보는 뷰 변경.
#7. 🌀 Damping (감쇠)
- 카메라가 대상(플레이어)을 따라갈 때 지연 시간을 주어 자연스럽게 움직이게 함.
- 3가지 축(X, Y, Z) 각각에 적용 가능.
예시:
- 0 → 즉각 반응 (딱딱하고 로봇 같은 느낌).
- 0.2 → 살짝 지연, 부드럽고 자연스러움 (보통 많이 사용).
- 10 이상 → 카메라가 너무 늦게 따라와서 플레이어가 화면 밖으로 벗어나기도 함.
👉 강의에서는 0.2 정도로 조정해서 적절한 추적 효과를 만듦.
#8. 💡 응용 예시
- 탑다운 게임: Y값 크게 올려서 위에서 내려다보는 느낌.
- 3인칭 RPG: Third Person Follow + Z값 뒤로 멀리 설정.
- 컷신: 여러 Virtual Camera를 배치해서 상황마다 전환.
- 레이싱 게임: Follow + 낮은 Y값, 뒤쪽 Z값 크게 해서 차량 뷰 연출.
✅ 정리하면:
- Body → 카메라 위치를 결정.
- Aim → 카메라 회전을 결정.
- Follow Offset → 거리·각도 조정.
- Damping → 움직임의 부드러움.
#{ 🚧 벽 추가와 충돌 시스템 이해하기 }
#📋 목차
- 플레이 영역 설정하기
- 벽(Obstacle) 만들고 배치하기
- 재질(Material) 적용해서 색상 변경하기
- 오브젝트 정리와 그룹화
- Collider(콜라이더) 이해하기
- Rigidbody(리지드바디) 이해하기
- Constraints(제약) 옵션 사용하기
- Collider 편집과 Trigger 기능
#1. 플레이 영역 설정하기
- 게임이 진행될 바닥 평면의 크기를 설정해요.
- 너무 크면 장애물을 많이 배치해야 하고, 너무 작으면 재미가 줄어요.
- 예시: 바닥 크기를
(3.5, 3.5, 3.5)로 정리해서 깔끔하게 맞춤. - Y값은 두께가 없는 평면이라서 사실상 영향 없음.
#2. 벽(Obstacle) 만들고 배치하기
- **Cube(큐브)**를 이용해서 장애물이나 벽을 만듦.
- 이름을
Obstacle 1, Obstacle 2...또는Wall 1, Wall 2...로 정리하면 관리하기 편함. Ctrl + D→ 오브젝트 복제.W→ 이동,R→ 크기 조절,E→ 회전.- 벽은 플레이 영역 가장자리를 둘러싸도록 배치해야 플레이어가 밖으로 못 나감.
#3. 재질(Material) 적용해서 색상 변경하기
Assets → Create → Material
색상(Color)과 **Smoothness(매끄러움)**을 조절할 수 있음.
벽을 다른 색으로 칠해 구분하기 쉽게 만들 수 있음.
- 예시: 벽을 어두운 파란색으로 설정.
Material을 오브젝트에 드래그해서 적용 가능.
#4. 오브젝트 정리와 그룹화
- 많은 오브젝트가 생기면 계층(Hierarchy) 창이 복잡해짐.
- 빈 오브젝트(GameObject → Create Empty)를 만들고 이름을
Environment로 변경. - 벽과 장애물을 모두 선택해서
Environment에 넣으면 깔끔하게 그룹화 가능. - Hierarchy에서 그룹을 접었다 펼 수 있어 관리가 쉬워짐.
#5. Collider(콜라이더) 이해하기
Collider = 충돌 영역을 담당하는 보이지 않는 경계.
대표적인 종류:
- Box Collider → 네모난 물체
- Sphere Collider → 구형 물체
- Capsule Collider → 사람/기둥 모양
콜라이더가 있어야 오브젝트끼리 충돌 감지 가능.
Edit Collider 기능 → 콜라이더의 크기와 위치를 직접 조절 가능.
#6. Rigidbody(리지드바디) 이해하기
물리 엔진이 오브젝트를 진짜 물체처럼 인식하게 만드는 컴포넌트.
주요 옵션:
- Mass (질량) → 무게. 충돌할 때 영향.
- Drag (저항) → 속도가 줄어드는 정도.
- Angular Drag (회전 저항) → 회전이 얼마나 빨리 멈추는지.
- Use Gravity (중력 적용) → 체크하면 바닥으로 떨어짐.
플레이어에 Rigidbody를 추가해야 벽에 부딪히고 멈출 수 있음.
#7. Constraints(제약) 옵션 사용하기
Rigidbody 안에 있는 기능.
물리 엔진이 이상하게 움직이는 걸 방지할 수 있음.
Freeze Position: 특정 축의 이동을 막음.
- Y축을 고정 → 점프처럼 위로 튀는 걸 막음.
Freeze Rotation: 특정 축의 회전을 막음.
- 모든 회전 고정(X, Y, Z) → 캐릭터가 부딪혀도 옆으로 쓰러지지 않음.
#8. Collider 편집과 Trigger 기능
기본 충돌은 오브젝트끼리 부딪히고 멈춤.
Is Trigger 체크 → 충돌하지 않고 그냥 통과함.
- 하지만 "통과했는지" 이벤트를 코드에서 감지할 수 있음.
- 예시: 문을 통과할 때 이벤트 발생, 아이템 획득 구역 만들기 등.
즉,
- Collider → 벽, 바닥처럼 막는 용도.
- Trigger → 눈에 안 보이는 "이벤트 발동 구역" 용도.
✅ 정리하자면:
- Collider = 충돌 감지
- Rigidbody = 물리 법칙 적용
- Constraints = 이상한 움직임 방지
- Trigger = 통과 이벤트 발생