게임 심화편 프로토타입3
GCC 사관학교
안녕하세요
슈팅게임 제작 강의를 맡게 된 이영호입니다
이번 단원에서는 프로토타입 3번째에 대해 학습하겠습니다
학습 내용으로는 총알 이동 제작
총알 발사 제작
적 이동 제작에 대해 학습해 보겠습니다
총알 이동 제작
그럼 총알 이동 제작을 해보도록 하겠습니다
먼저 총알을 생성하고 그다음에 이 총알들이
날아가는 형태를 구현해보도록 할게요
유니티로 와서 먼저
총알 게임 오브젝트를 만들어 보도록 하죠
하이어라키에서 + 누르고
3D Object에 Cube를 눌러주도록 하겠습니다
이름은 Bullet으로 넣도록 할게요
Bullet 넣도록 하고요
위치는 Transform에서 Reset 눌러주도록 하겠습니다
여기에 있는데
크기는 저는 적당하게 플레이어보다는 작게
이렇게 작업을 해놓죠
이정도로 넣도록 하겠습니다
그리고 이 총알이 실제로 이동을 해야되니까
스크립트를 하나 만들어 볼게요
Project 창에 Scripts 폴더에다가
+ 눌러서 C# Script
이름은 Bullet이라고 넣도록 할게요
이렇게 Bullet 스크립트가 만들어지면
Bullet 게임 오브젝트한테 드래그 앤 드롭으로
이렇게 넣어주도록 하시죠
여기에서 이 총알이 해야 될 역할들은
이제 스크립트에서 정의를 해보도록 할게요
이 총알이 무엇을 하고 싶으냐
얘는 위로 계속 이동하게 할 거예요
이게 총알이 하는 역할이고요
그렇다면 이 총알은
이 총알이라는 클래스 자체는
속성 혹은 기능으로 이루어져 있는데
이 문장을 수행하기 위해서
어떤 속성들이 필요할까요?
기획자한테 계속해서 결국엔 물어봐야 되는
내용들이 필요합니다
여기 이 문장에서 이걸 구현하려고 하다보니까
어떤 정보들이 필요해요
그게 바로 필요한 속성으로 얘기할 수 있고요
바로 이때 이동속도라는 이 부분이 필요할 수 있어요
이동속도를 알려줘야
우리가 기획자의 의도에 맞게끔 움직일 수 있겠죠
그리고 우리가 이동속도를 설정해 놨는데
이 부분을 기획자가 직접
수정할 수 있게 해놓으면 좋을 것 같아요
자 그래서 이동속도는
이 부분에다가 public float speed 해서
10이라고 넣도록 할게요
플레이어는 속도 5로 움직였거든요?
PlayerMove에 가서 보면
지금 속도 5로 움직이고 있죠
그런데 Bullet은 어떻게?
10으로 움직이도록 처리를 해볼게요
그리고 얘는 위로 계속 이동하고 싶다고 했으니까
이 부분을 어느 곳에다가
Start 혹은 Update 둘 중에 하나에다가
우리는 구현을 해놓아야 되거든요
이 내용은 계속 이동해야 되니까
Update에다가 넣어 줘야 될 거예요
그럼 이 문장을 조금 더 세밀하게
잘게 쪼개 보도록 하겠습니다
이 문장이 궁극적으로 하고 싶은 부분은 뭘까요?
이동하고 싶은 거죠
이동하려면 뭔가가 필요해요
그게 바로 뭐냐면 방향이 필요하죠
즉 방향을 구해야
그 방향으로 이동할 수가 있게 되는 거예요
우선순위를 보면
이렇게 되어야 우선순위가 맞춰지겠죠
방향을 먼저 구하고 그 방향으로 이동하는 것
여기에서 방향은
우리가 뭘로 볼 수 있냐면
Vector3에 direction이라고 넣도록 할까요?
dir
얘는 Vector3에 Up 이렇게 되겠죠
이동공식은 P=P0+vt
이렇게 되어있죠
그러면 이대로 한번 넣도록 하겠습니다
앞에서 했던 것처럼 P0은 어떻게 된다고요?
transform의 position이 바로 P0가 되고요
그다음에 vt는 바로 dir 곱하기
크기는 여기 우리가 속성으로 주어졌던
Speed로 넣도록 하죠
그다음에 * Time.deltaTime하면
vt가 만들어진다고 했죠
그리고 Vector3에 결국 P=P0+vt
이 값을 최종적으로 transform의 position에다가
넣어주면 내용이 완성되죠
이렇게 일일 잘게 쪼개서 쓰셔도 되는데
하나의 문장으로 쓰면 결국에는 얘는 P0
그다음에 + vt, 이만큼으로 이렇게 써도 되겠네요
이 문장을 하나로 이렇게 합쳐서 써도 똑같을 거예요
이만큼이 P0이고 vt 이렇게 되겠죠
그래서 이 문장과 이 문장은 다 같다는 거 보시면 되겠습니다
저장을 하고 가서 확인을 해보도록 할까요?
Bullet에는 이미 Bullet (Script)가 붙어져 있죠
플레이 버튼을 누르면 이 Bullet 총알은 위로
슝 올라가게 되겠죠
여기에서 우리가 차별화해서 봐야 될 부분이 있어요
Bullet에는 지금 현재 Speed가 노출이 되어 있어요
Player에는 없죠
즉 기획자가 자신만의 이런 수치들을
계속해서 수정하고 싶다면
Player 같은 경우에는 계속 프로그래머한테
이 숫자를 계속 수정해 달라고 요청을 해야 돼요
그럼 Player가 작업하다 말고
이 숫자를 계속해서 수정해 줘야 되죠
이거는 굉장히 안 좋은 방식인 거예요
직접 기획자가 자신만의 컴포넌트를
수정할 수 있게끔 해주는 게 좋을 것 같습니다
그래서 이 숫자를 Player도 총알처럼 이렇게
5 이렇게 해주고
이 speed 값을 이렇게 사용할 수 있도록 하면
좋을 것 같아요 어떻게 했어요?
PlayerMove에 public float speed라는
속성을 하나 추가했고요
이 속성 값 speed 변수를
vt에서 사용할 수 있도록 이렇게 처리해 놨어요
그러면 우리가 저장을 하고 가서 보면
Player의 speed 5라는 게 이렇게 노출이 되죠
그래서 이 값을 우리가 변경할 수가 있게 되는 거예요
이렇게 기획자가 얼마든지 편하게 수정할 수 있게 되겠죠
프로그래머한테 부탁하지 않고도
이렇게 하는 방법을 알려드렸습니다
Bullet도 이렇게 노출이 되어있죠
그래서 플레이하면 총알은 위로 올라가고
Player는 speed에 맞게끔 움직이고
이 부분이 동작이 됐습니다
총알 발사 제작
이번에는 총알 발사를 해보도록 하겠습니다
총알을 여러분들 방아쇠를 당긴다고 하면
이런 과정들이 발생하게 돼요
보시면 여러분들이 이렇게 방아쇠를 당길 거잖아요
그러면 두 가지 방식이 있습니다
첫 번째는 이 화면에서 보시는 것처럼
총알 공장에 전화를 할 거예요
공장에 주문을 하는 거죠
그래서 총알을 받아가지고
그때 발사하는 방법이 있을 거예요
두 번째는 실제로 총알은 이렇게 나오겠지만
이 총알을 보더라도 탄창 안에 총알들이 잔뜩 들어있죠
그래서 어떻게 당길 때마다
탄창에서 총알을 가져와서 탕탕탕
발사하게 되는 구조인 거예요
두 번째는 탄창에서 총알을 발사하게 되는 구조인 거예요
당연하게 우리는 탄창에서 총알을 발사하도록 하겠지만
실제로 탄창에 있는 총알도
여기 있는 총알 공장에서부터 생산을 해서 와야겠죠
실제 실무에서도 공장에서 직접
이렇게 총알을 만들어내는 이 구조를 사용합니다
여기서는 실무라는 건 바로 게임 쪽에서 얘기하는 거예요
여기서 우리는 공장에 관련된 내용을 좀 보도록 할 거고요
뒤에서 나중에 바로 저 탄창에 총알을 넣는 작업도
한번 해보게 될 거예요
좀 무식하지만 우리는 방아쇠를 당길 때마다
이렇게 할 겁니다
방아쇠를 당기면 총알 공장에 전화를 할 거예요
그러면 이때 이 공장이 지금 연기가 나고 있지만
멈춰져 있어요, 이때 여기에 간이용 침대에서
마침 잠을 자고 있는 김군이 있습니다
김군이 여기 자고 있어요
띠리링 띠리링 전화가 울려요
그러면 김군이 자다 말고 벌떡 일어나야겠죠
아이고! 해서 여보세요 하고 전화를 받습니다
그랬더니 제가 급하게 다급하게 얘기하는 거예요
김군이라고 할게요
야 김군아 나 지금 방아쇠 당겼어
그러니까 빨리 총알 하나 만들어줘
그럼 김군이 네 알겠습니다 하고
바로 레버를 내려가지고 공장을 가동시키죠
그러면 공장이 가동되어 있지 않으니까
처음에 컨베이어 벨트가 먼저 움직여야 될 거예요
그리고 재료를 넣는 통이 있다고 치면
이 통에 납도 넣고 화약도 넣고 해서
김군이 열심히 작업하죠
그러면 어떻게? 이 납을 깎고
화약을 다 제조해서 총알이 하나 띵 나오는 거죠
이런 총알이 하나 띵 나오는 거예요
그럼 이 총알을 어떻게?
여기다가, 탑차에다가 총알을 싣죠
이렇게 탑차에다가 총알을 실었어요
그러면 이 도로를 따라서 탑차를 타고 옵니다
그럼 저한테 하나 총알을 주는 거죠
그러면 저는 여기에서 총알을 탕! 하고 쏘는 거예요
슝 날아가겠죠
그런데 이렇게 한 발만 쏠게 아니라 탕탕탕 쏠게요
그럼 어떻게 될까요?
전화를 해야겠죠 김군을 깨워야겠죠
김군아 총알 하나 만들어줘 탕탕탕 했으면
김군아 김군아 김군아 해야겠죠
그럼 그때마다 김군이 일어나서
레버 내려가지고 공장 가동시키고
납을 넣고 화약을 넣고 깎아가지고
총알을 하나 만들어내면 탑차 타고 나한테 배달해주고
또 김군아 김군아 했으니까 그때마다
이 작업을 계속 반복해야 될 거예요
혹시 여러분들이 여기에서 어떻게
우리가 흔히 무식하게 따발총이라고 하는 형태로
버스트로 넣고 두루루 쏜다고 하면 어떻게 될까요?
김구루루루운아! 이렇게 되겠죠
그러면 김군은 계속해서 빠른 speed로
이 작업을 계속해서 수행하게 될 거예요
이거는 굉장히 비효율적이겠죠
비효율적이 될 거예요
여러분들이 이 과정에서 어쨌든 총알을 하나 만들려면
이것은 반드시 발생할 수밖에 없어요
여러분들이 이 과정을 개선한다고 하면
어느 부분을 개선을 하면
빠르게 총알을 계속해서 쏠 수 있을까요?
어떤 분들은 속으로 이렇게 생각할 수 있어요
아 이거 도로를 좀 개선하면 되지 않을까요?
이렇게 생각할 수 있어요
그럼 배송이 빨라지니까 그것도 괜찮을 수 있어요
그런데 이렇게도 생각할 수 있지 않을까요?
총알 공장이잖아
한 발만 생산하니까 이건 좀 낭비 아닌가요?
그리고 이 공장이 멈춰있다가 가동되는데
너무 과부하가 걸리게 돼요
그러니까 아예 공장을 돌린 김에
그때 천발 만발 한 번에 만들어버리면
공장은 그런 거 만들 땐 정말 빠를 거 아니에요
만들어버리면 어떻게?
그때는 얘를 만발 싣고서 달려버리면 되잖아
그럼 나는 받아서 더 이상 공장에 주문할 필요 없이
얼마든지 총알을 쏘면 되겠죠
즉 이 부분에다가 한 번에 요청을 해버리는 거예요
이렇게 하는 것들을 우리는 배칭이라고 해요
일괄 처리한다고 하는 거예요, 배칭
현실에서도 그런 과정이 일어나겠죠, Batch라고 해요
현실에서도 당연히 그런 것처럼
이 컴퓨터 쪽에서도 어떤 처리를 할 때
이 똑같은 과정이 일어납니다
용어를 정리하면
이 공장을 우리 컴퓨터 소프트웨어에서 어떻게 얘기하냐면
컴퓨터 사이언스에서는 얘를 파일이라고 얘기할 수 있어요
그리고 이렇게 이 공장 파일로부터 만들어진 총알을
인스턴스라고 얘기합니다
이렇게 총알이 만들어졌죠?
인스턴스를 저를 이렇게 가져다 줘야겠죠
이렇게 가져다 주는 요거 있죠
이 통로, 이 통로를 우리는 스트림이라고 하는 거예요
Stream, a입니다
스트림이라고 하는 거예요
그러면 내가 파일을 읽어서 스트림을 통해서
인스턴스를 받으면
그때서야 총알을 보내는 거죠
우리가 여러분들이 이미지를 하나 탐색해서
더블 클릭해서 연다고 치면
어때요? 파일을 더블 클릭해서
얘가 열어달라고 하는 거예요
더블 클릭하는 작업이고요
그럼 파일이 열리면 스트림을 통해서
메모리 데이터가 넘어옵니다
걔를 화면에 출력하기 위해서는 인스턴스가 필요해요
걔를 가져다가 화면에 픽셀을 찍는 거예요
그래서 화면에 보이게 되는 거죠
이 총알이 바로 화면에 보이는 이미지라고 보시면 되겠습니다
이렇게 일련의 과정인데
바로 이 파일을 여는 작업이 결국에는 느리다는 얘기예요
파일을 여는 작업이
그러면 한 번 열었을 때
그때 왕창 생성해버리면 되겠죠
그것들을 배칭이라고 하고요
혹은 우리 쪽에서는 뭐라고 얘기할 수 있느냐
용어를 너네 인력풀이 어떻게 돼?
여분이 남으면 좀 줄래? 빌려줄래?
이런 얘기도 하잖아요
인력풀이라고 하잖아요
이때 풀이라는 용어를 씁니다
우리는 이때 총알, 게임 오브젝트잖아요
이 오브젝트를 여분이 있게끔
생산하는 이 작업을 Pool이라고 하고
앞에 Object를 붙이는 거예요
그러면 이것을 Object Pool이라고 합니다
즉 이 속도를 개선하기 위해서
미리 총알을 여러 개
오브젝트를 여러 개 미리 만들어 놓는 작업을
오브젝트 풀이라고 하는 거고요
이 파일을 여는 거는 똑같은 구조로 네트워크 서버
즉 여러분들이 네이버나 카카오 여러 가지 웹사이트에
구글 같은 사이트에 접속한다고 하죠
포털 사이트에 접속한다고 할 때
그때 접속한다고 할 때
얘네들의 네트워크에 접속하는
이 Connection이라는 게 일어납니다
연결이 되는 거죠 사용자들이
이것도 마찬가지예요
내가 사용자가 웹사이트에 두드리는 거예요
그럼 여기에 커넥션이 만들어지는 거예요
이것도 똑같이 파일을 열어서 하는 이 작업하고 똑같습니다
데이터를 주고 받고 네트워크에서
이때도 그러면 계속해서 접속할 때마다
이런 작업이 생기면 느려지겠네요
사용자들이 100만명이 붙어버리면 굉장히 느려지겠네요
천만명이 붙어버리면
심지어 서버가 다운될 수도 있겠죠
이때 느려지니까
파일을 여는 작업이 굉장히 느린 작업이에요
혹은 네트워크 커넥션을 여는 작업이 느린 작업이에요
그래서 그럼 커넥션도 풀이 있으면 좋겠네요
그래서 얘를 Connection Pool이라고 합니다
이런 일련의 컴퓨터 사이언스 용어들이 있어요
그래서 우리 총알을 발사할 때는
1차적으로 프로토타입에서는 이렇게
공장에서 직접 만들어내는 과정을 할 거고요
나중에 베타 버전에서는 오브젝트 풀을 이용해서
미리 이 부분을 속도 개선을 하는 작업으로
들어가도록 하겠습니다
먼저 공장에서 이 총알을 만들어내는 작업을
해보도록 하겠습니다
비주얼 스튜디오에서 Bullet 이 부분 있죠
이 애는 이미 만들어진 총알이에요
그렇다면 우리는 저 총알을 발사를 해야 될 거 아니에요
그래서 발사는 Player가 발사를 하게 되겠죠
방아쇠를 Player가 당기니까, 그래서
여기에는 Player 이동에 대한 스크립트는 있으니까
이제 발사에 대한 스크립트를 하나 만들어서 붙여볼게요
Project 창에서 + 눌러서 C#에서
이번에는 PlayerFire라고 넣도록 하겠습니다
이렇게 PlayerFire가 만들어지고요
얘를 우리 Player 게임 오브젝트에
드래그 앤 드롭으로 이렇게 붙여주면
PlayerFire 스크립트가 만들어지겠습니다
더블 클릭해서 열어볼게요
PlayerFire에서 하는 일은 이래요
사용자가 발사 버튼을 누르면 총알을 만들고 싶다
이 내용을 할 거예요
그러면 여기에서 필요한 속성은 어떤 게 있을까요
기획자가 알려줘야 될 것
총알 공장도 여러 개가 있을 수 있을 거 아니에요
총알을 만들 때는 총알 공장에서 만든다고 했잖아요
그러면 이 총알은 여러 개의 총알 공장이 있을 때
어느 총알 공장에서 만들어야 되는지
바로 총알 공장의 주소가 필요할 것 같아요
그래서 여기에 총알 공장이 필요하겠습니다
그리고 만들어져야 될 총알이 만들어졌으면
어디에다가 놓고 발사를 하게 될지
손에서 총알을 발사할 수는 없을 거 아니에요
날개 쪽에서 발사해야 될지 총구에서 발사해야 될지
이런 부분이 필요할 거예요
그래서 총구가 필요할 수 있겠습니다
필요 속성으로 이 두 가지를
클래스의 속성으로 추가해 보도록 할게요
먼저 총알 공장을 해보죠
총알 공장은 여기에 보시면
이미 만들어져 있는 이 총알이 있습니다
이 총알을 만들기 위한 총알 공장을 할 때는
어떤 식으로 하느냐? 이렇게 만들 수가 있어요
보시면 Assets에 폴더를 하나 더 만들게요
+ 누르고 Folder를 해서
이번에는 Prefabs라고 놓도록 하겠습니다
Prefabs라는 폴더를 하나 만들고
여기에 이 총알 공장이
총알 공장은 우리 쪽에서는 파일이라고 했죠
이 총알이 파일이 되었으면 좋겠어요
그러면 우리가 그때마다 이 파일을 열어서
이 총알이라는 인스턴스를 만들면 될 테니까
즉 개념상으로 보면 어때요?
이 Hierarchy에 있는 애는 인스턴스라는 애예요
Hierarchy scene에 올라가는 얘네들은 다
인스턴스라고 부릅니다
인스턴스예요
이미 만들어져서 메모리 올라가 있는 애예요
그런데 아직 저장 공간에
하드디스크에 저장이 되어 있지 않아요
하드디스크에 저장하는 공간은 바로 이 프로젝트 창이죠
즉 우리는 하드디스크에 저장되는 애들을 파일이라고 하죠
그래서 여기에 있는 이 인스턴스가 파일이 됐으면 좋겠어
그럼 얘가 어디에 있으면 돼요?
프로젝트 창에 있으면 파일이 되겠네요
개념상으로 이런 것처럼 유니티에서도 이 개념을
이 UX를 사용합니다
Bullet을 잡아서 드래그 앤 드롭으로
Prefabs 폴더로 넣으면
이렇게 Bullet이라는 이름의 총알 Prefabs가 만들어져요
얘는 파일이고요
우리가 유니티에선 이런 애들을
Prefabs이라고 지칭합니다
게임 오브젝트가 파일이 된 것
이것들을 뭐라고 불러요?
Prefabs이라고 부릅니다
그러면 여기에 있는 총알은 색상도 어때요
파란색으로 변했죠
파란색으로 변했어요
이 총알을, 여기에다가 만들어졌으니까
이제 이 총알은 사용자가 발사 버튼을 눌렀을 때만
만들어지도록 처리할게요
얘는 Delete 눌러서 지워도 돼요
왜? 이미 파일로 되어 있으니까
어? 다시 사용하고 싶으면요?
드래그 앤 드롭 얼마든지 해서
여기다 놓든 여기다 놓든 가져오실 수가 있어요
총알을 얼마든지 우리가 원하는 곳에다가
인스턴스로 이렇게 만들어낼 수가 있어요
파일이 있다면 파일을 열면 되니까 계속
그래서 여기에 총알을 얼마든지 만들어낼 수 있다
근데 이것을 언제 만들어낼까요
사용자가 발사 버튼을 눌렀을 때
얘가 바로 총알 공장이 되는 거예요
얘는 뭐예요?
게임 오브젝트가 파일이 된 거죠
에셋이 된 거예요
그래서 저 총알 공장은 이렇게 선언할 수가 있습니다
속성으로 public GameObject bulletFactory
이렇게 놓으면 어때요?
총알 공장을 받기 위한 거예요, 변수예요
왜 게임 오브젝트인가요
총알 공장, 우리가 만드는 프리패브는 뭐였어요 애초에?
게임 오브젝트였죠
Player에 보면 Player Fire에
Bullet Factory가 나타나고
이 Bullet을 드래그 앤 드롭으로
이렇게 넣을 수가 있게 되는 거예요
즉 총알 공장이 연결이 된 거예요
이름을 유의해서 보셔야 돼요
얘는 총알이 아니라 뭐예요?
총알 공장인 거죠
그다음에 총구는 어떻게 만들까요?
여기에다가 public GameObject
firePosition 이렇게 넣도록 하겠습니다
그러면 총구를 만들어낸 거예요
저희는 아직 총구가 없는데요?
그렇죠, 총구를 한번 만들어 볼까요?
보도록 하겠습니다, 총구는 이 Player에
이 정도 위치쯤에 있으면 좋을 것 같아요
만약에 나중에 날개가 달려
그러면 2발이 나오게 하고 싶어요
그러면 이 부분에다가 넣으면 되겠죠?
여기에서 총알이 나가도록
지금 현재 그게 없으니까
이 부분 쯤에서 총알이 나가도록
이렇게 처리를 해보도록 하겠습니다
그래서 Player에 선택하고
여기에서 +를 누르고 Create Empty 하면
이렇게 같은 Hierarchy 구조에서 레벨로 올라가죠
저희는 이렇게 드래그 앤 드롭으로
Player한테 넣을 수도 있겠지만 이 방법도 있어요
Player를 누르고 마우스 우 클릭을 하면
여기에서도 Create Empty
혹은 3D Object 이런 것들이 나타나요
여기에서 Create Empty를 눌러볼까요
그러면 Player의 자식으로 등록이 되죠
위치는 0, 0에 등록이 되고요
얘 이름은 FirePosition이라고 넣도록 하겠습니다
총구로
그러면 왜 Empty로 해놨느냐
얘는 눈에 보일 필요가 없어서 이렇게 해놨어요
눈에 보일 필요가 없었더니 Transform만 그대로 있죠
위치하고 회전각과 크기만 조절할 수 있는 이것만 있어요
저는 이 FirePosition을 잡아서
이쯤에다가 이렇게 넣도록 하겠습니다
그러면 이 부분에서 총알이 나가겠네요
그래서 Player를 다시 선택해보면
여기에 FirePosition을 넣도록 해놨잖아요?
이 부분에 이 FirePosition을
드래그 앤 드롭으로 넣어 주도록 하겠습니다
그러면 FirePosition이 할당이 됐어요
만약에 public이 없다면 어떻게 될까요?
public이 없다면
가서 보면 FirePosition은 없어졌죠
왜 그러느냐?
이 public만 외부에 노출이 될 수가 있어요
그래서 얘를 public 이렇게 붙여주셔야 돼요
만약에 아무것도 안 쓰면 기본적으로
접근 제한자는 Private입니다
그래서 bulletFactory, firePosition까지 노출하도록 했습니다
그러면 이제 사용자가 발사 버튼을 눌렀을 때
총알을 만들어낼 수 있도록
이 부분을 구현해 보도록 할게요
이런 문장들은 반드시 함수에 들어갈 수 있고요
우리가 아는 함수는 지금 Start 아니면 Update
이 둘 중에 하나밖에 없어요
여러분들이 자체적으로 함수를 만든다고 해도
그 함수의 호출은 반드시
Start 아니면 Update를 넣어 주셔야 돼요
그럼 저 문장은 어디에서 구현이 되어야 될까요?
호출이 바로 Update에서
Start에서 하면 태어날 때 한번 총알이 되겠죠
그리고 심지어 발사 버튼을 누르지도 못할 수 있어요
그러니까 살아가는 동안 사용자가 발사 버튼을 누르면
그때마다 계속해서 총알을 만들어낼 수 있도록
Update에다가 넣어 놓도록 하겠습니다
이걸 하려면 궁극적으로 하고 싶은 건
총알을 발사하고 싶은 거죠, 이거잖아요
총알을 만들어 내는 거잖아요, 그렇죠?
그렇다면 총알을 발사하려면 뭐가 필요하죠?
총알이 있어야죠
총알이 있어야 총알을 발사할 거 아니에요
그리고 여기서 질문이 있어요
총알을 갑자기 왜 만들까요? 이 문장대로 보면
사용자가 발사 버튼을 눌렀으니까
이 세 가지가 있기 때문에
사용자가 발사 버튼을 눌러서 그래서 총알을 만들고
그 총알이 발사가 되는 이 구조인거예요
엄밀히 말하면 총알을 발사한다는 것은
총알을 만들어 놓으면 저희는 위로 이미
올라가도록 해놨잖아요
총알은 어디에서 나갈지만 정하면 될 거예요
그래서 총알은 위치를 이렇게 설정만 해주면
총알을 만들어서 위치 설정을 해주면
그 위치에서 나가게 되겠죠
그래서 순서대로 보면 사용자가 발사 버튼을 눌러서
총알을 만들고 총알의 위치를 설정하는
이렇게 되는 게 가장 중요한 흐름이라고
볼 수가 있겠습니다
그럼 사용자의 발사 버튼을 눌렀다면
이런 것들은 만약 사용자가 발사 버튼을 눌렀다면
이렇게 볼 수 있겠죠
그때 사용하는 이 C# 언어에서의 문법은
if라는 애를 사용합니다
if 사용자의 입력은 다 어떤 게 처리하냐면
Input이라는 클래스가 처리한다고 얘기했어요
이제 . 하면 속성 혹은 기능 중에
우리가 사용할 것은 함수
기능 GetButtonDown 하면
버튼을 눌렀다는 거예요
그럼 눌렀다가 뗀 것도 있겠네요?
그러면 ButtonUp도 있고요
여기 보시면 Down은 누른 것, Up은 뗀 것
그럼 계속 누르고 있는 건?
GetButton 하고 있는 거죠
얘는 GetButton을 계속해서 누르고 있을 때
GetButton을 사용합니다
저희는 딱 누르는 그 순간을 사용할 것이기 때문에
GetButtonDown을 사용하도록 할게요
여기에서 Fire1 하면 마우스 왼쪽 버튼
혹은 왼쪽 Ctrl 버튼을 클릭했을 때에요
이때 아래 있는 이 내용들이 구현이 되도록
처리하면 되겠습니다
Fire1은 유니티의 Edit 메뉴의
Project Settings에 보면은
Input Manager가 있죠
Project Settings에 Input Manager가 있습니다
여기에 Fire1이 이렇게 설정이 되어 있어요
그래서 먼저 사용자가 발사 버튼을 눌렀다는 건
이 부분이 될 거고요
이게 참이면 버튼을 누른 거니까
총알을 만들면 돼요
총알을 만드는 건 유니티에서 어떻게 하느냐
Instantiate, 김군아 총알 공장에서
총알 하나 만들어줘 하는 내용에
그리고 나한테 가져다 줘, 여기까지가 다 뭐냐면
바로 Instantiate라는 팩토리 메소드라고 합니다
팩토리 함수
이 안에서 자동으로 다 만들어주는 역할까지 해줍니다
그리고 나한테 가져다 주는 것까지
이게 바로 총알 공장에서 총알을 만드는 거예요
Instantiate, 여기에 총알 공장을 넣어주면 돼요
bulletFactory, 총알 공장을 넣어주면
그렇게 해서 총알을 하나 만들어주고
그냥 게임 오브젝트 있죠?
이런 게임 오브젝트들 아무거나 넣어주면
걔를 클론 복제해서도 만들어줍니다
얘는 함수일 뿐이에요
나한테 이렇게 하나를 만들어줬다면
저는 위치 설정하고 이런 작업들을 할 때
변수에다가 담아서 쓰면 되겠어요
GameObject bullet 이렇게 하면 되겠습니다
여기에서 있는 얘는 총알 공장이고
얘는 뭐에요?
얘는 파일이고 얘는 인스턴스라고 부르는 거죠
여기서부터 나온 인스턴스를 여기에 담아놨으니까
이게 인스턴스라고 보시면 됩니다
이 변수 자체를
총알의 위치는 그럼 어떻게 설정하느냐
bullet. 하면 네가 가지고 있는 속성 혹은 기능 중에
원을 그리면 되죠?
여기에 위치는 누가 갖고 있어요
transform이 갖고 있죠, 게임 오브젝트에
그리고 transform. 하면 또 속성 혹은 기능 중에
위치는 뭐예요? position이죠
이 총알의 위치는 어디로 설정할 거냐
우리가 여기에 담았던 이 총구의 위치
이 부분이 바로 이 총구, firePosition이죠
얘를 .transform.position
이렇게 하면 총구의 위치로 할당이 되는 거예요
됐죠? 저장을 하고요
가서 플레이 버튼을 눌러보도록 하겠습니다
그러면 탕탕탕탕 총알이 나가게 되죠
이동하면서 쏴도 나가게 될 거예요
보시면 어때요? 총구의 위치에 따라서
그 위치에서 나가는 것을 볼 수 있죠
제가 여기다 놔볼까요?
탕탕탕탕 그러면 저 위치에서 나가죠
신기하게도 제가 플레이 버튼을 꺼볼게요
그럼 이 총구의 위치가 여기 있는데 어디로 가 있을까요?
끄면 다시 원래대로 돌아가 있죠
플레이 버튼을 눌렀을 때
우리가 어떤 값들을 수정하거나 하면
반영이 되지 않는 거예요
왜? 이것들이 저장되는 건 파일에 저장이 되는 거지
이 플레이 버튼이 있을 때는
파일에 저장이 되는 건 아닌 거예요
그래서 이거는 일시적으로
플레이하는 동안에만 존재하는 거예요, 데이터가
그러면 이렇게 저장되는 이것들이 저장이 되게 하고 싶으면
나중에 저장이라는 개념까지 배우셔야 돼요
그것들은 베타 버전에서 작업을 해보도록 하겠습니다
이렇게 해서 총알을 발사하는 것 까지 해봤습니다
적 이동 제작
그러면 이번에는 적 이동 제작을 해보도록 하겠습니다
먼저 적을 이동하려면 적이 있어야겠죠?
그래서 먼저 적부터 만들어 보도록 하겠습니다
Hierarchy에서 + 누르고 3D Object의 Cube
이름은 Enemy라고 할게요
여러분들이 눈치 채셨는지는 모르겠지만
계속 같은 과정으로 플레이어부터 총알, 적까지 나올 동안
같은 내용으로 하고 있습니다
제일 먼저 뭘 해요?
게임 오브젝트를 하나 만들죠
하이어라키에서 큐브를 하나 만들고요
그다음에 스크립트를 만들고, 스크립트를 할당하고
그다음에 코딩을 하고
이 흐름으로 계속해서 컨텐츠를 만들어가는 거예요
유니티로 컨텐츠를 만들 때 가장 어려운 부분이
다 기능별로는 학습할 수 있어요
하지만 어떻게 시작해서 컨텐츠를 만들어 갈까에 대한
어려움이 있을 수 있거든요
그런 부분 어떻게 한다고요?
이렇게 따라 하시면 되겠습니다
먼저 어떻게 한다고요?
게임 오브젝트를 하나 만들고, 큐브를 만들고
걔에다가 스크립트를 만들어서 할당을 하고
물론 스크립트는 컨트롤이 필요한
게임 오브젝트한테만 할당하는 거예요
이 흐름으로 계속해서 등장인물 형태로 계속해서
만들어 나가시면 되겠습니다
이렇게 Enemy가 만들어졌으니까
얘한테 스크립트도 할당을 해볼 거예요
그 전에 먼저 트랜스폼의 위치를 0, 0, 0으로 놓고
저는 위에다가 이렇게 놓도록 할게요
그래서 얘가 밑으로 슉 떨어지는
에너미를 만들어 보려고 해요
Enemy의 Scripts에
C# Script에서 이름은
Enemy라고 넣도록 할게요, 이렇게
그러면 Enemy가 만들어지고
이 Enemy 게임 오브젝트에다가
얘를 드래그 앤 드롭으로 넣어 주도록 하겠습니다
이제 스크립트를 편집을 해볼게요
Enemy 스크립트 여기 있죠?
여기를 클릭하셔도 되고
여기를 더블 클릭해서 열어주셔도 됩니다
이렇게 Enemy를 편집할 수 있는
비주얼 스튜디오가 열리면요
여기서 하고 싶은 건
얘는 총알은 계속 위로 올라갔다면
에너미는 아래로 계속 이동하고 싶다
여기에서도 필요한 속성은 뭘까요?
바로 이동 속도가 되겠습니다
그래서 public float speed
얘는 Player와 같은 속도로 맞춰 놓도록 하겠습니다
그리고 아래로 계속 이동하고 싶은 이 내용은
바로 계속 이동을 해야 되니까
Update에서 들어가게 될 거고
똑같죠? 방향을 구하고 그 방향으로 이동하는 형태
그래서 얘는 Vector3에
dir을 놓고, 방향은 뭐예요?
Vector3에 Down 하시면 아래로라는 게 되고요
그 다음 이동하고 싶다
P=P0+vt 한 번에 쓸 수 있다고 했죠
transform의 position은 어떻게 돼요?
transform.position = dir * speed * Time.deltaTime
이렇게 하셔도 되겠지만 이거는 어때요?
현재의 위치를 단순하게 갱신하는 거죠
P=vt일 뿐이에요
얘가 정상적으로 활동하려면 P=P0+니까
이렇게 하시면 되겠죠, 얘한테 이렇게
그러면 어때요? P0+vt
근데 얘도 언어다보니까 말 줄임이 됩니다
선생님을 쌤 이렇게 하는 것처럼
음식물 쓰레기를 음쓰, 이렇게 줄여서 하죠
얘도 줄여서 쓸 수가 있어요 이렇게
이렇게 하면 P=P0+vt 이렇게 된 거예요
마찬가지로 우리 Bullet에서도 가서 보면
똑같이 이렇게 되어 있죠
이 부분을 줄일 수가 있겠네요
Bullet에서도 += 이렇게 쓸 수가 있겠죠
마찬가지로, 맞죠? 그래서 에너미나 총알이나
P=P0+vt에서 transform은 더하기를
이렇게 하시면 되겠습니다
저장하고요
봐 볼게요, 플레이 버튼 누르면 아래로 내려오는
에너미를 만들 수가 있습니다
이렇게 아는 아래로 내려오는 에너미를 만들 수 있고요
벡터를 조금 더 활용을 해 가지고
이 에너미가 플레이어 쪽으로 이동하도록 하는 코드도
작성을 해보도록 할게요
벡터의 빼기를 이용하면 되겠죠?
그래서 이번에 하고 싶은건 아래로 가 아니라 추가로
타겟 쪽으로
타겟 쪽으로 계속 이동하고 싶다
그러면 필요 속성의 이동속도 말고도 또 뭐가 필요하죠?
바로 타겟이 필요한 거예요
이 타겟은 public
타겟은 월드상에 있는 플레이어죠
얘는 자료형이 게임 오브젝트
그래서 여기다가 GameObject라고 넣어 주도록 하겠습니다
자 public GameObject 다음에 target
이렇게 넣으면 되겠죠, 근데 궁극적으로 필요한 건
게임 오브젝트가 아니라 이 타겟의 위치가 필요한 거잖아요
위치를 갖고 있는 애는 누구죠?
게임 오브젝트의 위치를 갖고 있는 애는
바로 Transform이죠
우리는 그러면 이 플레이어의 다리만 알고 있으면 돼
다리가 어딘지만, 그렇죠?
여기에 강사 이영호가 있습니다
강사 이영호가 있는데, 이영호 전체를 알 게 아니라
다리의 지금 현재 위치가 어딘지만 알면
다리만 내가 모니터링 하고 있으면
얘 위치를 갖고 올 수 있는 거잖아요
그래서 이 Transform이라는 컴포넌트만 알고 있으면 돼요
그래서 이 부분에 GameObject를 해도 되지만
Transform 이렇게 놔도 되겠습니다
바로 이 Enemy의 Transform을
나는 기억하고 있으면 되니까
그러면 이렇게 저장을 해놓고
Enemy에 가서 보면 타겟이 노출이 되죠
여기 transform이 있는데
여기에서 중요한 개념을 하나 보시겠습니다
여기에 있는 플레이어는 게임 오브젝트입니다
게임 오브젝트를 에너미가 따라다니고 싶은 거예요
근데 명확하게 얘기하면
Player에 있는 이 Transform이
Enemy한테 들어가줘야 돼요
그런데 이렇게 넣어도 됩니다
제가 플레이어를 잡아서 게임 오브젝트를 잡아서
이 타겟에다가 넣어 주면
얘는 Transform을 원하는데
Player라는 게임 오브젝트를 넣어 줬어요
그러면 자동으로 Player의 Transform이
이렇게 할당이 되죠
유니티가 이렇게 User Experience
사용자 경험이 굉장히 훌륭합니다
플레이어 트랜스폼을 자동으로 할당해주는 부분까지 됩니다
이렇게 해서 Enemy한테 타겟까지 설정을 해줬고요
그러면 타겟 쪽으로 계속 이동을 하고 싶다고 했으니까
여기에는 플레이어가 들어가 있을 거예요
그러면 이 타겟 쪽으로 가기 위한
방향을 한번 구해 보도록 할게요
아래로가 아니라 이제는 타겟이죠
이때 우리는 타겟 쪽으로 방향을 어떻게 구한다고요?
Target-Me, 타겟에 있는 속성 중에 position이죠
바로 위치가 필요한 거예요
-Me, 나의 위치는
transform.position 이렇게 쓰시면 돼요
그러면 Target-Me 해서
내가 타겟 쪽으로 이렇게 향하는
이 벡터를 구해낼 수가 있는 거예요
그런데 이것을 길을 전체를 그냥 다 쓰면 안 된다고 했죠
어떻게? 이 벡터의 크기는 이렇게 만들어 놓고
나의 속도로 이동하게
이렇게 벡터의 크기를 그래서 1로 만들어 주는 행위를
Normalize 한다고 했어요
그래서 디렉션을, 이 방향을
dir을 Normalize 이렇게 함수를 호출해주면
이렇게 구해놓은 이 디렉션의 크기가 어떻게 된다고요?
1로 만들어 주게 돼요
이렇게 하면 그 방향으로 이동한다는 변화가 없죠
이렇게 저장을 하고 다시 가서 보도록 할게요
플레이 버튼을 눌러볼까요?
그러면 에너미는 제가 움직일 때
계속해서 저를 따라오죠
보이나요? 이렇게 계속해서 플레이어를 따라다니는
에너미를 만들 수가 있습니다
그러면 이렇게 계속해서 따라다니지만
저는 태어날 때 한 번만 따라다니게
이렇게 바꿔보도록 할게요
태어날 때 한 번만
태어날 때 한 번 방향을 구하고
그리로 계속 이동하고 싶다
그 방향으로 계속 이동하고 싶다는 거예요
타겟 쪽으로 계속 이동하는 게 아니라
그러면 어떻게 될까요?
태어날 때 한 번 방향을 구해야겠죠
바로 살아가면서 계속 구하는 게 아니라
어떻게 구하자고요?
태어날 때가 바로 Start니까 이쪽에서 하자고
그런데 여기에 있는 dir을 여기에서는 사용할 수가 없죠
이렇게 이 Start에 있는 이런 변수를
우리가 지역 변수라고 하죠
Update에서는 다른 함수에 있는 이 지역 변수를
접근할 수가 없습니다
그러면 어디에다가 넣어야지 접근할 수 있을까요?
바로 속성으로 전역으로 등록을 해놔야지
사용할 수가 있어요
그래서 여기 있는 Vector의 dir은
여기에다가, 속성 부분에다가 이렇게 놔주도록 하고요
얘네들은 여기에서 등록해 놓은
이 dir을 사용하도록 이렇게 처리할게요
그러면 얘는 불이 들어와 있죠?
다 같은 애들이 되는 거예요
그래서 태어날 때 한 번 방향을 구하고
그리고 그 방향으로 계속 이동하고 싶다가 되는 거죠
얘는 태어날 때 방향을 구하는 거죠
계속 이동하고 싶다 이렇게 되겠죠
저장을 하고 태어날 때 한 번 구하고
그 방향으로 계속 이동하고 싶다 이렇게 구했으면
가서 해 볼게요
그러면 저는 옆에다가 티가 나게 이렇게 놓도록 하겠습니다
플레이 버튼을 누르면 제가 피해도
얘는 처음에 구한 그 방향으로
계속 이렇게 이동을 하게 되겠네요
이렇게 Enemy가 만들어졌습니다
Enemy가 이렇게 만들어졌다면
어떤 녀석은 아래로 내려오고
어떤 녀석은 타겟 쪽으로 가고
이런 부분이 좀 필요할 수 있어요
그래서 랜덤으로 설정되게
이렇게 구현을 해 보도록 하겠습니다
그래서 랜덤으로 30%의 확률로
어떤 녀석은 타겟 쪽으로 가고
어떤 녀석은 그냥 아래로 내려가고 이렇게 하도록 할게요
그러면 무조건 다 타겟 쪽으로 이동을 하면
다 어려울 거 아니에요, 플레이어 입장에서는
그러니까 이런 식의 변동치를 주도록 하겠습니다
그럼 태어날 때 이 방향을 구할 때
내용이 들어가게 될 거예요
어떻게 할 거냐?
30%의 확률로 타겟 쪽으로 방향을 구하고
그렇지 않으면, 30% 밖이면
그렇지 않으면 그냥 아래로 방향을 설정하자
이렇게 넣도록 하겠습니다
그러면 30%의 확률이라는 건 이렇게 구할 수 있어요
먼저 그럼 확률을 구해야겠네요?
확률은 먼저 int라고 넣도록 할게요
percent라고 넣도록 하겠습니다
얘는 Random에 보면 여기 Range라는 게 있어요
RandomRange도 있지만
여기에 사용되지 않음으로 되어 있습니다
Range로 넣고요
여기에 1부터 10까지 이렇게 넣도록 하죠
그러면 이 Range에 보면 어떻게 되어 있어요?
maxExclusive 이렇게 되어 있죠
이 안에 들어가서 보면 이렇게 되어 있습니다
int 이렇게 들어가서 작업이 되어 있어요
그래서 우린 여기에다가 얘를 가져다가 사용하게 되겠습니다
1부터 10까지 percent를 가져오고요
그럼 얘가 30%의 확률이라는 건 어떻게 하면 돼요?
3보다 작으면 될 거 아니에요? 그러면은 30%고
3보다 크면? 다른 확률인거죠
그래서 30%의 확률은 it(percent <= 3)
3을 포함하는 거잖아요? 1,2,3 이니까
그러면 어떻게 하자고요?
타겟 방향으로 이렇게
타겟 방향으로 구하자는 거죠
이 부분이 바로 30%의 확률인 거예요
그렇지 않으면 어떻게? 그냥 아래로 했으니까
else 이렇게 해서 그냥 아래로
그래서 dir = Vector3.down
이렇게 하시면 되겠습니다
저장하고 가서 보도록 할까요?
플레이 버튼을 누르면 얘는
30% 확률로 아래로 혹은 타겟 쪽으로
이동하는 내용을 볼 수가 있겠습니다
여기까지 해서 적의 이동까지 알아봤습니다
이번 단원에서 학습한 내용을 정리하도록 하겠습니다
첫 번째 학습 내용으로
총알 이동 제작 내용을 구현했습니다
Bullet 게임 오브젝트를 생성하고 C# 스크립트를 만들어
위로 이동하도록 코드를 작성했습니다
두 번째로 총알을 발사하는 내용을 구현했습니다
Bullet Prefabs를 만들고
Player Fire 스크립트를 이용해
사용자가 발사 버튼을 누를 때
총알이 발사되도록 구현했습니다
마지막으로 적 이동 제작 내용을 학습했습니다
에너미 객체를 생성하고
아래로 이동하는 스크립트를 작성했습니다
여기까지 수고 많으셨습니다
총알 이동 제작 Bullet 생성 및 위치 설정
하이어라키에서 [+] - [3D Object] - [Cube] 생성 후 Bullet으로 이름 변경 Bullet의 Transform에서 총알의 위치와 크기 변경
Bullet 스크립트 생성 및 할당 프로젝트 창에서 [Scripts] - [+] - [C# Script] 생성 후 Bullet으로 이름 변경
Bullet 스크립트를 Bullet 게임 오브젝트의 컴포넌트로 드래그 앤 드롭
Bullet 이동 스크립트 구현 유니티 에디터 상에 노출되도록 접근제한자를 public으로 하여 speed 변수 생성
계속 호출되도록 Update 함수에 구현부 추가 위로 가는 up 방향을 구한 후 이동 공식 P = P0 + vt를 이용하여 이동 부분 구현
총알 발사 제작 PlayerFire 스크립트 생성 및 할당 프로젝트창에서 [+] - [C# Script] 생성 후 PlayerFire로 이름 변경
PlayerFire 스크립트를 Player 게임 오브젝트의 컴포넌트로 드래그 앤 드롭 Bullet Prefabs 제작 및 할당
프로젝트창에서 폴더 생성 후 Prefabs로 이름 변경 하이어라키의 Bullet 객체를 프로젝트창의 Prefabs 폴더로 드래그 앤 드롭
씬에서 Bullet 제거 후 PlayerFire의 Bullet Factory 속성에 Bullet Prefabs 할당 총구 제작 및 속성 할당
Player 객체를 선택하고 마우스 우클릭 후 Create Empty 선택해 자식으로 등록된 빈 게임 오브젝트 이름을 FirePosition으로 변경
FirePosition 객체를 Player의 PlayerFire 스크립트에 할당
총알 발사 입력 처리 발사 버튼을 누를 때마다 총알을 생산해야 하므로 Update 함수에 입력
버튼을 누를 때 True가 발생하는 GetButtonDown 함수 사용 마우스 왼쪽이나 왼쪽 Ctrl 버튼 클릭 시 입력처리는 'Fire1'
Instantiate 함수의 인자로 bulletFactory 입력 시 총알을 하나 생성함
만들어진 bullet 객체에 속성으로 선언한 firePosition 총구의 위치를 할당
적 이동 제작 Enemy 객체 생성 및 스크립트 할당 하이어라키에서 [+] - [3D Object] - [Cube] 생성 후 Enemy로 이름 변경
프로젝트창에서 [Scripts 폴더] - [+] - [C# Script] 생성 후 Enemy로 이름 변경 Enemy 스크립트를 Enemy 게임 오브젝트의 컴포넌트로 드래그 앤 드롭
이동 코드 작성 이동속도 속성 선언 후 방향을 구하고 이동공식으로 코드 구현