일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 2023년
- 골드메탈
- 2025년
- 수학
- 개인 프로젝트
- 3월
- 기초
- 1월
- 2월
- 입문
- 코딩 테스트
- 2024년
- 단계별로 풀어보기
- 유니티 심화과정
- 4월
- 개인 프로젝트 - 런앤건
- 코딩 기초 트레이닝
- 백준
- 자료 구조
- 10월
- c++
- 유니티
- 5월
- todolist
- 2022년
- C/C++
- 프로그래머스
- 게임 엔진 공부
- 다이나믹 프로그래밍
- 7월
- Today
- Total
기록 보관소
[Unity/유니티] 기초-2D 플랫포머: 플레이어 점프 구현하기[B16] 본문
개요
유니티 입문과 독학을 위해서 아래 링크의 골드메탈님의 영상들을 보며 진행 상황 사진 또는 캡처를 올리고 배웠던 점을 요약해서 적는다.
현재는 영상들을 보고 따라하고 배우는 것에 집중할 것이며, 영상을 모두 보고 따라한 후에는 개인 프로젝트를 설계하고 직접 만드는 것이 목표다.
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 플랫포머: 플레이어 점프 구현하기[B16]
1. 물리력에 의한 점프
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
public float maxSpeed;
public float jumpPower;
Rigidbody2D rigid;
SpriteRenderer spriteRenderer;
Animator anim;
void Awake() {
rigid = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
rigid.freezeRotation = true; //이동시 굴러가기 방지
}
void Update() {
//점프
if (Input.GetButtonDown("Jump")) //스페이스바
rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
//멈출 때 속도
if (Input.GetButtonUp("Horizontal")) {
//normalized : 벡터 크기를 1로 만든 상태
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
}
//방향 전환
if (Input.GetButton("Horizontal"))
spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1; //-1은 왼쪽 방향
//애니메이션 전환
if (Mathf.Abs(rigid.velocity.x) < 0.3) //정지 상태, Mathf : 수학관련 함수를 제공하는 클래스
anim.SetBool("isWalking", false);
else
anim.SetBool("isWalking", true);
}
void FixedUpdate() {
float h = Input.GetAxisRaw("Horizontal"); //좌,우 A, D
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
//오른쪽 속도 조절
if (rigid.velocity.x > maxSpeed) //velocity : 리지드바디의 현재 속도
rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y); //y축 값을 0으로 하면 멈춤
//왼쪽 속도 조절
else if (rigid.velocity.x < maxSpeed*(-1))
rigid.velocity = new Vector2(maxSpeed * (-1), rigid.velocity.y);
}
}
- 실행해보니 점프는 잘 되지만, 내려올때 공기 저항 값(Linear Drag)때문에 속도가 느리다. 이는 Project Settings의 Physics 2D 설정에서 Gravity Y값을 바꿔서 해결할 수 있다.
- 다만 위 방법의 경우 전반적인 프로젝트 설정을 변경하는 것이 문제다. 원하는 스프라이트의 중력 비율만 조정하고 싶다면, 해당 스프라이트의 중력 값(Rigidbody 2D의 Gravity Scale 값)을 바꾸면 된다. 참고로 Gravity Scale은 비율 값이라서 기본 값 1은 100%가 된다.
2. 점프-착지 애니메이션
- Animator에서 isJumping 매개변수와 이전에 만들어두었던 isWalking을 사용하면된다.
- Walk -> Jump : isWalking = true | isJumping = true
- Jump -> Walk : isWalking = true | isJumping = false
- Idle -> Jump : isWalking = false | isJumping = true
- Jump -> Idle : isWalking = false | isJumping = false
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
public float maxSpeed;
public float jumpPower;
Rigidbody2D rigid;
SpriteRenderer spriteRenderer;
Animator anim;
void Awake() {
rigid = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
rigid.freezeRotation = true; //이동시 굴러가기 방지
}
void Update() {
//점프
if (Input.GetButtonDown("Jump")) { //스페이스바
rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
anim.SetBool("isJumping", true); //Jump 애니메이션 추가
}
//멈출 때 속도
if (Input.GetButtonUp("Horizontal")) {
//normalized : 벡터 크기를 1로 만든 상태
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
}
//방향 전환
if (Input.GetButton("Horizontal"))
spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1; //-1은 왼쪽 방향
//애니메이션 전환
if (Mathf.Abs(rigid.velocity.x) < 0.3) //정지 상태, Mathf : 수학관련 함수를 제공하는 클래스
anim.SetBool("isWalking", false);
else
anim.SetBool("isWalking", true);
}
void FixedUpdate() {
float h = Input.GetAxisRaw("Horizontal"); //좌,우 A, D
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
//오른쪽 속도 조절
if (rigid.velocity.x > maxSpeed) //velocity : 리지드바디의 현재 속도
rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y); //y축 값을 0으로 하면 멈춤
//왼쪽 속도 조절
else if (rigid.velocity.x < maxSpeed*(-1))
rigid.velocity = new Vector2(maxSpeed * (-1), rigid.velocity.y);
}
}
3. 레이캐스트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
public float maxSpeed;
public float jumpPower;
Rigidbody2D rigid;
SpriteRenderer spriteRenderer;
Animator anim;
void Awake() {
rigid = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
rigid.freezeRotation = true; //이동시 굴러가기 방지
}
void Update() {
//점프
if (Input.GetButtonDown("Jump")) { //스페이스바
rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
anim.SetBool("isJumping", true); //Jump 애니메이션 추가
}
//멈출 때 속도
if (Input.GetButtonUp("Horizontal")) {
//normalized : 벡터 크기를 1로 만든 상태
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
}
//방향 전환
if (Input.GetButton("Horizontal"))
spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1; //-1은 왼쪽 방향
//애니메이션 전환
if (Mathf.Abs(rigid.velocity.x) < 0.3) //정지 상태, Mathf : 수학관련 함수를 제공하는 클래스
anim.SetBool("isWalking", false);
else
anim.SetBool("isWalking", true);
}
void FixedUpdate() {
float h = Input.GetAxisRaw("Horizontal"); //좌,우 A, D
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
//오른쪽 속도 조절
if (rigid.velocity.x > maxSpeed) //velocity : 리지드바디의 현재 속도
rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y); //y축 값을 0으로 하면 멈춤
//왼쪽 속도 조절
else if (rigid.velocity.x < maxSpeed*(-1))
rigid.velocity = new Vector2(maxSpeed * (-1), rigid.velocity.y);
//레이캐스트
Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0)); //레이 표시
RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1); //레이에 닿는 물체
if (rayHit.collider != null) { //레이에 닿는 물체가 있다면
Debug.Log(rayHit.collider.name); //물체 이름 콘솔창에 출력
}
}
}
- RayCast : 오브젝트 검색을 위해 Ray를 쏘는 방식
- DrawRay(위치, 방향, 색상) : 에디터 상에서만 Ray를 그려주는 함수
- RayCastHit : Ray에 닿은 오브젝트. 해당 변수의 콜라이더로 검색 확인 가능.
- 콘솔창에 Floor는 나오지 않고 Player만 출력되는 이유는 RayHit가 관통이 되지 않기 때문이다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
public float maxSpeed;
public float jumpPower;
Rigidbody2D rigid;
SpriteRenderer spriteRenderer;
Animator anim;
void Awake() {
rigid = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
rigid.freezeRotation = true; //이동시 굴러가기 방지
}
void Update() {
//점프
if (Input.GetButtonDown("Jump")) { //스페이스바
rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
anim.SetBool("isJumping", true); //Jump 애니메이션 추가
}
//멈출 때 속도
if (Input.GetButtonUp("Horizontal")) {
//normalized : 벡터 크기를 1로 만든 상태
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
}
//방향 전환
if (Input.GetButton("Horizontal"))
spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1; //-1은 왼쪽 방향
//애니메이션 전환
if (Mathf.Abs(rigid.velocity.x) < 0.3) //정지 상태, Mathf : 수학관련 함수를 제공하는 클래스
anim.SetBool("isWalking", false);
else
anim.SetBool("isWalking", true);
}
void FixedUpdate() {
float h = Input.GetAxisRaw("Horizontal"); //좌,우 A, D
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
//오른쪽 속도 조절
if (rigid.velocity.x > maxSpeed) //velocity : 리지드바디의 현재 속도
rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y); //y축 값을 0으로 하면 멈춤
//왼쪽 속도 조절
else if (rigid.velocity.x < maxSpeed*(-1))
rigid.velocity = new Vector2(maxSpeed * (-1), rigid.velocity.y);
//레이캐스트
Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0)); //레이 표시
RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1, LayerMask.GetMask("Platform")); //레이에 닿는 물체
if (rayHit.collider != null) { //레이에 닿는 물체가 있다면
Debug.Log(rayHit.collider.name); //물체 이름 콘솔창에 출력
}
}
}
- LayerMask : 물리 효과를 구분하는 정수값
- LayerMask.GetMask() : 레이어 이름에 해당하는 정수값을 리턴하는 함수
- .distance : Ray에 닿았을 때의 거리
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
public float maxSpeed;
public float jumpPower;
Rigidbody2D rigid;
SpriteRenderer spriteRenderer;
Animator anim;
void Awake() {
rigid = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
rigid.freezeRotation = true; //이동시 굴러가기 방지
}
void Update() {
//점프
if (Input.GetButtonDown("Jump")) { //스페이스바
rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
anim.SetBool("isJumping", true); //Jump 애니메이션 추가
}
//멈출 때 속도
if (Input.GetButtonUp("Horizontal")) {
//normalized : 벡터 크기를 1로 만든 상태
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
}
//방향 전환
if (Input.GetButton("Horizontal"))
spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1; //-1은 왼쪽 방향
//애니메이션 전환
if (Mathf.Abs(rigid.velocity.x) < 0.3) //정지 상태, Mathf : 수학관련 함수를 제공하는 클래스
anim.SetBool("isWalking", false);
else
anim.SetBool("isWalking", true);
}
void FixedUpdate() {
float h = Input.GetAxisRaw("Horizontal"); //좌,우 A, D
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
//오른쪽 속도 조절
if (rigid.velocity.x > maxSpeed) //velocity : 리지드바디의 현재 속도
rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y); //y축 값을 0으로 하면 멈춤
//왼쪽 속도 조절
else if (rigid.velocity.x < maxSpeed*(-1))
rigid.velocity = new Vector2(maxSpeed * (-1), rigid.velocity.y);
//점프 후 착지시 애니메이션 전환(레이캐스트)
if (rigid.velocity.y < 0) { //y축 속도 값이 0보다 클때만. 땅에 있으면 레이 표시 X
Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0)); //레이 표시
RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1, LayerMask.GetMask("Platform")); //레이에 닿는 물체
if (rayHit.collider != null) //레이에 닿는 물체가 있다면
if (rayHit.distance < 0.5f)
anim.SetBool("isJumping", false);
}
}
}
4. 무한 점프 막기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMove : MonoBehaviour {
public float maxSpeed;
public float jumpPower;
Rigidbody2D rigid;
SpriteRenderer spriteRenderer;
Animator anim;
void Awake() {
rigid = GetComponent<Rigidbody2D>();
spriteRenderer = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
rigid.freezeRotation = true; //이동시 굴러가기 방지
}
void Update() {
//점프
if (Input.GetButtonDown("Jump") && !anim.GetBool("isJumping")) { //스페이스바, 점프 애니메이션이 작동중이지 않다면
rigid.AddForce(Vector2.up * jumpPower, ForceMode2D.Impulse);
anim.SetBool("isJumping", true); //Jump 애니메이션 추가
}
//멈출 때 속도
if (Input.GetButtonUp("Horizontal")) {
//normalized : 벡터 크기를 1로 만든 상태
rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
}
//방향 전환
if (Input.GetButton("Horizontal"))
spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1; //-1은 왼쪽 방향
//애니메이션 전환
if (Mathf.Abs(rigid.velocity.x) < 0.3) //정지 상태, Mathf : 수학관련 함수를 제공하는 클래스
anim.SetBool("isWalking", false);
else
anim.SetBool("isWalking", true);
}
void FixedUpdate() {
float h = Input.GetAxisRaw("Horizontal"); //좌,우 A, D
rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
//오른쪽 속도 조절
if (rigid.velocity.x > maxSpeed) //velocity : 리지드바디의 현재 속도
rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y); //y축 값을 0으로 하면 멈춤
//왼쪽 속도 조절
else if (rigid.velocity.x < maxSpeed*(-1))
rigid.velocity = new Vector2(maxSpeed * (-1), rigid.velocity.y);
//점프 후 착지시 애니메이션 전환(레이캐스트)
if (rigid.velocity.y < 0) { //y축 속도 값이 0보다 클때만. 땅에 있으면 레이 표시 X
Debug.DrawRay(rigid.position, Vector3.down, new Color(0, 1, 0)); //레이 표시
RaycastHit2D rayHit = Physics2D.Raycast(rigid.position, Vector3.down, 1, LayerMask.GetMask("Platform")); //레이에 닿는 물체
if (rayHit.collider != null) //레이에 닿는 물체가 있다면
if (rayHit.distance < 0.5f)
anim.SetBool("isJumping", false);
}
}
}
- 간단하게 점프 애니메이션에서 사용하는 isJumping 매개변수를 사용하여 false일때만 점프 키가 작동하도록 설정하면 무한 점프를 해결할 수 있다.
'유니티 프로젝트 > 2D 플랫포머' 카테고리의 다른 글
[Unity/유니티] 기초-2D 플랫포머: 몬스터 AI 구현하기[B18] (0) | 2022.02.13 |
---|---|
[Unity/유니티] 기초-2D 플랫포머: 타일맵으로 플랫폼 만들기[B17] (0) | 2022.02.13 |
[Unity/유니티] 기초-2D 플랫포머: 플레이어 이동 구현하기[B15] (0) | 2022.02.10 |
[Unity/유니티] 기초-2D 플랫포머: 아틀라스와 애니메이션[B14] (0) | 2022.02.09 |
[Unity/유니티] 기초-2D 플랫포머: 프로젝트 준비하기[B13] (0) | 2022.02.08 |