2.1 공이 분열할 때 공의 크기별로 프리팹으로 만들어두기
Bullet이 공에 닿으면? 기본 : 바로 분열 , 추후 시간이 되면 ( 난이도or 스테이지증가시 데미지(예 파랑풍선2방 컷 빨강풍선1대 컷) )
Bullet은 Collider 벽(맵 밖의 한계선 설정 벽)에 맞거나 공(Enemy) 맞으면 Bullet은 사라져야 함. (추후 오브젝트 풀링 최적화)
( "Collision"Enter2D를 이용, Bullet은 닿으면 사라지는 로직만, 공 스크립트에서 Bullet에 닿으면 분열하는 로직을 써야 함 ) ( Tag이용)
Player의 공격은 1초의 CoolTime , Bullet을 밀어주는 힘(스피드) Force는 5
추후 아이템 or 장비로? 강화로 증가 : 드롭 아이템(시간제한) 증가
아이템의 경우 공 제외 다른 오브젝트( 동물 or 물체 ) 랜덤으로 날아다니는 걸 맞추면 랜덤 아이템 드롭
아이템을 먹으면 지속시간을 적용 ( ex: n초 )
아이템 드롭이 되어 바닥에 떨어진 아이템은 - n초뒤에 사라짐 ( x, z축 프리징 고정 )
아이템 : Bullet의 증가, Bullet 변경, 공속 증가, Bullet Speed 증가, 시간 정지, 관통, 튕김, 유도
캐릭터 : Collision
불릿 : Trigger
공 : ?
벽 : ?
공속 증가 - CoolTime 초를 줄인다.
Bullet Speed 증가 - bullet.foce
###########################
Bullet의 증가 - case 문으로 아이템을 먹으면 증가시켜 그 케이스에 맞는 인스턴스 찍어내기.
관통 - 장애물 오브젝트 및 공을 뚫고 지나감 ( 관통으로 인한 효과가 이 게임에서 클지는 모르겠음 )
튕김 - Bullet이 벽에 닿으면 랜덤방향으로 튕겨 n번까지 지속
유도 - 가장 가까운 공을 따라가서 맞춤
무적 - 맞아도 데미지를 입지 않는다.
Bullet의 변경 - Prefab 추가, 메서드 경우의 수 추가
시간 정지 - 공의 움직임이 멈춤, 플레이어는 이동 및 공격 가능 ( 플레이어는 이동을 해야해서 Time.timeScale = 0 은 불가능 )
##########################
또는 상점을 만들어서 게임 플레이에서 골드를 휙 득하여 상점에서 아이템 or 장비를 구매하는 방식은? 마감일 맞출수 있을지.
만일 상점을 넣는다면 ( UI, 스테이지 (Map), 상점, 캐릭터, 공, 총알, 골드, 아이템 ) 로 역할 분할
##########################
GameManager는 DontDestoryOnLoad를 사용할 것인가? 사용.
GameManager에서 무엇을 관리할 것인지? 예) 점수, 목숨, 난이도, 스테이지 정보 등 ( 랭킹 ) ( 캐릭터 정보들 보관용 )
MainSceneManager, SoundManager, UIManager는 운용할 것인가?
Player의 공격 기능은 만들었기에 이번엔 아이템에 따른 Player의 공격 변화를 구현해보았다.
ItemManager를 통해 Item을 Enum타입으로 관리하고 아이템을 먹으면 상태를 변경하여 공격을 적용하게 하도록 짜보았다.
public class ItemManager : MonoBehaviour
{
#region ItemType
public enum ItemType
{
Normal,
BulletUPItem, // bullet 갯수 증가
PenetrateItem, // 관통
BounceItem, // 튕김
GuidedMissileItem // 유도탄
}
// ItemType Reset Value
public ItemType currentItem;
#endregion
public static ItemManager instance;
private void Awake()
{
instance = this;
}
// Basic Value
[SerializeField] protected float force = 5;
[SerializeField] protected float coolTime = 1.0f;
public IEnumerator ItemTime(float time, ItemType current)
{
float timeRemained = time;
while (timeRemained > 0.0f)
{
//if (current != this.currentItem) yield break;
timeRemained -= Time.deltaTime;
Debug.Log(timeRemained);
yield return null;
Debug.Log(timeRemained);
}
Debug.Log("끝");
currentItem = ItemType.Normal;
}
}
public class PlayerAttackSystem : ItemManager
{
TopDownCharacterController _controller;
Rigidbody2D bulletRigid; // bullet Prefab Clone Rigidbody
GameObject bullet; // ( bullet는 player가 발사하는 총알 Prefab )
//// Coroutine Caching
//private IEnumerator ItemCoolTime;
//private WaitForFixedUpdate fixedUpdate = new WaitForFixedUpdate();
private bool coolTimeCheck = true;
private void Awake()
{
_controller = GetComponent<TopDownCharacterController>();
bullet = Resources.Load<GameObject>("Prefabs/Bullet");
}
private void Start()
{
_controller.OnAttackEvent += Attack;
}
private void Attack()
{
// CoolTime Check
if (coolTimeCheck == true) StartCoroutine(CollTime(coolTime));
}
private void RecallBullet()
{
Debug.Log(currentItem);
switch(currentItem)
{
case ItemType.Normal:
GameObject playerBullet = Instantiate(bullet);
playerBullet.transform.position = new Vector3(transform.position.x, transform.position.y + 0.4f, transform.position.z);
ApplyAttck(playerBullet);
break;
case ItemType.BulletUPItem:
GameObject playerBullet1 = Instantiate(bullet);
GameObject playerBullet2 = Instantiate(bullet);
playerBullet1.transform.position = new Vector3(transform.position.x - 0.2f, transform.position.y + 0.4f, transform.position.z);
playerBullet2.transform.position = new Vector3(transform.position.x + 0.2f, transform.position.y + 0.4f, transform.position.z);
ApplyAttck(playerBullet1);
ApplyAttck(playerBullet2);
break;
case ItemType.PenetrateItem:
break;
case ItemType.BounceItem:
break;
case ItemType.GuidedMissileItem:
break;
default:
break;
}
}
private void ApplyAttck(GameObject obj)
{
bulletRigid = obj.GetComponent<Rigidbody2D>();
bulletRigid.AddForce(transform.up * this.force, ForceMode2D.Impulse);
}
private IEnumerator CollTime(float time)
{
// CoolTime Setting
coolTimeCheck = false;
RecallBullet();
while (time > 0.0f)
{
time -= Time.deltaTime;
yield return new WaitForFixedUpdate();
}
// CoolTime Reset
coolTimeCheck = true;
}
}
public class BulletIncrease : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Player")
{
if (ItemManager.instance.currentItem != ItemManager.ItemType.BulletUPItem)
{
ItemManager.instance.currentItem = ItemManager.ItemType.BulletUPItem;
Debug.Log(ItemManager.instance.currentItem);
StartCoroutine(ItemManager.instance.ItemTime(5.0f, ItemManager.instance.currentItem));
}
//else //if (currentItem == ItemType.BulletUPItem)
//{
// currentItem = ItemType.Normal;
// currentItem = ItemType.BulletUPItem;
// StartCoroutine(ItemTime(5f, currentItem));
// currentItem = ItemType.Normal;
//}
//Destroy(gameObject); // 추후 오브젝트 풀링
}
}
}
public class ItemFall : MonoBehaviour
{
GameObject item;
Rigidbody2D rigid;
private void Awake()
{
item = GetComponent<GameObject>();
rigid = transform.GetComponent<Rigidbody2D>();
}
private void Start()
{
rigid.AddForce(transform.up * -1, ForceMode2D.Impulse);
}
}
Player가 아이템을 먹으면 ItemType Enum currentItem의 상태를 바꿔주어 공격 불렛을 바꾸려 했지만 아이템이 부딪혀 Destory가 되면 코루틴이 바로 종료가 되버리는 버그가 있었다.
그리고 먹어서 ItemManager쪽에선 Enum상태가 변해도 그걸 상속받는 PlayerAttackSystem에서는 Enum상태가 변하지 않는 버그도 있어서 주말동안 그 버그를 잡아보려고 한다...