본문 바로가기

Development/[Game] Basic Game

[Game] #4. 충돌 및 사냥 구현

728x90
반응형

이전 포스팅 복습 및 목표

이전 포스팅에서는 몬스터의 애니메이션 구현과 AI를 만들어보았다. 이번 포스팅에서는 플레이어가 몬스터를 잡고, 코인을 얻으며 도착 지점으로 도착 시 다음 스테이지로 넘어가는 것을 구현해보자.

https://udangtangtang-cording-oldcast1e.tistory.com/118

 

[Game] #3. AI 구현

지난 포스팅 복습 저번 포스팅에서는 타일 팔레트를 설정하여 타일을 사용하기 위해 모아둔 프리 펩 / 타일 맵을 사용하기 위한 준비단계를 진행했고, 타일 팔레트를 이용하여 지형을 빠르게 생

udangtangtang-cording-oldcast1e.tistory.com

이번 포스팅의 목표는 다음과 같다.

  1. 플레이어가 몬스터를 사냥한다.
  2. 플레이어가 코인을 얻는다.
  3. 도착 지점에 도달 시 새로운 스테이지로 이동한다.

동전 접촉 구현

다음 코드를 OnCollisionEnter2D 함수에 작성한다.

if (collision.gameObject.tag == "Coin"){
    Destory(collision.gameObject);
}

도착지 접촉 구현

else if (collision.gameObject.tag == "Finish"){
    Destroy(collision.gameObject);
}

도착지에 도착 시 다음 스테이지를 불러와야한다. 이는 게임 메니저에서 구현한다.

몬스터와의 충돌 구현

몬스터와 충돌 시 몬스터와 충돌한 반대 방향으로 튕겨나는 충돌 메서드를 구현해보자.

private void OnCollisionEnter2D(Collision2D collision) {
    if (collision.gameObject.tag == "Enemy") {
        //Attack - 3.22
        Debug.Log("Enemy Connect!");
        if(rigid.velocity.y<0 && transform.position.y > collision.transform.position.y){

        }
        else OnDamaged(collision.transform.position); //Damaged - 3.22
    }
}
if (collision.gameObject.tag == "Enemy") 

위의 조건문에 의해 Enemy라는 태그를 가진 오브젝트와 충돌 시 디버그 메시지를 출력하고 다음과 같은 조건을 실행한다.

1. (rigid.velocity.y<0 && transform.position.y > collision.transform.position.y) 

: 플레이어의 y방향 속도가 0보다 작고(낙하 중) y 방향에서 collision 충돌이 일어난 경우

2. else

:  조건 (1)을 만족하지 않는 충돌인 경우

1  
2  
public void OnDamaged(Vector2 TargetPos){//-3.22
    //Change Layer
    gameObject.layer = 11;
    //Sprite Alpha
    spriteRenderer.color = new Color(1,1,1,0.4f);
    //Readctio Force 3.22
    int dirc = transform.position.x - TargetPos.x > 0 ?1:-1;
    rigid.AddForce(new Vector2(dirc,1)*5,ForceMode2D.Impulse);

	animator.SetTrigger("Die"); //- 3.25
    Invoke("OffDamaged",3);
}
gameObject.layer = 11;

게임 오브젝트의 레이어를 11로 만들어 일종의 무적을 표현한다.

spriteRenderer.color = new Color(1,1,1,0.4f);

int dirc = transform.position.x - TargetPos.x > 0 ?1:-1;
rigid.AddForce(new Vector2(dirc,1)*5,ForceMode2D.Impulse);
  • 캐릭터의 스프라이트 색상을 (1,1,1,0.4f)으로 변경한다. (흐릿하게 표현한다.)
  • 플레이어 캐릭터의 x 방향을 변경한다.
  • 플레이어 캐릭터에 설정한 방향으로 힘을 부여한다.
Invoke("OffDamaged",3);

3초 후 캐릭터의 무적 해제를 실행한다.

void OffDamaged(){
    gameObject.layer = 10;
    spriteRenderer.color = new Color(1,1,1,1);
}

플레이어의 레이어를 원상태로 복귀하고 스프라이트의 색을 되돌린다.

몬스터 사냥하기

몬스터 위에 플레이어가 착지하면 몬스터를 죽이는 코드를 제작해보자. 이를 위해선 onCollision 함수와 OnAttcak, 그리고 OnDamaged함수를 새로 생성한다.

onCollisionEnter2D

콜리션 충돌 발생 시, 충돌한 오브젝트의 태그가 Enemy 인경우 다음 조건문을 수행한다.

  1. 디버그 창에 Debug.Log("Enemy Connect!"); 을 출력한다.
  2. 플레이이어의 y 방향 속도가 0보다 작고 위치가 충돌한 위치보다 큰 경우 조건문 수행
  3. 2번 조건을 만족시키지 못한 경우 Ondamaged 함수 실행
private void OnCollisionEnter2D(Collision2D collision) {
    if (collision.gameObject.tag == "Enemy") {
        //Attack - 3.22
        Debug.Log("Enemy Connect!");
        if(rigid.velocity.y<0 && transform.position.y > collision.transform.position.y){
            OnAttack(collision.transform);
        }
        else OnDamaged(collision.transform.position); //Damaged - 3.22

    }
    if (collision.gameObject.tag == "Coin"){
        Destroy(collision.gameObject);
    }
}

OnAttcak

충돌 발생시 사용할 함수이다. 인자로는 enemy의 Trasfrom을 갖는다.

  1. 플레이어에 (Vector2.up * 10,ForceMode2D.Impulse) 만큼의 힘을 부여한다.
  2. EnemyMove 객체를 가지는 enemyMove 변수에 컴포넌트를 할당한다.
  3. EnemyMove에 대해 OnDamaged 함수를 실행한다.
