1단계 보스 공격Patern01

* 1단계 보스의 첫 번째 공격 패턴이 생성됩니다. 어제 보스의 스프라이트를 뒤집을 때 콜라이더 영역이 뒤집히지 않아 원본 콜라이더와 뒤집힌 콜라이더 오브젝트가 활성화/비활성화 되는 문제가 있었는데 비효율적이었습니다(보스 오브젝트가 다른 오브젝트를 자식 오브젝트로 가지고 있는 경우) , 모두 동일하게 제어해야 하므로 비효율적임)

그래서 이를 해결하기 위해 보스 오브젝트의 회전값을 -180으로 수정했습니다.

*첫 번째 공격 패턴은 총알이 360도 방향으로 뻗어나가는 방식입니다. 먼저 최적화를 위한 오브젝트 풀링 스크립트를 생성한 후 글머리 기호를 생성했습니다.

using System.Collections.Generic;
using UnityEngine;

public class BulletPool : MonoBehaviour
{
    public static BulletPool instance; //인스턴스화

    (SerializeField)
    private GameObject pooledBullet;
    private bool notEnoughBulletsInPool = true;

    private List<GameObject> bullets;

    private void Awake()
    {
        instance = this;
    }
    void Start()
    {
        this.bullets = new List<GameObject>(); //List초기화 
    }

    public GameObject GetBullet()
    {
        if (this.bullets.Count > 0)
        {
            for (int i = 0; i < this.bullets.Count; i++)
            {
                if (!this.bullets(i).activeInHierarchy) //부모 오브잭트의 활성화 체크
                {
                    return this.bullets(i);
                }
            }
        }

        if (this.notEnoughBulletsInPool)
        {
            GameObject bul = Instantiate(this.pooledBullet);
            bul.SetActive(false);
            this.bullets.Add(bul);
            return bul;
        }
        return null;
    }
}

*보스오브젝트에서 발사되는 총알이 자연스럽지 않아서 파이어포인트오브젝트를 어린아이로 넣어놓고 거기에서 쏘도록 했습니다.


*bullet 객체는 SetMoveDirection()입니다. 메서드를 정의하고 “Vector2 dir”을 매개변수로 받아 총알의 방향(“Direction”)을 결정했습니다.

일정 시간이 지나면 총알 프리팹이 자동으로 파괴됩니다. 파괴하다(); 메서드를 만들고 호출 Invoke(“Destroy”, 3f); 구성 요소가 활성화될 때 호출되도록 OnEnabled에서 호출됩니다.

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

public class FireWormBullet : MonoBehaviour
{
    private Vector2 moveDirection;
    private float moveSpeed;
    private void OnEnable() //컴포넌트 활성 시 호출
    {
        Invoke("Destroy", 3f);
    }
    private void Start()
    {
        this.moveSpeed = 5f;
    }
    void Update()
    {
        this.transform.Translate(this.moveDirection * this.moveSpeed * Time.deltaTime);
    }
    public void SetMoveDirection(Vector2 dir)
    {
        this.moveDirection = dir;
    }
    private void Destroy()
    {
        this.gameObject.SetActive(false);
    }
    private void OnDisable() //컴포넌트 비활성 화 시 호출
    {
        CancelInvoke(); 
    }
}

*어제 만든 보스 스크립트에서 AttackPattern01(); 방법을 정의하고 첫 번째 공격 패턴을 구현했습니다.

bulletAmount 변수에 발사할 총알의 수를 설정하고 startAngle=0f, endAngle=360f를 정의하여 총알이 360도 방향으로 발사되도록 합니다. 또한 float angleStep = (endAngle – startAngle) / bulletsAmount; 발사되는 총알 사이의 간격이 결정되었습니다. 자세한 내용은 스크립트를 참조하십시오.

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

public class FireWorm : MonoBehaviour
{
    private enum eState
    {
        Idle, //0
        Walk, //1
        Attack, //2
        Death, //3
        GetHit, //4
    }
    public Transform player;
    public float bossMoveSpeed = 2.5f;
    private Rigidbody2D rb;

    public GameObject firePoit;

    //animator(State)
    private Animator anim;

    private void Awake()
    {
        this.rb = this.GetComponent<Rigidbody2D>();
        this.anim = this.GetComponent<Animator>();

        this.anim.SetInteger("state", (int)eState.Idle);
    }
    private void Start()
    {
        InvokeRepeating("AttackPattern01", 2f, 2f);
    }
    private void FixedUpdate()
    {
        Vector2 direction=this.player.position-this.transform.position;

        if(direction.magnitude>1f)
        {
            direction.Normalize();
        }

        this.rb.velocity = direction*this.bossMoveSpeed;

        if(this.rb.velocity.x!=0f)
        {
            Debug.Log("Walk");
            this.anim.SetInteger("stat",(int)eState.Walk);
        }

       

        if (this.player.position.x < this.transform.position.x)
        {
            this.transform.rotation = Quaternion.Euler(0f, -180f, 0f);
        }
        else
        {
            this.transform.rotation= Quaternion.identity;
        }

       
    }

