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 게임 제작