[Unity/유니티] 기초-2D 종스크롤 슈팅: 플레이어 이동 구현하기[B27]
개요
유니티 입문과 독학을 위해서 아래 링크의 골드메탈님의 영상들을 보며 진행 상황 사진 또는 캡처를 올리고 배웠던 점을 요약해서 적는다.
현재는 영상들을 보고 따라하고 배우는 것에 집중할 것이며, 영상을 모두 보고 따라한 후에는 개인 프로젝트를 설계하고 직접 만드는 것이 목표다.
https://youtube.com/playlist?list=PLO-mt5Iu5TeYI4dbYwWP8JqZMC9iuUIW2
유니티 강좌 기초 채널 Basic
유니티 개발을 처음 시작하시는 입문자 분들을 위한 기초 채널. [ 프로젝트 ] B00 ~ B12 (BE1) : 유니티 필수 기초 B13 ~ B19 (BE2) : 2D 플랫포머 B20 ~ B26 (BE3) : 2D 탑다운 대화형 RPG B27 ~ B37 (BE4) : 2D 종스크롤
www.youtube.com
2D 종스크롤 슈팅: 플레이어 이동 구현하기[B27]
1. 준비하기
- 영상 설명에 첨부된 에셋 스토어 링크를 통해서 에셋을 다운로드 받았다.
- 참고로 이번 프로젝트부터는 최신 버전의 유니티를 활용할까 한다. 특별한 이유는 없고 앞으로 유니티 개인 프로젝트나 동아리를 통해서 팀 프로젝트를 진행할때는 아무래도 최신 버전의 유니티를 사용하면서 익숙해지는 것이 좋을 것같다는 생각이 들어서다.
- Sprite Mode를 Multiple로, Pixels Per Unit을 24로, Filter Mode를 Point(no filter)로, Compression을 None으로 설정한다. 이후 Sprite Editor를 통해서 Grid By Cell Size Type으로 Pixel Size의 X, Y 값을 24로 하고 Padding을 각각 1씩 주며 Slice를 눌러 잘라준다.
2. 플레이어 이동
//Player 스크립트 파일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
public float speed;
void Update() {
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
Vector3 curPos = transform.position;
Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
transform.position = curPos + nextPos;
}
}
- 물리적인 이동이 아닌 transform 이동에는 Time.DeltaTime을 곱해줘야한다. 이유는 지난 입문 프로젝트 글을 보면될 것 같다.
3. 경계 설정
- Player의 Rigidbody 2D의 Body Type은 Kinematic으로 설정한다. 기본 설정인 Dynamic을 하게되면 Dynamic끼리 부딪혔을때 밀리거나 떨리는 등의 물리 효과를 받게 된다. Kinematic을 설정하면 받지 않게 되어 작성한 코드 로직에 따라서만 작동하게된다. 그렇기에 이번 파트에서는 따로 경계선과 관련된 코드를 작성하지 않았으므로, 경계선이 잘 작동하는지 테스트하기위해서는 잠시 Dynamic으로 바꾸고 진행해야한다.
- 참고로 위 캡처에서 계속 아래 화살표를 누르게되면 Player가 계속 내려가려고 시도하면서 튕기고 내려가고를 반복해 떨림현상이 발생한다. 즉, transform 이동과 물리 충돌 때문이다.
- Border 4 경계의 Rigidbody 2D의 Body Type은 Static으로 설정한다. Static은 고정되어 움직이지 않는다.
4. 경계 충돌 로직
//Player 스크립트 파일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
public float speed;
public bool isTouchTop;
public bool isTouchBottom;
public bool isTouchLeft;
public bool isTouchRight;
void Update() {
float h = Input.GetAxisRaw("Horizontal");
if ((isTouchRight && h == 1) || (isTouchLeft && h == -1))
h = 0;
float v = Input.GetAxisRaw("Vertical");
if ((isTouchTop && v == 1) || (isTouchBottom && v == -1))
v = 0;
Vector3 curPos = transform.position;
Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
transform.position = curPos + nextPos;
}
void OnTriggerEnter2D(Collider2D collision) {
if (collision.gameObject.tag == "Border") {
switch(collision.gameObject.name) {
case "Top":
isTouchTop = true;
break;
case "Bottom":
isTouchBottom = true;
break;
case "Left":
isTouchLeft = true;
break;
case "Right":
isTouchRight = true;
break;
}
}
}
void OnTriggerExit2D(Collider2D collision) {
if (collision.gameObject.tag == "Border") {
switch (collision.gameObject.name) {
case "Top":
isTouchTop = false;
break;
case "Bottom":
isTouchBottom = false;
break;
case "Left":
isTouchLeft = false;
break;
case "Right":
isTouchRight = false;
break;
}
}
}
}
5. 플레이어 애니메이션
- 매개변수 Input은 입력받은 키 값과 동일하게 1, 0, -1로 나온다. 즉, 왼쪽을 누르면 -1, 오른쪽을 누르면 1, 안누르면 0이 된다. 자세한 Transition 설정은 아래와 같다.
- Center -> Right : Input Equals 1
- Right -> Center : Input Equals 0
- Center -> Left : Input Equals -1
- Left -> Center : Input Equals 0
- Right -> Left : Input Equals -1
- Left -> Right : Input Equals 1
//Player 스크립트 파일
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
Animator anim;
public float speed;
public bool isTouchTop;
public bool isTouchBottom;
public bool isTouchLeft;
public bool isTouchRight;
void Awake() {
anim = GetComponent<Animator>();
}
void Update() {
float h = Input.GetAxisRaw("Horizontal");
if ((isTouchRight && h == 1) || (isTouchLeft && h == -1))
h = 0;
float v = Input.GetAxisRaw("Vertical");
if ((isTouchTop && v == 1) || (isTouchBottom && v == -1))
v = 0;
Vector3 curPos = transform.position;
Vector3 nextPos = new Vector3(h, v, 0) * speed * Time.deltaTime;
transform.position = curPos + nextPos;
if (Input.GetButtonDown("Horizontal") || Input.GetButtonUp("Horizontal")) {
anim.SetInteger("Input", (int)h);
}
}
void OnTriggerEnter2D(Collider2D collision) {
if (collision.gameObject.tag == "Border") {
switch(collision.gameObject.name) {
case "Top":
isTouchTop = true;
break;
case "Bottom":
isTouchBottom = true;
break;
case "Left":
isTouchLeft = true;
break;
case "Right":
isTouchRight = true;
break;
}
}
}
void OnTriggerExit2D(Collider2D collision) {
if (collision.gameObject.tag == "Border") {
switch (collision.gameObject.name) {
case "Top":
isTouchTop = false;
break;
case "Bottom":
isTouchBottom = false;
break;
case "Left":
isTouchLeft = false;
break;
case "Right":
isTouchRight = false;
break;
}
}
}
}