ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 개발 모임 23회차) 지렁이 적군, UI 형태 잡기, 기타 최적화
    개발모임 2022. 6. 25. 13:04

    tile객체로 구성된 맵의 mesh를 하나로 묶고 material tile로 해결했다.

     

    타일에 파티클을 두어 색상 처리하여 Batch를 줄이고 랜더링의 계산으로 떠넘겼다.

     

    이전에는 렌더링의 계산이 좀더 적었고, Batch가 1000을 넘어섯고, 최대 3000까지 갔었다. 그렇기에 최적화가 필요했다.

     

    셰이더 그래프에서 Tiling 기능을 사용하여 메쉬의 크기에 맞게 체크무늬 머티리얼을 생성하였다.

    그 위에는 Quad를 사용한 파티클을 통해 색상을 나타내었다.

     

    좀더 심화적인 방법으론 텍스쳐의 픽셀을 실시간으로 접근하여 색상을 바꾸는 방법이 있다.

    하지만 그러기엔 픽셀의 색상을 보간하기에 어려움이 있어 위의 방법을 채용했다.

     

     

     

    2. UI의 형태를 잡아둠.

    TMP Pro의 기능인 <color>></color> 태그를 사용하여 텍스트 색상을 지정하였다.

     

    {0} 부분에는 아래 코드가 들어갈 것이다.

                    temp.m_Description = string.Format(temp.m_Description,
                        "(<color=green>{0}</color> + <color=red>TILE</color>)");

    색상의 적용법은 HTML의 태그 기능과 똑같다.

     

     

     

     

    3. 적군의 모델 구매, 적군 조금더 다듬음.

     

    적군의 CSV 생성

     

    EnemyGroup을 통해 지정된 위치에 적군을 생성한다.

     

    한번 생성된 적군은 그룹이 다시 활성화 될때 같이 활성화 된다.

     

     

     

    적용된 적군은 위와 같다.

     

    상태머신은 아주 간단하다.

     

    플레이어를 발견했다면 공격을 하고, 그 외에는 IDLE 상태이다.

     

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class CEnemy_BaseMelee : CEnemy
    {
        public override void ACT()
        {
            base.ACT();
        }
    
        public override void AfterSpawn()
        {
            base.AfterSpawn();
        }
    
        Coroutine coDelay = null;
    
        ////////////////////////////////////////
        ////////////////////ATTACK
        ///////////////////////////////////////////
        public override void Attack()
        {
            m_CurrState = EActState.ATTACKING;
            Idle();
            Debug.Log("Attack");
            m_Anim.SetTrigger("Attack");
    
            //StartCoroutine(CoAttackDelay());
        }
    
        IEnumerator CoAttackDelay(float delay)
        {
            yield return new WaitForSeconds(delay);
            m_CurrState = EActState.IDLE;
        }
    
        public void AnimAttack() 
        {
            m_Attack.Melee();
        }
    
        public override void EndAttack()
        {
            m_Attack.EndAttack();
            
        }
    
        public override void EndAnim(float delay = 0)
        {
            Debug.Log(delay);
            Idle();
            if (coDelay != null) StopCoroutine(coDelay);
            coDelay = StartCoroutine(CoAttackDelay(delay));
    
            //m_CurrState = EActState.IDLE;
        }
        ////////////////////
    
        ////////////////////////////////////////
        ////////////////////IDLE
        ///////////////////////////////////////////
        public override void Idle() { m_CoState = StartCoroutine(CoIdle()); }
        IEnumerator CoIdle()
        {
            while (true)
            {
                yield return null;
                if (m_IsBattle == false) continue;
    
                //쳐다보기
                this.transform.forward = Vector3.Lerp(currTransform.forward, Look(), Time.deltaTime * 3);
                
    
                if (m_CurrState == EActState.ATTACKING)
                {
                    //yield return null;
                    continue;
                }
                //사거리 밖이면 이동
                else if (m_CurrState == EActState.MOVE)
                {
                    Move();
                }
                else if (Vector3.Distance(currTransform.position, Target.position) > m_Range)
                {
                    m_CurrState = EActState.MOVE;
                }
                else if (m_CurrState == EActState.IDLE)
                {
                    m_CurrState = EActState.ATTACK;
                }
    
    
                yield return null;
            }
        }
        ////////////////////
        
    
        public override Vector3 LookAvoid()
        {
            return base.LookAvoid();
        }
    
        ////////////////////////////////////////
        ////////////////////MOVE
        ///////////////////////////////////////////
        public override void Move() { m_CoState = StartCoroutine(CoMove()); }
        IEnumerator CoMove()
        {
            while (true)
            {
                //쳐다보기
                this.transform.forward = Vector3.Lerp(currTransform.forward, LookAvoid(), Time.deltaTime * 3);
    
                //사거리 까지 움직임
                if (Vector3.Distance(currTransform.position, Target.position) > m_Range)
                {
                    float grav = m_Rigid.velocity.y;
                    Vector3 move = currTransform.forward * m_Speed;
                    move.y = grav; m_Rigid.velocity = move;
                    if (m_Anim != null) m_Anim.SetFloat("Move", m_Rigid.velocity.magnitude);
                }
                else
                {//in sight
                    if (m_CurrState != EActState.ATTACKING)
                        m_CurrState = EActState.ATTACK;
                    else
                        m_CurrState = EActState.IDLE;
                }
    
                yield return null;
            }
        }
        ////////////////////
    
        public override void OnDie()
        {
            StopAllCoroutines();
            m_Anim.SetTrigger("Die");
            m_Anim.SetBool("IsBattle",false);
            m_IsBattle = false;
    
            //다른 타겟 선택하게 함
            CGameManager.Instance.m_Hero.m_Player.SetOtherTarget(m_Self);
        }
    
        public override void Die()
        {
            this.gameObject.SetActive(false);
        }
    
    
        public override void Spawn(CCSV_Enemy _enemyPref)
        {
            base.Spawn(_enemyPref);
        }
    
        public override void Start()
        {
            base.Start();
        }
    
        public override void StateChanger(EActState _currstate)
        {
            switch (_currstate)
            {
                case EActState.IDLE: Idle(); break;
                case EActState.MOVE: Move(); break;
                //case EActState.CAN_ATTACK:  Move();     break;
                case EActState.ATTACKING: Idle(); break;
                case EActState.ATTACK: Attack(); break;
                case EActState.ACT: ACT(); break;
                default: break;
            }
        }
    
        public override string ToString()
        {
            return base.ToString();
        }
    }

     

    그 외에도 상태머신들의 작은 부분들에 대해 최적화를 하였다.

    (상태머신, CSVLoader, Hitable 등등)

     

    다음에는 아이템을 추가하고, 맵을 좀더 구성지게 꾸밀것이며, 캐릭터와 몬스터의 성장 치를 손보겠다.

     

Designed by Tistory.