    //AttackPattern01
    private void AttackPattern01()
    {
        int bulletsAmount = 20;
        float startAngle = 0f; //시작 각도
        float endAngle = 360f; //끝나는 각도
        float angleStep = (endAngle - startAngle) / bulletsAmount; //bullet의 간격
        float angle = startAngle;

        for (int i = 0; i < bulletsAmount; i++)
        {
            float bulDirX = transform.position.x + Mathf.Sin((angle * Mathf.PI) / 180f);
            float bulDirY = transform.position.y + Mathf.Cos((angle * Mathf.PI) / 180f);

            Vector3 bulMoveVector = new Vector3(bulDirX, bulDirY, 0f);
            Vector2 bulDir = (bulMoveVector - transform.position).normalized;

            GameObject bul = BulletPool.instance.GetBullet();
            bul.transform.position = this.firePoit.transform.position;
            bul.transform.rotation = this.firePoit.transform.rotation;
            bul.SetActive(true);
            bul.GetComponent<FireWormBullet>().SetMoveDirection(bulDir);
            angle += angleStep;
        }

        this.anim.SetInteger("stat", 2);
    }

    ////Test
    //private void OnTriggerEnter2D(Collider2D collision)
    //{
    //    if(collision.CompareTag("Player"))
    //    {
    //        Debug.Log("Player");
    //    }
    //}


}

*애니메이션 타이밍이 맞지 않는 문제가 있습니다. 애니메이션 클립을 보면 11프레임에 공격 패턴이 나오면서 자연스러워 보였다. 원하는 프레임에 추가 이벤트를 녹화하고, 호출할 메서드 이름과 오브젝트에 애니메이션을 붙이니 마음에 드는 연출이 나왔다.



*boss 스크립트도 수정해야 합니다.

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

public class FireWorm : MonoBehaviour
{
    private enum eState
    {
        Idle, //0
        Walk, //1
        Attack, //2
        Death, //3
        GetHit, //4
    }
    public Transform player;
    public float bossMoveSpeed = 2.5f;
    private Rigidbody2D rb;

    public GameObject firePoit;

    //animator(State)
    private Animator anim;

    private void Awake()
    {
        this.rb = this.GetComponent<Rigidbody2D>();
        this.anim = this.GetComponent<Animator>();

        this.anim.SetInteger("state", (int)eState.Idle);
    }
    private void Start()
    {
        InvokeRepeating("AnimationEventTest", 2f, 2f);
    }

    ////movement01
    //private void FixedUpdate()
    //{
    //    Vector2 direction=this.player.position-this.transform.position;

    //    if(direction.magnitude>1f)
    //    {
    //        direction.Normalize();
    //    }

    //    this.rb.velocity = direction*this.bossMoveSpeed;

    //    if(this.rb.velocity.x!=0f)
    //    {
    //        Debug.Log("Walk");
    //        this.anim.SetInteger("stat",(int)eState.Walk);
    //    }

       

    //    if (this.player.position.x < this.transform.position.x)
    //    {
    //        this.transform.rotation = Quaternion.Euler(0f, -180f, 0f);
    //    }
    //    else
    //    {
    //        this.transform.rotation= Quaternion.identity;
    //    }      
    //}

    //AttackPattern01
    private void AttackPattern01()
    {
        int bulletsAmount = 20;
        float startAngle = 0f; //시작 각도
        float endAngle = 360f; //끝나는 각도
        float angleStep = (endAngle - startAngle) / bulletsAmount; //bullet의 간격
        float angle = startAngle;

        for (int i = 0; i < bulletsAmount; i++)
        {
            float bulDirX = transform.position.x + Mathf.Sin((angle * Mathf.PI) / 180f);
            float bulDirY = transform.position.y + Mathf.Cos((angle * Mathf.PI) / 180f);

            Vector3 bulMoveVector = new Vector3(bulDirX, bulDirY, 0f);
            Vector2 bulDir = (bulMoveVector - transform.position).normalized;

            GameObject bul = BulletPool.instance.GetBullet();
            bul.transform.position = this.firePoit.transform.position;
            bul.transform.rotation = this.firePoit.transform.rotation;
            bul.SetActive(true);
            bul.GetComponent<FireWormBullet>().SetMoveDirection(bulDir);
            angle += angleStep;
        }        
    }

    //AnimationEventTest
    private void AnimationEventTest01()
    {
        Debug.Log("Attack");
        this.anim.SetInteger("stat", 2);
    }

    ////Test
    //private void OnTriggerEnter2D(Collider2D collision)
    //{
    //    if(collision.CompareTag("Player"))
    //    {
    //        Debug.Log("Player");
    //    }
    //}


}

*만들다 보니 좀 더 다양한 움직임 패턴이 필요했어요. 당장은 플레이어를 쫓아가는 움직임밖에 없지만, 좀 더 다양하게 움직일 수 있는 패턴을 생각해야 한다.