1. 실행 이미지

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class BombGuyController : MonoBehaviour
{
    private Rigidbody2D rBody2D;
    [SerializeField] private float jumpForce = 10f; // 점프하는 힘
    [SerializeField] private float moveForce = 30f; // 이동하는 힘
    [SerializeField] private GameObject BombPrefab;
    [SerializeField] private Transform ShootPoint;
    private Animator anim;
    private State currentState = State.Idle;

    private bool isJumping = false;

    private enum State
    {
        Idle,
        Walk,
        Jump
    }

    void Start()
    {
        rBody2D = GetComponent<Rigidbody2D>();
        anim = GetComponentInChildren<Animator>();
        StartCoroutine(HandleMovement());
        StartCoroutine(ShootBomb());
    }

    void Update()
    {
        AdjustAnimationSpeed();
    }

    void AdjustAnimationSpeed()
    {
        float speed = Mathf.Abs(rBody2D.velocity.x);
        float animationSpeed = speed / 2.0f;
        anim.speed = Mathf.Max(1, animationSpeed);
    }
    IEnumerator ShootBomb()
    {
        while (true)
        {
            if (Input.GetKeyDown(KeyCode.A))
            {
                // BombPrefab을 ShootPoint의 위치에 생성하고, 회전은 기본값(Quaternion.identity)으로 설정
                Instantiate(BombPrefab, ShootPoint.transform.position, Quaternion.identity);
            }
            yield return null;
        }
    }


    IEnumerator HandleMovement()
    {
        while (true) // 무한 루프를 사용하여 지속적으로 입력을 체크
        {
            if (Input.GetKey(KeyCode.Space) && !isJumping && Mathf.Abs(rBody2D.velocity.y) <= 0f)
            {
                rBody2D.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
                isJumping = true;
                SetAnimationState(State.Jump);
            }

            int dirX = 0;

            if (Input.GetKey(KeyCode.LeftArrow))
                dirX = -1;

            if (Input.GetKey(KeyCode.RightArrow))
                dirX = 1;

            if (dirX != 0 && !isJumping)
            {
                SetAnimationState(State.Walk);
            }
            else if (!isJumping)
            {
                SetAnimationState(State.Idle);
            }

            transform.localScale = dirX != 0 ? new Vector3(2 * dirX, 2, 1) : transform.localScale;

            if (dirX == 0)
            {
                rBody2D.velocity = new Vector2(0, rBody2D.velocity.y);
            }

            float speedX = Mathf.Abs(rBody2D.velocity.x);
            if (speedX < 2f)
            {
                rBody2D.AddForce(transform.right * dirX * moveForce);
            }

            transform.position = new Vector3(Mathf.Clamp(transform.position.x, -8.2f, 8.4f), transform.position.y, transform.position.z);

            yield return null; // 다음 프레임까지 대기
        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.CompareTag("ground"))
        {
            isJumping = false;
            if (currentState == State.Jump)
            {
                SetAnimationState(State.Idle);
            }
        }
    }

    private void SetAnimationState(State newState)
    {
        if (currentState != newState)
        {
            currentState = newState;
            anim.SetInteger("State", AnimationStateToInt(currentState));
        }
    }

    private int AnimationStateToInt(State state)
    {
        switch (state)
        {
            case State.Idle:
                return 0;
            case State.Walk:
                return 1;
            case State.Jump:
                return 2;
            default:
                return 0;
        }
    }
}

2. BombGuyController.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BombController : MonoBehaviour
{
    private Rigidbody2D rBody2D;
    private Animator anim;
    void Start()
    {
        rBody2D = GetComponent<Rigidbody2D>();
        anim = GetComponentInChildren<Animator>();
        StartCoroutine(BombAnimation());
        
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag("ground"))
        {
            this.rBody2D.gravityScale = 0f;
            this.rBody2D.velocity = Vector3.zero;
        }
    }

    IEnumerator BombAnimation()
    {

        yield return new WaitForSeconds(2f);
        anim.SetInteger("State", 1);
        BoxCollider2D boxCollider = GetComponent<BoxCollider2D>();
        if (boxCollider != null)
        {
            Destroy(boxCollider);
        }

    }

   
}

3. BombController

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyCaptainController : MonoBehaviour
{
    private Rigidbody2D rBody2D;
    private Animator anim;
    [SerializeField] private int HP = 3; // 예시로 HP를 3으로 설정합니다.

    private enum State
    {
        Idle,
        Hit,
        DeadHit
    }

    private State currentState = State.Idle;

    void Start()
    {
        rBody2D = GetComponent<Rigidbody2D>();
        anim = GetComponentInChildren<Animator>();
    }

    void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Bomb"))
        {
            TakeDamage();
        }
    }

    void TakeDamage()
    {
        HP -= 1; // HP를 1 감소
        if (HP <= 0) // DeadHit 상태가 아니면 DeadHit 애니메이션 재생
        {
            SetAnimationState(State.DeadHit);
        }
        else if (HP > 0)
        {
            SetAnimationState(State.Hit); // 아니면 Hit 애니메이션 재생
        }
    }

    private void SetAnimationState(State newState)
    {
        
            currentState = newState;
            anim.SetInteger("State", (int)newState);

 
        
    }

}

4. EnemyCaptainController

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AutoBombDestroy : MonoBehaviour
{
    public void DestroyObject() //이벤트 핸들러 메서드
    {
        GameObject parentObject = gameObject.transform.parent.gameObject;
        Destroy(parentObject);
    }
}

5. AutoBombDestroy.cs

 

using UnityEngine;

public class ReturnIdle : MonoBehaviour
{
    private Animator anim; 

    void Start()
    {
        anim = GetComponent<Animator>();
      
    }

    public void ResetToIdle()
    {
        anim.SetInteger("State", 0); // Idle 상태로 설정

    }
}

6. ReturnIdle.cs

 

 

코루틴 까지는 금방 했는데,

애니메이션 이벤트에서 한번 꼬여가지고 고생한 것 같다.

그래도 막혔던 부분을 해결하니

또 하나 배운 것 같다.

 

적(Captain)이 죽을 떄 넉백되면서 죽게 만들고 싶었는데

자꾸 parameter에서 ignore가 뜨면서 애니메이션 실행에 문제가 발생해서

그 부분이 좀 아쉽긴 하다.

+ Recent posts