ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 개발 모임 22회차) 지렁이 게임 - 공격 구현
    개발모임 2022. 6. 10. 12:33

    이번에는 시뮬레이션 장면에서 사용되는 공격을 구현하였다.

     

    skill csv 데이터시트

    스킬의 데이터들 이다.

     

    Size는 스킬을 사용하기 위한 타일 크기,

    Attack Type은 공격이 생성될 타입을 지정한다.

     

     

    객체에는 아래 3개 스크립트가 필요하다

    Player  상태머신

    CAttack 공격

    CHitbale 피격

     

    기본적으로 3개의 객체가 있어야 시뮬레이션 파트에서 작동을 한다.

     

     

    공격은 3가지 타입이 있다.

    Melee 근접

    Projectile 투사체

    Area 범위공격

     

     

    투사체 공격 코드

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    [RequireComponent(typeof(Collider))]
    public class CProjectile : CSpawnableAttack
    {
        public ParticleSystem m_SpawnParticle = null;
        public ParticleSystem m_Particle = null;
    
        public CHitScanAttack m_hitScan = null;
    
        public float m_LifeTime = 1f;
        public float m_Speed = 10f;
    
        protected Coroutine m_CoLife = null;
    
        protected virtual void OnEnable()
        {
            Debug.Log(m_SpawnParticle?.ToString());
            if (m_SpawnParticle != null) m_SpawnParticle.Play();
            if (m_Particle != null) m_Particle.Play();
    
            m_hitScan.m_HitCB = Hitted;
            m_CoLife = StartCoroutine(CoLife());
        }
    
        IEnumerator CoLife() 
        {
            float life = m_LifeTime;
            while (life > 0) 
            {
                life -= Time.deltaTime;
                Move();
                yield return null;
            }
            EndLife();
        }
    
        public virtual void EndLife() 
        {
            this.gameObject.SetActive(false);
        }
    
        public virtual void Move() 
        {
            this.transform.position += this.transform.forward * m_Speed * Time.deltaTime;
        }
    
    
    
        protected virtual void OnDisable()
        {
            if (m_SpawnParticle != null) m_SpawnParticle.Stop();
            if (m_Particle != null) m_Particle.Stop();
            if (m_CoLife != null) StopCoroutine(m_CoLife);
        }
    
        public override void Spawn(float _dmg, int _hitCount = 0)
        {
            this.gameObject.SetActive(true);
            m_hitScan.Spawn(_dmg);
        }
    
        //투사체 피격 이후 함수
        public virtual void Hitted() 
        {
            
        }
    
    }

    코드는 쓸대없이 길다.

    그냥 생성되면 파티클, 콜라이더 활성화

    생존시간동안 움직임, 시간이 지나면 스스로 사라짐.

     

    area공격 코드도 위와 흡사하다.

     

     

     

    이번엔 공격에 대한 풀링을 알아보자.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class CAttack : MonoBehaviour
    {
        //public void AttackTarget(List<CHitable> _targets, float _dmg) 
        //{
        //    foreach (var it in _targets) 
        //    {
        //        it.Hit(_dmg);
        //    }
        //}
        public CHitScanAttack m_HitScaner = null;
        public Transform m_ObjPool = null;
    
        //[SerializeField] List<CSpawnableAttack> m_AttackPool = new List<CSpawnableAttack>();
        Dictionary<string, List<CSpawnableAttack>> m_AttackPool 
            = new Dictionary<string, List<CSpawnableAttack>>();
    
        //즉시 적중
        public void ImmidiateHit(CHitable _target, float _dmg) 
        {
            _target.Hit(_dmg);
        }
    
        //스킬 풀링
        CSpawnableAttack SkillPoolCtrl(CCSV_Skill _skill) 
        {
            var name = _skill.m_Data.m_Name;
            //List<CSpawnableAttack> currPool = m_AttackPool[name];
            m_AttackPool.TryGetValue(name, out List<CSpawnableAttack> currPool);
            CSpawnableAttack poolObj = null;
    
            if (currPool == null)
            {
                currPool = new List<CSpawnableAttack>();
                poolObj = Instantiate(_skill.m_Attack, m_ObjPool);
                currPool.Add(poolObj);
                m_AttackPool.Add(name, currPool);
            }
            else
            {
                foreach (var it in currPool)
                {
                    if (it.gameObject.activeSelf == false)
                    { poolObj = it; break; }
                }
                if (poolObj == null)
                {
                    poolObj = Instantiate(_skill.m_Attack, m_ObjPool);
                    currPool.Add(poolObj);
                }
            }
    
            return poolObj;
        }
        //TODO : 스킬 csv에 삭제될때 콜백 필요할듯
    
        //범위 공격
        public void SpawnArea(CCSV_Skill _skill, Transform _target,
            float _dmg)
        {
            var poolObj = SkillPoolCtrl(_skill);
            poolObj.transform.position = _target.position;
            poolObj.Spawn(_dmg, 5);
        }
    
        //투척
        public void ThrowProjectile(CCSV_Skill _skill,
            Transform _target, Transform _spawnPos, float _dmg)
        {
            var poolObj = SkillPoolCtrl(_skill);
            poolObj.transform.position = _spawnPos.position;
            Vector3 forward = _target.position - _spawnPos.position; 
            forward.y = 0;
            poolObj.transform.forward = forward;
    
    
            poolObj.Spawn(_dmg);
        }
    
        public void OnEnable()
        {
            
        }
    
        public void Melee(float _dmg = 1f) 
        {
            if (m_HitScaner == null)
            {
                Debug.Log("no scanner");
                return;
            }
            m_HitScaner.Spawn(_dmg);
        }
    
        public void EndAttack() 
        {
            m_HitScaner.gameObject.SetActive(false);
        }
    
    
    
    }

    아주 특별한 내용은 없다.

     

    공격 타입에 따라 스킬 내부에 저장되어있는 prefab을 생성한다.

    생성된 prefab은 Dictionary형태로 관리한다.

    ex) ["Bash", prefabObj1] , ["Bash", prefabObj2]

     

    스킬을 사용했을때 이미 생성된 공격 객체가 있다면 그것을 사용한다.

    스킬이 삭제되었을때 pool에서 삭제하는 코드는 아직 적용되지 않았다.

     

     

    이번엔 크게 구현하기 보다는 흐름을 잡은것 같다.

    개인적으로 좋지 않았던 일이 겹쳐 코딩에 집중을 못했던것 같다.

    빨리 마음을 다시 잡고, 코딩과 설계에 집중할수 있도록 하겠다.

Designed by Tistory.