ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 플레이어 공격
    연습 프로젝트/2D로그라이크 게임

     

    작업 진행중인 영상 입니다.
    private bool isAttack = false;
    private bool isAttacking = false;
    private float timeBtweenAttack = 0f;
    private float timeSinceAttack = 0f;
    private void Attack()
    {
        timeSinceAttack += Time.deltaTime;
        if (isAttack && timeSinceAttack >= timeBtweenAttack)
        {
            timeSinceAttack = 0;
            playerAnimations.PlayerAttacking();
            if (isAttacking == false)
            {
                Hit(forwardCheck, forwardCheckPos);
                isAttacking = true;
            }
        }
    }

    코드는 "Player Attack" 스크립트에서 진행 하였습니다.

     

    Attack() 함수 내에서 타이머를 정해 주어 공격이 끝나기 전 재 공격을 하는 경우를 방지 하였습니다.

    타이머는 현재 1초로, 1초에 한번 공격 애니메이션을 실행 합니다.

     

    또한 공격 중인지 판단할 Bool 변수 isAttacking 을 이용하여 공격 감지를 반복하는것을 막아 주었습니다.

     

    먼저 애니메이션 부터 보겠습니다.

    public class PlayerAnimations : MonoBehaviour
    {
        [SerializeField] private PlayerJump playerJump;
    
        [SerializeField] private Animator playerAnimator;
    
        [SerializeField] private Rigidbody2D playerRigidbody2D;
    
        private void Update()
        {
            PlayerWalking();
            PlayerJumping();
        }
    
        private void PlayerWalking()
        {
            playerAnimator.SetBool("Walk", playerRigidbody2D.velocity.x != 0 && playerJump.CheckGround());
        }
    
        private void PlayerJumping()
        {
            playerAnimator.SetBool("Jump", !playerJump.CheckGround());
        }
    
        public void PlayerDashing()
        {
            playerAnimator.SetTrigger("Dash");
        }
    
        public void PlayerAttacking()
        {
            playerAnimator.SetTrigger("Attack");
        }
    }

    기존에 만들어 두었던 "PlayerAnimations" 스크립트 입니다.

     

    모든 애니메이션 동작 관련 함수는 PlayerAnimations 스크립트 내에 정의가 되어있습니다.

     

    PlayerAttack 스크립트에서 1초에 한번씩 공격을 할 시 playerAnimations.PlayerAttacking(); 코드로

     

    PlayerAttacking(); 함수가 실행 됩니다.

    플레이어의 애니메이션 컨트롤러 입니다.

     

    현재는 동작 구현이 많지 않아 대기, 걷기, 점프, 대쉬, 공격 으로 5가지 애니메이션이 존재 합니다.

     

    이 후 PlayerAttack 스크립트 내에서

     

    if (isAttacking == false)
    {
        Hit(forwardCheck, forwardCheckPos);
        isAttacking = true;
    }

     

    와 같은 코드로 공격 된 오브젝트를 감지합니다.

     

    감지 할 경우도 반복을 막기 위해 bool 변수인 isAttacking 을 사용 하였으며 기본 상태는 false 입니다.

     

    public void NotIsAttacking()
    {
        isAttacking = false;
    }

    즉시 true가 되어 반복 감지를 막아 버리지만 원래 상태인 False가 되는 로직은 애니메이션의 이벤트를 사용하였습니다.

     

    private void Hit(Transform forwardCheck, Vector2 forwardCheckPos)
    {
        Collider2D collider = Physics2D.OverlapBox(forwardCheck.position, forwardCheckPos, 0, layerMask);
    
        if (collider != null && ((1 << collider.gameObject.layer) & layerMask) != 0)
        {
            MonsterController monsterController = collider.GetComponent<MonsterController>();
            if (monsterController != null)
            {
                monsterController.BeDamaged(playerDamage, (transform.position - collider.transform.position).normalized, 100);
            }
        }
    }

    이 후 마지막으로 감지는 Hit 함수 에서 구현되어 있습니다.

     

    PhysicsOverlabBox를 사용하였고

     

    코드를 보자면 현재 forwardCheck의 포지션을 중심으로 forwardCheckPos 벡터 만큼의 범위를 감지 하며 layerMask에 설정되어 있는 콜라이더만 박스 형태의 범위로 감지 합니다.

     

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireCube(forwardCheck.position, forwardCheckPos);
    }

    이는 에디터 상에서 시각적으로 보기 위한 OnDrawGizmos 함수 입니다.

     

    *지난번 DrawWireLine 처럼 이름에서 유추할 수 있듯이 Cube 형태로 기즈모를 그려 냅니다.

     

    if (collider != null && ((1 << collider.gameObject.layer) & layerMask) != 0)
    {
        MonsterController monsterController = collider.GetComponent<MonsterController>();
        if (monsterController != null)
        {
            monsterController.BeDamaged(playerDamage, (transform.position - collider.transform.position).normalized, 100);
        }
    }

     

    현재 코드는 몬스터에게 데미지를 입히는 코드로

     

    첫번째 조건문인 if문 에서 감지된 콜라이더가 있는지, 또한 레이어가 맞는지 판단한 뒤

     

    감지된 콜라이더에서 GetComponent를 사용하여 MonsterController 라는 스크립트를 받아오게 됩니다.

     

    이후 MonsterController 스크립트 내에 있는 BeDamaged 함수를 사용해 데미지를 입혀줍니다.

     

    특별한 구현은 없지만

     

    transform.position - collider.transform.position).normalized 이 부분을 살펴 보자면

     

    현재 transform (나 자신 player) 에서 감지된 오브젝트의 위치를 빼주어 normalized(방향 벡터) 로 만들어 줍니다.

     

    -1과 1로 오브젝트의 반동을 구현하기 위함 입니다.

     

    using System.Collections;
    using System.Collections.Generic;
    using Unity.VisualScripting;
    using UnityEngine;
    
    public class MonsterController : MonoBehaviour
    {
        [SerializeField] private float monster_Hp;
    
        [SerializeField] private Rigidbody2D monsterRigidbdy2D;
    
        [SerializeField] private float recoilFactor = 0f;
    
        private void Update()
        {
            if (monster_Hp <= 0)
            {
                Destroy(gameObject);
            }
    
        }
    
        public void BeDamaged(float damage, Vector2 dir, float force)
        {
            monster_Hp -= damage;
    
            monsterRigidbdy2D.AddForce(dir * -force * recoilFactor);
    
        }
    }

     

    몬스터에게 입혀져 있는 "MonsterController" 스크립트 입니다.

     

    몬스터도 플레이어와 같이 Rigidbody2D로 구현될 예정이며 매 프레임마다 실행 되는 Update 함수 내에선 몬스터의 Hp가 0보다 작거나 같다면 Destroy 함수를 이용해 없애 주는 모습이고

     

    PlayerAttack 스크립트에서 사용할 BeDamaged 함수에선 플레이어가 공격할 때 감지된 오브젝트(몬스터) 가 있다면 Damage를 깎아 주는 로직과 Rigidbody2D에 AddForce를 이용하여 방향과 힘 그리고 recoilFactor를 조절하여 뒤로 넉백 되는 값을 조절하여 줍니다.

     

    마지막으로 몬스터가 위에서 내려오는 로직은 특별한 기능은 없습니다.

     

    비하인드 스토리

    1. 단순히 몬스터를 비활성화 상태로 y값을 높게 잡아 둔 뒤 영상을 찍으면서 하이어라키 창에서 활성화를 해주었으며

    Rigidbody2D가 입혀져 있어 중력의 영향을 받아 아래로 내려오게 됐습니다.

     

    2. 플레이어와 몬스터의 충돌 감지를 하지 않게 하기 위해 Layer를 정해주고

    Physics

    Layer Collision Matrix를 설정하여 Player와 Monster의 충돌 물리연산을 하지 않게 하였지만 여전히 충돌을 하는 문제가 있었습니다.

    네..

    일반 3D 와 2D 가 따로 있었습니다.

    Physics 2D

    Ctrl + c, v 한 줄..

    '연습 프로젝트 > 2D로그라이크 게임' 카테고리의 다른 글

    UI 정보 패널 & 미니맵  (0) 2024.06.08
    UI 기획 (1차)  (0) 2024.06.08
    몬스터 상태 구현 (Update)  (0) 2024.06.08
    몬스터 상태 구현  (0) 2024.06.07
    플레이어 이동 로직  (0) 2024.06.06

    댓글

김효겸 / Tel. 010-7735-0580 / E-mail. dollzzang2@hanmail.net