본문 바로가기

Unity/Portfolio Daily Log

캐주얼 슈팅 액션 대전 게임 (모바일) - 9 피격 애니메이션, 이펙트 추가 및 구조 수정

구조를 조금 수정했다.

원래 Mediator에서 명령을 내려줘야 하는데 Status부분에서 SetDamage를 하면서 Mediator한테 전달해주는 건 의도한 바와 조금 달랐다. 그래서  Mediator에 Damaged라는 함수를 만들어서 Bullet에서 피격 판정을 할 때 Status에서 SetDamage를 부르는게 아닌 Mediator의 Damaged를 RPC로 불렀다.

    [PunRPC]
    public void Damaged(float attackPower)
    {
        status.SetDamage(attackPower);
        UI.SetSliderValue(status.CurrentHP, status.MaxHP);
        DamageAnimation();
        effect.HitEffect(transform);
    }

그리고 피격 애니메이션을 추가했다. 

public void OnDamage()
{
    ResetAttack();
    ani.Play("Damage");
}

심플한 코드이다. 공격상태 도중에 불릴 수도 있으니 저번에 만든 ResetAttack 함수를 넣었고 Damage 애니메이션을 재생하게 했다. 그리고 effect를 나오게 했는데

 

public class EffectManager : MonoBehaviour
{
    public GameObject hitEffect;
    private MemoryPool memoryPool;
    
    void Start()
    {
        memoryPool = GameObject.Find("MemoryPool").GetComponent<MemoryPool>();
    }
    public void HitEffect(Transform characterPosition)
    {
        GameObject tempEffect = memoryPool.ActivePoolItem(MemoryPool.ObjectType.HitEffect);
        tempEffect.transform.position = characterPosition.position + new Vector3(0, 0.5f, 0);
    }
}

HitEffect는 Transform 값을 받아서 해당 위치 + y 값으로 0.5위치에 나타나게 했다.

보면 Bullet할 때 봤던 ActivePoolItem에 매개변수가 추가된 것을 볼 수 있는데 만들어 뒀던 오브젝트 풀에 확장성을 추가했다.

public class MemoryPool : MonoBehaviour
{
    
    public MemoryPool instance { get; private set; }
    public GameObject bullet;
    public GameObject hitEffect;
    public enum ObjectType { Bullet, HitEffect }
    private void Awake()
    {
        InitEnv(bullet, ObjectType.Bullet);
        InitEnv(hitEffect, ObjectType.HitEffect);
    }
    private int increaseCount = 10;          //오브젝트가 부족할 때 Instantiate()로 추가 생성되는 오브젝트 개수
    private int maxCount;                   //현재 리스트에 등록되어 있는 오브젝트 개수
    private int activeCount;                //현재 게임에 사용되고 있는 활성화 오브젝트 개수

    private GameObject bulletObject;          //오브젝트 풀링에서 관리하는 게임 오브젝트 프리팹 // 불릿
    private GameObject hitEffectObject;          //오브젝트 풀링에서 관리하는 게임 오브젝트 프리팹 // 불릿
    private List<PoolItem> poolItemList;    //관리되는 모든 오브젝트를 저장하는 리스트
}

우선 인스팩터상에서 프리팹을 어사인 할 GameObject bullet 과 hitEffect가 추가됐다. 기존의 스크립트에서는 한 개만 있었다. 그리고 오브젝트 풀링에서 관리하는 게임 오브젝트 프리팹인 bulletObject와 hitEffectObject를 추가했다. 이 역시 기존에는 한 개만 있었다.

 

그리고 enum ObjectType이 추가됐는데 앞으로 추가로 오브젝트를 관리할 일이 생기면 프리팹 추가 및 enum 추가를 하면 된다.

public void InitEnv(GameObject poolObject, ObjectType objectType)
    {
        maxCount = 0;
        activeCount = 0;
        switch (objectType)
        {
            case ObjectType.Bullet:     this.bulletObject = poolObject;     break;
            case ObjectType.HitEffect:  this.hitEffectObject = poolObject;     break;
            default:    break;
        }

        if(poolItemList == null)
            poolItemList = new List<PoolItem>();

        InstantiateObjects(objectType);
    }

처음에 초기화를 해주기 위해 만들었던 함수이다. 불릿 오브젝트 풀을 만들고 싶으면 InitEnv(bullet, ObjectType.Bullet); 하면 되고, 히트 이펙트 오브젝트 풀을 만들려면 InitEnv(hitEffect, ObjectType.HitEffect); 를 사용하면 된다.

사실 bulletObject hitEffectObject 안 나눠놨어도 됐을 것 같은데 가독성을 위해 나눠놨다.

 

public void InstantiateObjects(ObjectType objectType)
    {
        maxCount += increaseCount;

        for( int i =0; i < increaseCount; i++ )
        {
            PoolItem poolItem = new PoolItem();

            poolItem.isActive = false;
            switch (objectType)
            {
                case ObjectType.Bullet:     poolItem.gameObect = GameObject.Instantiate(bulletObject);  break;
                case ObjectType.HitEffect:  poolItem.gameObect = GameObject.Instantiate(hitEffectObject); break;
                default:    break;
            }
            
            poolItem.gameObect.transform.parent = this.transform;
            poolItem.gameObect.SetActive(false);

            poolItemList.Add(poolItem);
        }
    }

실제로 풀을 만드는 함수이다. enum Type을 받아서 타입에 맞는 오브젝트를 Instantiate 해주고 list에 추가한다.

 

 

SetActive True 와 False를 해주는 함수이다.

public GameObject ActivePoolItem(ObjectType objectType)
    {
        if (poolItemList == null) 
            return null;

        if (activeCount == maxCount)
            InstantiateObjects(objectType);

        int count = poolItemList.Count;
        for (int i = 0; i < count; i++)
        {
            PoolItem poolItem = poolItemList[i];

            if(poolItem.isActive == false)
            {
                if (objectType == ObjectType.Bullet && poolItem.gameObect.CompareTag("Bullet"))
                {

                    activeCount++;

                    poolItem.isActive = true;
                    poolItem.gameObect.SetActive(true);

                    return poolItem.gameObect;

                }
                else if (objectType == ObjectType.HitEffect && poolItem.gameObect.CompareTag("HitEffect"))
                {
                    activeCount++;

                    poolItem.isActive = true;
                    poolItem.gameObect.SetActive(true);

                    return poolItem.gameObect;
                }
            }
        }
        return null;
    }

    // 현재 사용이 완료된 오브젝트를 비활성화 상태로 설정
    public void DeactivatePoolItem(GameObject usedObject)
    {
        if (poolItemList == null || usedObject == null)
            return;

        int count = poolItemList.Count;
        for (int i = 0; i < count; i++)
        {
            PoolItem poolItem = poolItemList[i];

            if(poolItem.gameObect == usedObject)
            {
                activeCount--;

                poolItem.isActive = false;
                poolItem.gameObect.SetActive(false);

                return;
            }
        }
    }

 

 

내일은 오브젝트 풀의 리스트를 나누는 작업을 할 예정이다.