Unity
[Unity] 3차 Study : PalyerController Script
mooni_
2024. 3. 11. 19:27
[PlayerController]
변수 선언부
Rigidbody2D rbody; //Rigidbody2D : 오브젝트에 물리적 속성을 더하는 컴포넌트
float axisH = 0.0f; //수평축
public float speed = 3.0f; //이동에 사용할 스피드 값
public float jump = 9.0f; //점프에 사용할 점프력 값
public LayerMask groundLayer; //LayerMask : Layer 자료형, groungLayer를 넣을 예정
bool goJump = false; //점프 개시 플래그
bool onGround = false; //지면 접촉 플래그
Animator animator; //애니메이션 처리
public string stopAnime = "PlayerStop"; //플레이어 정지
public string moveAnime = "PlayerMove"; //플레이어 이동
public string jumpAnime = "PlayerJump"; //플레이어 점프
public string goalAnime = "PlayerGoal"; //플레이어 골인
public string deadAnime = "PlayerOver"; //플레이어 Dead,,,
string nowAnime = ""; //현재 애니메이션
string oldAnime = ""; //이전 애니메이션
public static string gameState = "playing"; //게임 상태 초기값 playing
public int score = 0; //시작 점수 0
Start()
void Start()
{
rbody = this.GetComponent<Rigidbody2D>(); //현재 오브젝트의 물리적 속성 가져오기
animator = GetComponent<Animator>(); //현재 오브젝트의 Animator 가져오기
nowAnime = stopAnime; //시작 애니메이션은 stopAnime
oldAnime = stopAnime;
gameState = "playing"; //시작 상태는 playing
}
Update()
void Update()
{
if(gameState != "playing") //게임이 playing 상태가 아니면 아무것도 반환하지 않음
{
return;
}
axisH = Input.GetAxisRaw("Horizontal"); //GetAisRaw -1(방향키좌), 1(방향키우)
if (axisH > 0.0f) //수평축이 0.0f(기본값)보다 크면 == 1이면
{
Debug.Log("오른쪽 이동");
transform.localScale = new Vector2(1, 1);
//Scale = 1(x), 1(y)
}
else if(axisH < 0.0f) //수평축이 0.0f(기본값)보다 작으면 == -1이면
{
Debug.Log("왼쪽 이동");
transform.localScale = new Vector2(-1, 1);
//Scale = -1(x), 1(y) 좌우반전
}
if(Input.GetButtonDown("Jump")) //Jump 버튼 == Spacebar
{
Jump(); //Jump() 실행
}
}
여러번 정리했지만 한번 더 해서 나쁠 건 없으니까 정리해봄
Input.GetAxis : -1 ~ 1 사이의 값을 받아옴
Input.GetAxisRaw : -1, 0, 1 중 하나의 값을 받음
위의 인수에 대해서
Horizontal : 수평축 → 좌우 방향키
Vertical : 수직축 → 위아래 방향키
FixedUpdate()
void FixedUpdate()
{
if(gameState != "playing") //상태가 playing이 아니면 아래 코드 미실행
{
return;
}
onGround = Physics2D.Linecast(transform.position, transform.position - (transform.up * 0.1f), groundLayer);
//Ground Layer 접촉 여부를 담음
//Linecast(시작, 끝, 대상 레이어)
if(onGround || axisH != 0) //접촉했거나 좌, 우 이동이 있다면 Rigidbody.velocity 값 갱신
{
rbody.velocity = new Vector2(speed * axisH, rbody.velocity.y);
}
if(onGround && goJump) //접촉과 점프 플래그가 true면 점프, AddForce 활용
{
Debug.Log("점프!");
Vector2 jumpPw = new Vector2(0, jump);
rbody.AddForce(jumpPw, ForceMode2D.Impulse);
goJump = false;
}
//애니메이션
if (onGround) //지면 접촉 상태
{
if (axisH == 0) //좌우 방향키의 입력이 없으면 stopAnime
{
nowAnime = stopAnime;
}
else //이동 중이면 moveAnime
{
nowAnime = moveAnime;
}
}
else //지면 미접촉 상태면 jumpAnime
{
nowAnime = jumpAnime;
}
if (nowAnime != oldAnime) //애니메이션이 변경 되었으면 now, old 변수 업데이트
{
oldAnime = nowAnime;
animator.Play(nowAnime);
}
}
Jump()
public void Jump()
{
goJump = true;
Debug.Log("점프 버튼 눌림!");
}
Jump의 전체 흐름
1. Update()에서 키 입력 여부 확인
2. Jump() 실행 → goJump 플래그 true로 변경
3. FixedUpdate()에서 실질적인 점프 효과를 줌
OnTriggerEnter2D(Collider2D collision)
private void OnTriggerEnter2D(Collider2D collision) //충돌 시작할 때 호출
{
if(collision.gameObject.tag == "Goal") //Goal 태그 오브젝트와 충돌 시 Goal() 실행
{
Goal();
}
else if(collision.gameObject.tag == "Dead") //Dead 태그 오브젝트와 충돌 시 GameOver() 실행
{
GameOver();
}
else if(collision.gameObject.tag == "ScoreItem") //ScoreItem 태그 오브젝트와 충돌 시
{
ItemData item = collision.gameObject.GetComponent<ItemData>();
//ItemData script에서 충돌한 아이템을 받아옴
score = item.value;
//해당 아이템의 value를 score에 저장 후에 GameManager script에서 점수 계산
Destroy(collision.gameObject); //아이템 오브젝트 제거
}
}
[오브젝트 충돌 처리]
OnTriggerEnter2D(Collider2D other) : 충돌이 일어날때 처음 한번만 호출
OnTriggerStay2D(Collider2D other) : 충돌이 일어나는 동안 지속적으로 호출
OnTriggerExit2D(Collider2D other) : 충돌에서 벗어날때 한번 호출
조건! 충돌하는 오브젝트들은 Collider 컴포넌트를 갖고 있어야하고 적어도 하나는 RigidBody 컴포넌트도 가져야함
Goal() GameOver() GameStop()
public void Goal()
{
animator.Play(goalAnime); //goal 애니메이션 play
gameState = "gameclear"; //상태 gameclear로 변경
GameStop(); //GameStop() 실행
}
public void GameOver()
{
animator.Play(deadAnime); //dead 애니메이션 play
gameState = "gameover"; //상태 gameover로 변경
GameStop(); //GameStop() 실행
GetComponent<CapsuleCollider2D>().enabled = false;
//플레이어의 CapusalCollider2D 비활성화 => 지면과 상관없이 아래로 떨어짐
rbody.AddForce(new Vector2(0, 5), ForceMode2D.Impulse); //튀어오르는 효과
}
public void GameStop()
{
Rigidbody2D rbody = GetComponent<Rigidbody2D>(); //물리적 속성을 받아서
rbody.velocity = new Vector2(0, 0); //velocity 0, 0으로 설정
}
그런데 GameStop()에서 rbody는 또 선언할 필요가 없지 않나...? 이미 Start()에서 받아왔는걸...
*교재 : 누구나 할 수 있는 유니티 2D 게임 제작