void OnAttack(Transform enemy){
    //Point

    //REaction Force
    rigid.AddForce(Vector2.up * 10,ForceMode2D.Impulse);
    //Enemy Die
    EnemyMove enemyMove = enemy.GetComponent<EnemyMove>();
    enemyMove.OnDamaged();
}

OnDamaged

[PlayerMove 코드]

몬스터 죽은 함수에는 죽었을 때 취해야하는 액션을 구현한다.

해당 함수를 만들기 전에 코드 위 부분에 CircleCollider 컴포넌트를 생성한다.

private CircleCollider2D Coliider;

아래 코드는 Vector2를 인자값으로 받으며, 스프라이트의 상태를 변경한다.

void OnDamaged(Vector2 TargetPos){//-3.22
    //Sprite Alpha
    spriteRenderer.color = new Color(1,1,1,0.4f);
    //Sprite Flip Y
    spriteRenderer.flipY = true;
    //Collider Disable
    Coliider.enabled = false;
    //Die Effect Jump
    rigid.AddForce(Vector2.up * 5, ForceMode2D.Impulse);
    //Destroy
    Invoke("DeActive",5);

}

void DeActive(){
    gameObject.SetActive(false);
}

이때, 충돌 발생시 사용할 함수인 OnAttack 시 인자로서 Enemy를 가지므로 EnemyMove의 코드로 수정이 필요하다.

[EnemyMove 코드 수정]

추가된 함수와 기능은 다음과 같다.

함수 이름 기능
OnDamaged
 
스프라이트의 컬러를 변경한다.
스프라이트의 레이어를 변경한다.
스프라이트의 콜라이더를 비활성화한다.
리지드 바이에 힘을 부여한다.
DeActive 함수를 실행한다.
DeActive
게임 오브젝트를 비활성화한다.
using UnityEngine;

public class EnemyMove : MonoBehaviour
{
    // Start is called before the first frame update
    private Rigidbody2D EnemyRigd; //물리이동을 위한 변수 선언 
    private SpriteRenderer spriteRenderer; //방향전환을 위한 변수 
    private Animator Enemyanimator; //애니메이터 조작을 위한 변수 
    private Transform EnemyTransform; //애니메이터 조작을 위한 변수 
    private CircleCollider2D EnemyColider;

    public int NextMove;

    void Start()
    {
        EnemyRigd = GetComponent<Rigidbody2D>();
        EnemyTransform = GetComponent<Transform>();
        spriteRenderer = GetComponent<SpriteRenderer>(); // 초기화 
        EnemyColider = GetComponent<CircleCollider2D>();
        NextMove = Random.Range(-1,2);
        Invoke("Think",5); 
    }
    // Update is called once per frame
    void Update()
    {   
        //Move
        EnemyRigd.velocity = new Vector2(NextMove,EnemyRigd.velocity.y);

        //Platform Check
        Vector2 frontVec = new Vector2(EnemyRigd.position.x+NextMove,EnemyRigd.position.y);
        Debug.DrawRay(frontVec, Vector3.down, new Color(0,1,0)); //빔을 쏨(디버그는 게임상에서보이지 않음 ) 시작위치, 어디로 쏠지, 빔의 색 
        // float EnemyRay = (frontVec>0)?(frontVec-0.5f):frontVec+(0.5f);
        RaycastHit2D rayHit = Physics2D.Raycast(frontVec, Vector3.down, 1, LayerMask.GetMask("Platform"));
        //빔의 시작위치, 빔의 방향 , 1:distance , ( 빔에 맞은 오브젝트를 특정 레이어로 한정 지어야할 때 사용 ) // RaycastHit2D : Ray에 닿은 오브젝트 클래스 
        if(rayHit.collider == null){ //빔을 맞은 오브젝트가 있을때  -> 맞지않으면 collider도 생성되지않음 
            // Debug.Log("Danger!");
            NextMove *= -1;
            CancelInvoke();
            Invoke("Think",5);
        }

        //Diection
        if(NextMove==1) transform.localScale = new Vector3(-1, 1, 1); // 왼쪽 바라보기
        else if(NextMove== -1) EnemyTransform.localScale = new Vector3(1, 1, 1);
    }
    void Think(){
        NextMove = Random.Range(-1,2);

        // EnemyRigd.velocity = new Vector2(NextMove,EnemyRigd.velocity.y);
        
        float nextThinkTime = Random.Range(2f,5f);
        Invoke("Think",nextThinkTime);
    }

    public void OnDamaged(){
        //Sprite Alpha
        spriteRenderer.color = new Color(1,1,1,0.4f);
        //Sprite Flip Y
        spriteRenderer.flipY = true;
        //Collider Disable
        EnemyColider.enabled = false;
        //Die Effect Jump
        EnemyRigd.AddForce(Vector2.up * 5, ForceMode2D.Impulse);
        // //Destroy
        Invoke("DeActive",5);
    }

    void DeActive(){
        gameObject.SetActive(false);
    }

    
}

완성된 충돌 메서드 구현: Enemy 컴포넌트

728x90
반응형

'Development > [Game] Basic Game' 카테고리의 다른 글

[Game] #7. 게임 UI 생성 및 완성  (0) 2022.03.29
[Game] #5. 게임 메니저  (0) 2022.03.29
[Game] #3. AI 구현  (0) 2022.03.20
[Game] #2. 게임 UI 및 팔레트  (0) 2022.03.20
[Game] #1. 새로운 프로젝트  (0) 2022.03.20
댓글