EntityManager
EntityManager에서는 entity들을 관리한다. entity들의 움직임, 공격, 소환되는 것을 관리
1.EntityAlignment
Entity가 죽거나, 소환될 때 호출되며 entity를 정렬한다.
public void EntityAlignment(bool isMine) //내 것이면 내 entity 정렬, 상대 것이면 상대 entity 정렬
{
float targetY = isMine ? -6.0f : 6.0f;
var targetEntities = isMine ? myEntities : otherEntities;
for (int i = 0; i < targetEntities.Count; i++)
{
float targetX = (targetEntities.Count - 1) * -2.5f + i * 5.0f;
var targetEntity = targetEntities[i];
targetEntity.originPos = new Vector3(targetX, targetY, 0);
targetEntity.MoveTransform(targetEntity.originPos, true, 0.5f);
targetEntity.GetComponent<Order>()?.SetOriginOrder(i);
}
}
2.SpawnEntity
카드 상태에서 entity로 소환했을 때 호출되며, 호출되면 필드에 entity prefebs를 통해 생성된다.
public bool SpawnEntity(bool isMine, Item item, Vector3 spawnPos) //카드의 아이템을 바탕을 생성
{
if (isMine)
{
if (IsFullMyEntities || !ExitMyEmptyEntity)
return false;
}
else
{
if (IsFullOtherEntities)
return false;
}
var entityObject = Instantiate(entityPrefab, spawnPos, Utils.QI);
var entity = entityObject.GetComponent<Entity>();
if (isMine)
{
myEntities[myEmptyEntityIndex] = entity;
entity.name = SetEntityNum(isMine);
}
else
{
otherEntities.Insert(UnityEngine.Random.Range(0, otherEntities.Count), entity);
entity.name = SetEntityNum(isMine);
}
entity.isMine = isMine;
entity.Setup(item);
EntityAlignment(isMine);
return true;
}
3.Attack & AttackCallback
공격과 공격 이후의 데미지에 따른 결과를 호출한다.
public void Attack(Entity attacker, Entity defender)
{
if (defender.canBeAttacked == false && attacker.ablcode1 !=21)
{
return;
}
attacker.attackable = false; //턴당 1회 공격이기에 bool 값을 false로 만들어 공격을 한번만 할 수 있다.
attacker.GetComponent<Order>().SetMostFrontOrder(true);
if (attacker.isMine)
{
if (defender.isBossOrEmpty)
{
byte[] send = new byte[3] { 0x00, Convert.ToByte(attacker.gameObject.name), Convert.ToByte("0") };
BackEndMatch.SendMessage(send);
}
else
{
byte[] send = new byte[3] { 0x00, Convert.ToByte(attacker.gameObject.name), Convert.ToByte(defender.gameObject.name) };
BackEndMatch.SendMessage(send);
}
AbilityManager.Inst.eTurnState = AbilityManager.ETurnState.attacking;
AbilityManager.Inst.stateTrigger = true;
if (AbilityManager.Inst.abilityNum[attacker.ablcode1].state == (int)AbilityManager.ETurnState.attacking || AbilityManager.Inst.abilityNum[defender.ablcode1].state == (int)AbilityManager.ETurnState.beAttacked)
{
castEntity = attacker;
return;
}
}
Sequence sequence = DOTween.Sequence() // 공격에 따른 DOTween 모션
.Append(attacker.transform.DOMove(defender.transform.position, 0.4f)).SetEase(Ease.InSine)
.AppendCallback(() =>
{
attacker.Damaged(defender.attack);
defender.Damaged(attacker.attack);
SpawnDamage(defender.attack, attacker.transform);
SpawnDamage(attacker.attack, defender.transform); //공격 시 공격자와 방어자 모두 데미지를 서로의 공격력만큼 입는다.
})
.Append(attacker.transform.DOMove(attacker.originPos, 0.4f)).SetEase(Ease.OutSine)
.OnComplete(() => AttackCallback(attacker, defender)); //공격 후 entity가 죽었는지 확인하기 위해
StartCoroutine(cursor.Inst.Attack());
}
공격 시 데미지를 호출한다.
public void SpawnDamage(int damage, Transform tr)
{
if (damage <= 0)
return;
var damageComponent = Instantiate(damagePrefab).GetComponent<Damage>();
damageComponent.SetupTransform(tr);
damageComponent.Damaged(damage);
}
public void Damaged(int damage)
{
if(damage <=0)
return;
GetComponent<Order>().SetOrder(1000,"Entity");
damageTMP.text =$"-{damage}";
Sequence sequence =DOTween.Sequence()
.Append(transform.DOScale(Vector3.one * 4.0f,0.5f).SetEase(Ease.InOutBack))
.AppendInterval(1.0f)
.Append(transform.DOScale(Vector3.zero, 0.5f).SetEase(Ease.InOutBack))
.OnComplete(() => Destroy(gameObject));
}
공격 이후에 호출되며, 호출된 entity들의 사망 정보를 확인하고, 플레이어의 entity의 죽음을 확인하여, 만약 플레이어가 죽었으면 게임을 종료하는 코루틴을 호출
public void AttackCallback(params Entity[] entities)
{
entities[0].GetComponent<Order>().SetMostFrontOrder(false);
foreach (var entity in entities)
{
if (!entity.isDie || entity.isBossOrEmpty)
continue;
if (entity.isMine)
{
AbilityManager.Inst.eTurnState = AbilityManager.ETurnState.myMonDie;
AbilityManager.Inst.stateTrigger = true;
if(AbilityManager.Inst.abilityNum[entity.ablcode1].state == (int)AbilityManager.ETurnState.myMonDie)
{
castEntity = entity;
}
myEntities.Remove(entity);
}
else
otherEntities.Remove(entity);
Sequence sequence = DOTween.Sequence()
.Append(entity.transform.DOShakePosition(1.0f))
.Append(entity.transform.DOScale(Vector3.zero, 0.3f)).SetEase(Ease.OutCirc)
.OnComplete(() =>
{
EntityAlignment(entity.isMine);
Destroy(entity.gameObject);
});
}
StartCoroutine(CheckBossDie());
}
4.Entity 움직임
1)EntityMouseUp
마우스가 entity 클릭을 멈출 때 호출된다.
public void EntityMouseUp()
{
if (!CanMouseInput)
return;
if (selectEntity && targetPickEntity && selectEntity.attackable) //클릭해서 움직인 entity가 있고, 공격할 entity위에서 마우스 클릭을 멈췄을 때
Attack(selectEntity, targetPickEntity);
selectEntity = null;
targetPickEntity = null;
}
2)EntityMouseDown
마우스가 entity를 클릭할 때 호출한다.
public void EntityMouseDown(Entity entity)
{
if (!CanMouseInput)
return;
selectEntity = entity;
AbilityManager.Inst.eTurnState = AbilityManager.ETurnState.drag;
AbilityManager.Inst.stateTrigger = true;
}
3)EntityMouseDrag
마우스로 entity를 선택하고 드래그할 때 호출된다. 공격 대상을 찾는다. 공격 대상을 찾으면 멈춘다.
public void EntityMouseDrag()
{
if (!CanMouseInput || selectEntity == null)
return;
bool existTarget = false;
foreach (var hit in Physics2D.RaycastAll(Utils.MousePos, Vector3.forward))
{
Entity entity = hit.collider?.GetComponent<Entity>();
if (entity != null && !entity.isMine && selectEntity.attackable)
{
targetPickEntity = entity;
targetEntity = entity;
existTarget = true;
break;
}
}
if (!existTarget)
targetPickEntity = null;
}