* 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");
// }
//}
}
*만들다 보니 좀 더 다양한 움직임 패턴이 필요했어요. 당장은 플레이어를 쫓아가는 움직임밖에 없지만, 좀 더 다양하게 움직일 수 있는 패턴을 생각해야 한다.