게임을 만들어 보고싶어졌다..
만들어 볼 만한 게임이 없을까..찾아보다가 강의를 하나 찾았다.
https://www.youtube.com/watch?v=SviIeTt2_Lc&list=PLctzObGsrjfyevwpeEVQ9pxGVwZtS7gZK&index=1&pp=iAQB
탑 다운 뷰 슈팅 게임이다.
3D 상에서 플레이어 이동, 마우스 위치에 따른 방향 전환, 탄환 발사,
적 생성 후 장애물을 피해 플레이어를 따라오는 AI, 맵 생성 등, 재밌어보였다.
위 채널의 영상에서 쉽게 잘 설명해주시는 것 같다. (한글 자막도 있어서 좋다)
위 영상을 참고하여 탑다운 슈팅게임을 만들어보기로 했다.
먼저 Unity 를 설치하고 프로젝트를 3D 프로젝트로 생성했다.
C# 스크립트들을 저장할 Script 폴더를 생성하자.
플레이어 정보를 저장 할 Player 스크립트와
플레이어를 조종하기 위한 PlayerController 스크립트를 생성한다.
| Player 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(PlayerController))]
/* 이 스크립트가 포함된 오브젝트에 PlayerController 스크립트도 포함되어야 한다.
이 스크립트를 추가할 때 해당 스크립트도 자동으로 추가한다. */
public class Player : MonoBehaviour
{
public float moveSpeed = 5.0f; // 플레이어 이동 속도
Camera viewCamera; // 카메라
PlayerController controller; // 플레이어 컨트롤러
void Start() {
controller = GetComponent<PlayerController>();
// controller 에 현재 오브젝트에 추가되어있는 PlayerController 를 가져와서 사용.
viewCamera = Camera.main;
// Camera 의 main 할당
}
void Update() {
Vector3 moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxis("Vertical"));
// 수평(x), 수직(z) 입력을 받기.
Vector3 moveVelocity = moveInput.normalized * moveSpeed;
// normalized : 방향을 가리키는 단위 벡터로 변경
controller.Move(moveVelocity);
// 플레이어를 움직이는 Move() 메소드를 호출. PlayerController 스크립트에서 만들예정
/* 플레이어가 바라보는 방향을 알아내기 위해 아래의 방법을 사용한다.
카메라에서 마우스 위치로 ray 를 쏴서 바닥(plane)과 닿는 부분이 바라볼 방향이 된다. */
Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);
// 화면 상의 마우스 위치를 가져온다.
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
// 평면의 법선 벡터 생성.
float rayDistance;
if (groundPlane.Raycast(ray, out rayDistance)) {
/* 위 조건문이 true 라면 바닥이 ray 와 교차한것이다.
이 때 교차지점까지의 거리가 rayDistance 에 저장 */
Vector3 point = ray.GetPoint(rayDistance);
// point 벡터를 생성하고 GetPoint 에 교차지점까지의 거리를 전달해 교차지점의 위치를 저장.
// 카메라부터 교차지점까지 선으로 표시 : Debug.DrawLine(ray.origin, point, Color.red);
controller.LookAt(point);
/* 플레이어의 바라보는 방향을 바꾸는 LookAt() 메소드를 호출.
이 역시 PlayerController 스크립트에서 만들예정 */
}
}
}
RayCast 란 간단하게 말해 충돌 감지이다.
레이저를 내가 설정한 거리만큼 쏴서 레이저가 물체에 닿았는지를 통해
충돌 감지를 한다고 생각하면 될 것 같다.
위 코드에서 플레이어가 바라보는 방향을 구하기 위해 카메라부터 바닥까지 레이저를 쏘고,
이 레이저가 바닥에 닿는 곳 까지의 거리를 구한다.
이 거리를 레이저의 GetPoint 메소드에 전달해 닿은 위치를 알아낸다.
이제 플레이어가 해당 위치를 바라보게 하면 된다.
| PlayerController 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
/* 이 스크립트에서는 RigidBody 컴포넌트가 필요하다.
따라서 이 스크립트가 포함된 오브젝트에 RigidBody 컴포넌트가 포함되도록 한다. */
public class PlayerController : MonoBehaviour
{
Vector3 velocity; // 속도
Rigidbody myRigidbody; // 리지드바디
void Start() {
myRigidbody = GetComponent<Rigidbody>(); // 현재 오브젝트의 리지드바디 할당.
}
public void Move(Vector3 _velocity) { // 플레이어 이동 속도 저장 메소드
velocity = _velocity; // 전달받은 속도를 velocity 에 저장.
}
public void LookAt(Vector3 lookPoint){ // 플레이어 방향 설정 메소드.
Vector3 heightCorrectedPoint = new Vector3(lookPoint.x, transform.position.y, lookPoint.z);
// 플레이어의 현재 y 값은 고정시킨 상태로 바라보는 위치를 저장할 벡터 생성.
transform.LookAt(heightCorrectedPoint);
// transform 의 LookAt 메소드에 위치를 전달 하여 플레이어가 해당 위치를 바라보게 한다.
}
public void FixedUpdate() {
myRigidbody.MovePosition(myRigidbody.position + velocity * Time.fixedDeltaTime);
/* 리지드바디의 MovePosition 을 사용하여 위치를 변경(이동)
velocity(이동속도)에 FixedDeltaTime(물리 업데이트 주기)을 곱하고,
이 값을 현재 리지드바디의 위치에 더해 프레임차이가 있어도 동일한 이동을 하도록 한다. */
}
}
FixedUpdate 는 프레임 단위로 호출되는 Update 와 다르게 Fixed Timestep 에 따라 호출된다.
물리효과가 적용된 RigidBody 에서 사용되는데 물리 업데이트 발생 시 호출된다고 보면 된다.
이제 Player 가 될 캡슐을 생성하자.
생성했다면 인스펙터에 Player 스크립트를 마우스로 끌어와 스크립트를 추가하자.
위 스크립트만 추가해도 자동으로 PlayerColtroller, RigidBody 가 추가된다.
이제 바닥 Plane 을 생성하자.
플레이어가 위에 서있도록 플레이어 기본 위치 y 값을 1로 하여 바닥 위에 위치하도록 한다.
플레이어와 바닥의 구분을 위해 Material 폴더를 만들어 각 Material 을 만들고,
각 오브젝트에 적용해준다.
적용했다면 Player Material 의 색상을 변경해주어 플레이어 캡슐의 색을 변경하자.
나는 하늘색으로 설정했다.
이제 카메라의 각도, 위치를 변경하여 탑 뷰 형태로 바꿔주자.
각도, 위치는 본인 취향에 맞게 잘 보이게 바꾸자.
이제 위와 같이 설정하고 실행하면 방향키, 또는 wasd 키에 따라 캡슐이 움직인다.
하지만 움직이다 보면 캡슐이 넘어지게 된다.
이를 막아보자.
RigidBody 의 Constraints 의 회전 고정으로 플레이어가 회전하지 않게 하여 넘어지지 않게한다.
이제 플레이가 넘어지지 않게 잘 움직이고, 마우스 커서를 따라 잘 회전한다.
위 영상에서는 카메라가 고정되어있다.
하지만 나는 카메라가 플레이어를 따라가게, 즉 카메라가 플레이어에게 고정되도록 하고 싶었다.
카메라 오브젝트를 플레이어 오브젝트의 하위(자식)오브젝트로 넣어서 고정 시킬 수도 있지만,
지금 코드의 경우엔 플레이어가 회전 할 때 카메라도 같이 돌아버린다..
(카메라가 돌고 마우스 커서 따라 플레이어가 또 돌아서 무한회전..)
따라서 카메라에 스크립트를 추가해서 회전 없이
플레이어 오브젝트의 좌표만 가져와서 따라가게 하자.
| CameraController 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public GameObject Player; // 플레이어 오브젝트 할당.
public Vector3 offset; // 카메라 거리를 저장할 벡터
private void Start() {
offset = this.transform.position - Player.transform.position;
// 현재 위치에서 플레이어 위치를 빼 플레이어와 카메라 사이의 거리를 저장.
}
private void Update() {
this.transform.position = Player.transform.position + offset;
// 현재 오브젝트의 위치를 플레이어 오브젝트의 위치에 카메라 거리를 더해 적용.
}
}
위 코드를 카메라에 적용해 카메라가 플레이어를 따라가도록 했다.
참고 영상 :
https://www.youtube.com/watch?v=jdv8erC7ML8&list=PLctzObGsrjfyevwpeEVQ9pxGVwZtS7gZK&index=3
이번 글은 위 영상의 내용만큼 진행했다.
앞으로도 한 글에서는 한 강의의 내용만큼 진행 할 예정이다.
다음 글에서 E02 강의 내용에 따라 진행해보자.
'Unity > 게임개발' 카테고리의 다른 글
[Unity] 게임 개발 일지 | 탑다운 슈팅 6 (0) | 2023.11.24 |
---|---|
[Unity] 게임 개발 일지 | 탑다운 슈팅 5 (1) | 2023.11.23 |
[Unity] 게임 개발 일지 | 탑다운 슈팅 4 (0) | 2023.11.22 |
[Unity] 게임 개발 일지 | 탑다운 슈팅 3 (1) | 2023.11.22 |
[Unity] 게임 개발 일지 | 탑다운 슈팅 2 (0) | 2023.11.17 |