버그 픽스

6.11

닐리는 마법사이기 때문에 마법이 완성되면 다 된것처럼 보인다. 하지만 운석에 가려 망토가 흩날리는 것이 잘 보이지는 않는다. 그 외에도 이런 잘 안보이는(하지만 엉성하면 티나는) 애니메이션이 많다. 이걸 해보자.

그런데 앨리스의 모션이 생각보다 호환이 잘된다.넘어가도 될 것 같다. 그럼 닐리의 작업은 여기서 마무리해도 될 것 같다.

하지만 그간 작업하면서 새롭게 튀어나온 버그들이 많다.

6.12

닐리의 킥잡기는 캐릭터를 거꾸로 세운다. 당연히 이 땐 캐릭터의 앞머리가 뒤집어질 것 같다. 그런데… 이것이 앨리스를 앨리스답지 않게 보이게 한다는 의견이 있었다.

물리적인 관점에서 보면 앞머리가 뒤집어지는 것이 맞다. 하지만 이것이 앞머리 몇가닥에 의해 캐릭터가 달라지는 만화적 관점에서 본다면 유지되는 것도 괜찮은 것 같다. 그리고 무엇보다 중요한 건 머리카락이 아니다! 이러한 정책은 향후의 작업량에도 많은 영향을 준다. 따라서 앞머리를 고정해보자. 아무리 단단히 고정해도 유니티에선 조금씩은 움직인다. 다이나믹 본이 있으니까.

두번째로 많았던 의견은 ‘왜 팬티가 민트색이야?’라는 의견이었다. 그것은 개인적 취향이므로 안고칠 예정이다. (여담이지만 이건 일부러 좀 튀게 했다. 흰색은 너무 흔하고, 너무 어울리면 그냥 유니폼같아서.)

원래 닐리의 장풍모션은 원래는 서서 지팡이만 까딱이는 수준이었다. 하지만 실제로 게임에 적용해 보니 발사지점이 높아서 장풍을 앉아서 피할 수 있는 문제가 있었다. 그 때서야 왜 스파2 터보(..맞나?)의 춘리가 왜 그런 엉거주춤한 자세로 장풍을 쏘는 지 깨닫게 되었다. 서나 앉으나 장풍이 맞아야 하는 문제도 있지만, 낮게 날아가는 장풍은 점프로 피하기도 쉬운 것이다. 정말 많은 시행착오끝에 나온 게임이었겠구나. 싶었다.

6.13

야호. 다 했다. 대시는 추후 작업이다. 며칠 전에 지인사무실에서 간이테스트를 했던 적이 있었는데, 가장 개선되었면 좋을 것 같은 요소였다. 21세기 유저가 플레이하기엔 아무래도 답답한 모양. 그래서 추가하기로 결정했다.

달래의 필살기 작업으로 넘어가자. 얘도 할 것이 참 많다.

닐리의 이펙트 #2

6.8

이펙트가 루프되는 경우, 이펙트가 사라질 때 바로 active를 끄면 안된다. 갑자기 사라져 어색하기 때문이다. 난 코루틴을 매우 싫어하지만, 이런 걸 처리하기엔 또 코루틴만한 게 없다.

오늘의 깨달음. 파티클의 라이프타임은 3가지가 있는데 Constant, ConstantMin, ConstantMax가 그것이다. 이 중 Constant는 항상 ConstantMax값과 같은 값을 리턴한다. 따라서 이걸 계산해 Duration으로 맞추고 Looping을 끄면 … 의미없네…? 그냥 Duration을 짧게 맞춰두면 된다. 게다가 길어봐야 5초니까…

…를 생각하다가 챗GPT에게 물어봤는데 훨씬 간단한 방법이 있다.(…)

    public void RemoveLoop(GameObject effect)
    {
        ParticleSystem[] particles = effect.GetComponentsInChildren<ParticleSystem>();

        foreach (ParticleSystem particle in particles)
        {
            particle.Stop();
        }

        StartCoroutine(CoroutineRemoveLoop(effect));
    }

    IEnumerator CoroutineRemoveLoop(GameObject effect)
    {
        ParticleSystem particle = effect.GetComponent<ParticleSystem>();

        while (particle.IsAlive(true))
        {
            yield return null;
        }

        Remove(effect);
    }

particle.Stop()은 생성을 멈추는 거고 IsAlive()는 잔여파티클이 완전히 사라졌는가 조사하는 것이다.

그른데 만들어놓고 보니 이거 찰 땐 불 안붙이는 게 자연스러워 보인다(…) 빼자.

파이어볼의 작은 파편 불꽃들은 이펙트가 명중한 후에도 남아야 한다. 하지만, 파이어볼 본체는 사라져야 어색하지 않다. 그렇기 때문에 2개의 처리는 다르다. 이걸 위해 발사체변수에 tailEffect를 넣었다.

아직 발사할 때와 맞을 때의 이펙트가 덜 됐지만 졸려서 여기까지.

6.9

‘마법을 사용하고 있다’라는 신호를 주기 위해 지팡이 끝에 이펙트를 달이야 한다. 이에 이펙트 탈부착 시스템이 필요했고, 이를 구현. 발사 이펙트 자체는 어려운 작업이 아니지만, 시스템을 잡느라 오래걸렸다. 그리고 알아낸 놀라운 사실. 지금까지 지팡이 본이 익스포트 안되고 있었다! 잘도 돌아갔군.

더불에 머티리얼 관리 문제도 새롭게 부상했다. 마법사라서 그런지, 생각보다 머티리얼이 많이 나온다.

6.10

이제 메테오를 만들자.

메테오- 두두두두

트레일도 달고,

이펙트는 끝나가지만 모션은 아직 더미이다. 일단 잡히는 모션에 이펙트를 추가하고, 애니메이션을 손보기로 하자.

6.11

잡기에 마법적인 요소가 들어있으므로, 이펙트를 추가하자.

이펙트를 만들고 붙이는 데 시간이 너무 오래 걸린다. 뭔가 좋은 방법이 있을 것 같은데…

닐리의 이펙트 #1

6.5

닐리는 방어할 때 얼음을 사용할 예정이다. 본래는 애니메이션 작업을 해야 하지만, 얼음을 얹었을 때 모션을 정확히 보려면 셰이더가 우선구현되어야 한다. 때문에 얼음 셰이더가 필요한데, 이것은 곧 굴절셰이더이다. 이는 이미 빗방울을 구현할 때 해보았지만, 이는 셰이더 그래프를 통한 포스트프로세스로 구현한 것이고, 입체적인 모양은 다시해야 한다. 이건 모르니까 유튜브를 찾자.

굴절을 아주 정확하게 구현하려는 것은 아니니, 그 자체는 어렵지 않다. 하지만 SceneColor를 어찌가져오는지 몰랐다. 여기에 잘 설명이 되어 있는데, 문제는 GrabPass{}를 URP에선 못쓴다고 한다.

chatGPT에게 물어보니 URP에선 이것 대신 _CameraOpaqueTexture를 사용하면 된다고 한다. 이 텍스처는 반투명렌더 전의 오파쿠 상태를 텍스처로 사용할 수 있게 해준다. 때문에 Transparent큐에서만 사용할 수 있다. AlphaTest에서 사용해도 고장난다.

기본형은 다 만들었으니 이제 꾸며보자.

소품이 점점 늘어난다.

된 것 같음.

6.6

얼음 셰이더는 완성을 했으나 문제가 하나 있다. 타격효과까지 굴절되어 버리는 것이다. 이를 원하지 않으므로 ZTest를 Always로 설정해주고 싶다. 이를 위해선 ZTest부분을 열거형으로 설정해서 제어해주어야 한다.

    Properties
    {        
        [NoScaleOffset] _MainTex ("Cutout Texture", 2D) = "gray" {} 
        [HDR] _Color ("Color", Color) = (1, 1, 1, 1)
        _Threshold ("Cutout Threshold", Float) = 0 
        
        [KeywordEnum(Less, Greater, LEqual, GEqual, Equal, NotEqual, Always, Never)] _ZTest("ZTest Mode", Float) = 2        
    }

Enum어트리뷰트는 쓸 때마다 맨날 까먹는데, 자료도 별로 없어서 검색해도 잘 안나온다. chatGPT도 잘 모른다. 이 기회에 적어두자. 이후 커맨드 설정부에서

        Pass
        {            
            Cull Off
            Zwrite On
            ZTest [_ZTest]

일케 써주면 사용할 수 있다. 참고로 블렌드 모드는 엔진에 이미 지정이 되어 있는데

[Enum(UnityEngine.Rendering.BlendMode)] _BlendMode ("Blend Mode", Float) = 1

요래 선언하면 된다.

확실하게 앞에 찍기 위해 큐도 하나 높여준다. 빌드 테스트도 완료. 잘 돌아간다. 내부적으로는 셰이더가 2개로 분리되었을 것이라 추정한다.

얼음 작업이 이어지는 가운데, 입이 유별나게 하얘써 살펴봤더니… 오.맙소사. Transparent큐에서는 그림자 정보를 받지 못한다!

별 수 없이 컷아웃을 써야 한다. 이걸 안쓰고 싶었던 이유는 립스틱 때문인데… 포기해야 할 듯.

얼음은 주변의 빛을 반사하기 때문에, 스테이지마다 색이 달라야 한다.

되게 번거롭다.으악!

6.7

닐리의 트레일을 처리하던 중 트레일 구동방식이 좀 잘못되어 있음을 깨달았다. 이대로 진행해도 괜찮지만, 별로 깔끔하지가 않아서 앨리스로 거슬러 올라가 다시 처리하기로 했다. 트레일 코드를 고치고, 익스포트를 하고, 유니티에서도 셰이더 코드를 수정하고…다시 닐리로 돌아온다. 분명 귀찮은 일이지만, 각잡고 하면 의외로 빨리 끝난다.

한 동작이지만, 컨트롤러가 없으니 또 허전해서 추가.

영락없는 가일.

하지만 하나 달라야 하는 것이… 불속성이어야 한다. = 맞은 상대는 불에 타야 한다. = 셰이더를 만들어야 한다.

이글이글… 기본적인 원리는 킹오파에서 파렛 오프셋(?)에서 아이디어를 얻었다. 하지만 이것만으로는 좀 모자라고…

불은 어차피 필요하니 미리 만들어 두자. 파티클 생성시에 SDF를 두껍게 썼더니 적절하게 볼륨감이 생겨서 예쁜 모양이 됐다.

활활. 이제 붙이자.

닐리의 2기 애니메이션 제작 #1

6.1

닐리의 컨셉은 가일이다. 어쩌다보니 그렇게 됐다. 필살기 계획은 다음과 같다.

  • 파이어볼(FireBall) : ←모으고 → A, B
  • 섬머솔트킥(RollingJumpKick) : ↓ 모으고 ↑ K
  • 날기(Wing) : 공중상태에서 ↑모으기. 다 모이면 앞으로 날아간다.
  • 메테오(Meteor) : ← 모으고 →←→ B. 초필

마법사를 격투 게임에 녹여내려니 파이어볼 외에는 생각이 안나고, 가일이니까 대공기 하나 쯤 있어야 하니 섬머솔트킥을 넣었다(?)

그 외에도 추가 모션들이 필요하다. 앨리스 때 설정한 것에서 스턴이 빠지고 좀 더 추가됐다.

  • 방어 (Block)
  • 앉아서 방어(CrouchBlock)
  • 소점프킥(SmallJumpKick)
  • 소점프킥 착지(SmallJumpKickLanding)
  • 일직선 날아가기(DamageFlying)
  • 날아가 벽에 부딪히기(DamageFlyingWall)
  • 바닥에 엎드려 떨어지기(KnockDownFront)
  • 공중에서 바닥에 꽂히기(DamageJumpSlam)
  • SlamAir의 넉다운 모션(KnockdownSlam) : DamageSlam에서 짤라쓴다.
  • 회전하며 맞기(DamageScrewCW)
  • 회전하며 맞기(DamageScrewCCW)
  • 맞고 날아가기(DamageKnockback) : DamageJumpHeavy와 같다.

모으기 기술의 특징은 사용이 어려운 대신 발동딜레이가 짧다는 것이다. 앨리스의 기술들이 6~12프레임의 발동딜레이를 가진다면, 닐리는 좀 더 빨라야 한다. 모션을 만들 땐 이 점에 주의해야 한다.

날기를 구현하기 위해선 빗자루가 필요하다. 마법사니까!

아무리 간단한 사물이라도 꼭 러프를 그려보는 편이 좋다.오랫만에 다 까먹었을 것 같은 모델링을 해보자.

블렌더엔 커브챔퍼기능이 없다. 이게 없어서 그동안 애드온을 깔아서 썼었는데, 블렌더가 버전업되며 더 이상 그 애드온을 지원하지 않게 되었다. 혹시 4.0의 커브에 챔퍼 혹은 베벨기능이 추가됐을까? 싶어서 살펴보았지만 보이지 않는다.

그런데 유튜브에 튜토리얼을 찾아보니 Curve가 아닌 Mesh상태에서 베벨을 준 후 커브로 옮겨오는 것이 아닌가…? 그..그러네?! 왜 이 생각을 못했지? 맥스 기준으로 생각하다보니 당연히 있어야 할 것이 없다는 생각이었는데, 블렌더는 엣지 모델링이 가능하므로 이 쪽에 맞추어 생각을 해야 한다. 오늘의 깨달음. 커브의 베벨을 사용하려면 메쉬를 써라.

모델링을 하고

색칠을 하자.

6.2

이제 모션을 러프하게 제작한다. 이 모션들을 기반으로 코드를 짜자.

익스포트를 해서 본격적으로 코드를 짜려고 하니 버그가 말도 안되게 많이 나왔다. 한숨 잔 다음 맑은 정신으로 도전하는 편이 좋겠다.

타격 시 밀리는 양에 따라 먼지를 조절하고 싶어서 파티클의 이미터에 접근해야 하는 코드가 필요했다. 그런데 유니티의 버스트는 구조가 이상하다.

            foreach (ParticleSystem particle in particles)
            {
                ParticleSystem.EmissionModule emmision = particle.emission;

                int burstCount = emmision.burstCount;
                ParticleSystem.Burst[] bursts = new ParticleSystem.Burst[burstCount];
                emmision.GetBursts(bursts);

                for (int i = 0; i < bursts.Length; i++)
                {
                    bursts[i].cycleCount = (int)(Mathf.Abs(pushDistance) / 0.1f);
                }

                emmision.SetBursts(bursts);
            }

GetBurst()는 Burst객체를 리턴하고 GetBursts()는 배열을 리턴해야…. 할 것 같은데 int를 리턴한다.(??) 기존 버스트의 숫자하나를 바꾸고 싶을 뿐인데, 새 인스턴스를 만들어서 갈아끼우는 비효율적인 방식을 쓰고 있다. 알고 보니 GetBurst()로 얻은 객체도 읽기 전용인 듯? Get은되는데 Set이 안된다.

으..모으기 처리도 쉽지 않다. 키가 많이 충돌하는데, 조용한 새벽에 각잡고 봐야할 것 같다.

6.3

키처리 완료. 이제 1초를 모아야 장풍이 나간다. 어우.. 어렵다. 그런데 앉아서 대기군인 하려니 키 충돌이 있다… 세상에! 21세기에 키충돌이라니!

…를 다시 조사해보니 코드에 L,R입력 중 하나만 받게 되어 있었다. 둘 다 누르면 선입력된 것만 적용된다. 그..그럼 그렇지.

섬머솔트 킥! 잘 어울린다. (?)

발사체는 현재 데이터가 없는데, 생각보다 많은 데이터가 필요하다. 이에 대한 시스템을 먼저 구축해야 할 것 같다.

6.4

오늘의 깨달음.

유니티의 c#스크립트에서 그냥 tag를 불러와도 해당 게임오브젝트의 tag를 알아서 리턴한다. 굳이 .gameObject.tag 로 안써도 된다. 원래 이랬나..?!

발사체를 맞았을 때의 밀림처리, 발사체가 화면 밖으로 나갔을 때의 처리등을 구현했다. 풀매니저는 필요없을 거라 생각했는데, 안만들었으면 큰일날 뻔했다.

그냥 게임매니저 아래에 마구잡이로 저장해놓았던 리소스들은 순식간에 늘어난다.

닐리의 기본 콤보. 모으기 커맨드는 정말 어렵다.

버그 픽스

5.31

이펙트 매니저를 손보며 발생한 문제가 꽤 됐었다. 그런데 절반 정도는 그냥 게임로직에 관련된 것이라는 것이 웃기다…여튼 이런 작은 것들을 손보다 보면 게임이 좀 더 완성됐다는 느낌을 받아서 기분이 좋아진다.

눈깜빡임은 간헐적으로 일어나야 한다. 현업에 있을 땐 이런걸 애니메이션에 박아넣곤 했는데, 이것이 캐릭터를 로봇처럼 보이게 하는 원인이 됐었다. 이런 비정기적 움직임은 랜덤수를 이용해 코드로 처리하는 것이 자연스럽다.

그 외에 눈에 보이지 않는 작업을 처리. .. 끝인가!? 일찍 끝났네?!

이제 닐리의 2기 애니메이션 작업으로 넘어가자

앨리스의 이펙트 #2

5.28

유니티의 셰이더는 프로퍼티의 이름이 변하면 정보가 초기화된다. 때문에 애써 맞춰놓은 색상정보가 날아가기 쉽다. 원론적으로 이야기하자면 프로퍼티의 이름이 변하면 안되지만, 개발하며 어디 그게 쉬운 일인가. 이름으로 판독하는 처리가 얼마나 많은데.

때문에 나중에 닥쳐올 불행을 미리 대비하는 마음으로 레벨데이터 매니저를 새로 만들었다. 씬의 번호에 따라 미리 세팅된 조명과 먼지의 색정보등을 넣어주는 방식이다.

하지만 작업을 하고 나니 문제가 또 있는데, 셰이더가 늘어난다…! 별로 바람직하지가 않다. 프로퍼티로 구분하면 안될 것 같고, 파티클이름으로 구분해야 할 것 같다. 그럼 파티클을 만들 때마다 이름에 신경써야 하잖아…싶었는데 별수가 없다. 다시 되돌리자.

많은 고민 끝에 배경과의 호환을 위해 파티클의 게임오브젝트에 이름을 예약어로 사용하기로 했다. dust, stratum, soil, crack의 이름은 예약어로 사용된다. 리소스의 이름엔 항상 앞에 대문자를 붙이는 규칙이 있으니, 원칙적으로는 충돌하지 않는다. 그 외 HDR로 지정된 컬러프로퍼티엔 리니어변환을 해주어야 한다. 그런데 이게 정확하지가 않다… 이에 대해 조금 조사를 했는데 최종 화면에 나오는 컬러를 구하는 법은 톤매핑까지 거치며 매우 복잡해지는 것 같다. 뭐 그렇게 중요한 것은 아니고 비슷하게는 나오니, 넘어가기로 하자.

이제 스테이지별로 이펙트가 다른 색깔로 표현된다.

머티리얼을 정리하고, 발도장 이펙트도 완료…했는데 너무 후져서 사거리 좀 늘려야 할 듯

5.29

아휴. 안끝나…

어류겐할 때 검기 모양이 동그란게 안어울려서 셰이더 로직을 수정하자.

하고 싶은 걸 해봤는데 별로 안예쁘다…되돌리자.

요 기술엔 둥그런 먼지를 추가.

공중에서 Slam데미지를 맞을 경우의 처리가 되어있지 않아서 처리했다.

데미지 모션이 정말 많다. 포스트는 이펙트 작업인데, RnD작업이 훨씬 더 많아.

5.30

이래저래 삽질이 많았던 작업프로세스는 점차 분명해져간다. 모든 문제는 결국 어떤 방향으로든 해결되기 마련이다. 그렇다면 이 쯤에서 효율성에 대해 한 번 더 고민을 해보자.

지금은 이펙트를 Left/Right를 분리해 만들고 있다. 파티클시스템은 단순히 스케일-1로 해결되지 않는 경우가 많기 때문이다. 이거… 정말 안될까?

스케일을 좌우반전했을 때, 문제가 되는 부분은 파티클이미터가 기울어져 있는 경우이다. 이것은 트랜스폼이 아니고 이미터의 정보이기 때문이다. 그럼 트랜스폼을 기울이면 될 것 아닌가?

…는 전혀 엉뚱한 값이 튀어나온다. 안되나 보다.

위치는 반전이 된다. 그렇다면 기울어져 있는 이미터의 각도만 바꿔주면 되는 것 아닐까?

이미지를 바꿔보니 문제가 하나 더 있다. 이미지는 Flip되어야 한다. 일단 여기까지 적용가능 여부를 확인해보자.

오? 일단 요기까지는 작동한다. 시운전 끝났으니까 실전에 적용해보자.

2시간 가까이 시도했…지만, 실패했다. 고려할 게 너무 많다. 그렇다고 조건을 줄이면 이펙트 제작에 제약이 많아진다. 이거 정말 안되네. 에이…

오늘의 깨달음. 프로퍼티의 HDR은 단순히 숫자를 1이상 쓸 수 있도록 해주는 것이 아니다. Color프로퍼티를 좀 일원화시켜보고자 이를 적용해봤는데, 그냥 컬러는 톤매핑을 거치지 않은 러프한 색을 내보낸다.

방어 이펙트도 작업완료. 맞은 후엔 배우는 것이 있다.

5.31

일단 이렇게 앨리스의 이펙트를 완료. 파란색 머리는 2P가 헛갈려서 바꿔놓은 것이다.

이펙트 시스템을 구축하며 헤집어 놓은 코드들 때문에 버그가 많이 쌓였다. 이를 한 번 정리하고 가는 편이 좋아보인다.

앨리스의 이펙트

5.24

먼저 기존의 이펙트를 조금 손보아야 한다. 먼지 이펙트는 지금까지 무언가 2%부족한 느낌이 있어서 바닥과의 연결부가 되는 이펙트를 추가하자. 원래는 캐릭터처럼 뒤쪽에 그림자를 뿌려볼 생각이었는데, 파티클이 머티리얼을 1개밖에 받지 못한다. 그래서 셰이더를 개조해 한 번에 2번을 그릴 수 있는 2pass셰이더로 만들었더니, 이번엔 또 두번째 패스에서 커스텀 데이터를 받지 못한다. 옘병!

별 수 없이 아랫부분에 그림자스러운 그라데이션을 약간 주고, 점프할 때 ‘팟!’하는 느낌의 쇼크이펙트를 추가하자. 이것은 시간으로 따지면 0.2초 정도 되는데, 이 짧은 순간의 유무가 완성도에 상당한 영향을 끼친다.

그리고 이 결론을 얻기까지 저녁 작업 시간을 모두 할애했다….나머지는 내일

스샷찍고 나니 위치가 좀 안맞는다…

이제 먼지는 된 것 같고,

파티클은 좀 더 작은 입자를 추가.

기존 작업 수정은 끝났고, 해야 할 것들에 대해서 정리해 보자.

공용 이펙트:

  • Grappling – 잡았을 때.
  • DustDamageSlam – 내리꽂기 공격을 당했을 때. (돌이 튀어야 한다.)
  • DamagePush – 데미지를 받고 크게 밀릴 때
  • Block – 방어했을 때

앨리스 이펙트

  • AliceCrouchKickDust – 둥글게 땅을 훑는 스타일의 먼지
  • AliceCrouchPunchHeavyDust
  • AliceTripleAttack_Dust_01
  • AliceTripleAttack_Dust_02 : 01과 같은데 좀 더 길다.
  • AliceUpperSlash
  • AliceStomp
  • AliceBash

그런데 이펙트의 위치를 어떻게 잡을 것인가? 결국은 데이터가 필요하다. 먼저 애니메이션 이벤트리스너에 Effect()를 추가하고, 여기에 데이터문자열을 건네준다. 데이터는 스트링과 구조체의 딕셔너리로 이루어진다.

        effectData["SuperAttack"] = new EffectDataStruct{
            prefabString = "SuperAttack",
            followCharacterDirection = true,
        };

        effectData["DustLanding"] = new EffectDataStruct{
            prefabString = "DustLanding",
        };

쓰고 나니 현재 열거형으로 사용하고 있는 State도 딕셔너리로 처리하면 편하지 않았을까. 싶긴 한데, 속도면에선 그냥 열거형에 접근하는 쪽이 아무래도 빠를 것 같다. (업데이트에서 정말 뻔질나게 찾으니까…)

이로서 애니메이션 이벤트에서 이펙트를 부를 수 있게 됐다. 이걸 위해 흩어져 있던 이펙트코드를 한 데 모아 처리하는 정리작업을 병행했다. 그 와중에 버그가 있어 그걸 추적하느라 시간이 좀 더 걸렸다.

5.26

잡기이펙트는 순간 삐죽한 웨이브가 둥글게 회전하는 형태로 만들고 싶다. 이를 구현하려면 먼저 셰이더를 개발해야 한다.

대강 이런 느낌이다. 파티클에 입히자.

적용하기 위해선 코드를 수정해야 한다.

..가 버그를 안내려면 데이터를 등록해야 한다.

…를 정확한 위치에 뿌리려면 본의 위치를 참조해야 하므로 애니메이션을 수정해서 다시 익스포트를 해준다.

이제 적용됐다. 하루가 다 갔다. 아이고.

5.27

글 제목은 ‘앨리스의 이펙트’인데 아직도 공용이펙트만 작업중이다. 그런데 앨리스는 늘 그랬다. 그래서 가장 애정이 가는 캐릭터이기도 하다.

이제 내리 꽂혔을 때의 데미지 이펙트를 만들어보자. 땅이 갈라지며 조금 튀어나오면 좋겠다. 파티클로 사용하기 위해 치즈조각을 하나 모델링하자.

갈라지는 지형은 배경마다 다르다. 이를 위해 바닥과 지층을 구분해 칠할 것이다. 잠깐 나오고 사라질 애니까 텍스처까지는 좀 거하고 버텍스 컬러를 써서 구분하도록 하자.

이제 여기에 사용할 셰이더를 만들어주자. 솔리드 셰이더를 간단하게 축소하면 될 것이다.

여기저기 각이 져서 간단히 NdotL만 해도 예쁘다.

그렇게 완성된 이미지. 이 이펙트는 맞은 직후가 아니라, 맞고 나서 2프레임 후에 출력되어야 하기에 이와 관련된 코드작업을 병행했다. 하지만 새로운 문제가 발견됐다. 프레임이 안맞아! 맞는 순간 1프레임이 먼저 재생된다.

이제 와서 이를 해결하기 위해선 약간의 비효율을 감수해야 한다. 하지만 대충 하자.

먼지와 암석의 색깔등은 스테이지마다 달라야 한다. 이를 위해 데이터 베이스를 구축해야 한다. 원래는 좀 더 후반작업으로 생각하고 있었는데, 셰이더가 많아지면서 더 늦추면 안되겠다는 생각이 들었다.

앨리스의 2기 애니메이션 제작 #2

5.20

입력고장은 간단한 문제였다. 캐릭터를 강제로 미는 값이 있다면 방어로 인식하게 했는데, 이것이 대쉬와 값이 겹치며 내는 오류였다.

문제는 점점 정교해진다. 이번엔 충돌이 문제다. 현재 캐릭터는 빠른 속도로 지나가는 캐릭터를 막지 못한다. 대시할 때 한 프레임에 움직이는 이동량이 캐릭터를 넘어버리기 때문에, 두 캐릭터의 위치가 바뀌게 되는 현상이 있다. 이는 곧 벽체크에 걸려 다시 제자리로 돌아오긴 하나, 완성도가 떨어져 보이므로 수정해야 한다.

새벽에 이 문제를 3시간동안 살피다가 포기하고 잤는데, 자고 일어나니 10분만에 해결했다. 허탈해! 충돌이 문제가 아니었어!

프레임과 타이밍을 조절하고, 세부 조절이 끝나면 본격적으로 애니메이션을 만든다.

연계기가 들어가니 또다른 문제가 보인다. 검기의 셰이더 드라이버가 한 프레임 늦게 갱신됨에 따라, 연계시에 잘못된 정보를 보여준다.

업데이트를 한탐 늦게 하면 될 줄 알았는데, 예상대로 안되길래 그냥 모션 시작시에 검기를 숨겨서 물리적으로 해결했다. 마음에 드는 해결책은 아니지만…이걸 시간들여 해결할만한 가치가 있는가? 도 의문이긴 하다.

연계기 – 강베기인데, 다 만들어 실제로 써보니 그렇게 예쁘지도 않고, 효용성도 떨어져서 삭제. 오래걸렸는데…흑흑.

이로서 연계기의 형태는 좀 더 단순해진다.

A-A-A

A-A-B.

스톰프는 이펙트가 있어야 완성된다. 타격은 2번 일어나는데 맞으면 한 번만 맞는다. 하단이지만 발동도 느리기 때문에 방어데미지를 주는 용도

5.23

모든 초안은 쓰레기다. 소점프킥 모션을 수정.

본체 애니메이션이 끝난 후, 세컨더리 애니메이션까지 완료. 이제 너무 자잘한 건 신경쓰지 않게 된다.

초필은 2라운드당 한 번 정도 사용하게 디자인할 예정이지만, 정말로 극단적인 경우 둘이 동시에 초필을 발동할 수도 있을 것이다. 그럴 경우를 대비해서 코드를 수정해 준다.

자잘한 버그 수정까지 했으니 이제 이펙트로 넘어가보자.

앨리스의 2기 애니메이션 제작

5.16

애니메이션 제작 계획은 3기로 나뉜다.

  • 1기 : 지금까지 작업했던 기본이동+공격들
  • 2기 : 커맨드 기술과 그에 따른 데미지, 방어, 스턴등
  • 3기 : 승리 및 등장, 도발, 캐릭터 선택, 다이얼로그등의 연출 애니메이션

양은 1기가 가장 많은데 후반으로 갈수록 애니메이션의 디테일이 높아진다.

이제 어렴풋한 생각들을 구체화시켜야 한다. 일단 필요한 작업들에 대해 목록을 뽑자. 모든 일의 시작이다. 이 때 개발 코드명을 같이 설정하면 좋다. 공용모션에 관한 목록들을 먼저 설정해보자.

  • 방어 (Block)
  • 앉아서 방어(CrouchBlock)
  • 소점프킥(SmallJumpKick) : 커맨드 ↑K . 이것은 점프 공격 후 높은 확률로 하단 공격을 하는 플레이의 이지선다를 위한 것이다. 모든 캐릭터가 가지고 있으며, 점프 공격으로 분류되기 때문에 서서 막아야 한다.
  • 소점프킥 착지(SmallJumpKickLanding) : 소점프킥 후 착지모션이다. 밸런스상 강공격으로 분류해야 하기 때문에 모션을 따로 둔다.
  • 일직선 날아가기(DamageFlying) : 화면끝으로 일직선으로 날아가 부딪힌다.
  • 날아가 벽에 부딪히기(DamageFlyingWall) : 벽에 부딪혀 아래로 떨어진다.
  • 바닥에 엎드려 떨어지기(KnockDownFront) : 일어서기와 연계되려면 DamageSlam의 끝 모션과 같아야 한다.
  • 공중에서 바닥에 꽂히기(DamageSlamAir) : 밑으로 내리치는 공격을 했을 때의 데미지 모션이다.
  • SlamAir의 넉다운 모션(KnockdownSlam) : 이는 DamageSlam의 중간부분을 짤라쓰자.
  • 회전하며 맞기(DamageScrewCW) : 몇몇 공격은 상대를 회전시킨다. 시계방향으로 돈다.
  • 회전하며 맞기(DamageScrewCCW) : 반시계방향으로 돈다.
  • 기절(Stun) : 데미지가 누적됐을 경우 헤롱헤롱

주로 강한 공격에 관한 데미지 모션들이다. 다음은 스킬.

커맨드 기술을 2기 작업으로 잡아놓은 것은 기획을 못했기 때문이다. 앨리스는 1번캐릭터니까 아도겐,어류겐은 있어야지…싶었는데, 정작 계획하고 나니 그런 캐릭터들이 너무 많다! 때문에 앨리스는 장풍을 배제했다.

  • 3연참(AliceTripleSlash_01_A, AliceTripleSlash_01_B) : [↓→A or B] 앞으로 대쉬하며 공격, A,B는 대쉬거리의 차이. 이후 A,B 입력에 따라 연계기 형태가 바뀐다.
    • AliceTripleSlash_02_A : 짧고 약하게 공격. 01을 히트했다면 무조건 히트한다. 상단
    • AliceTripleSlash_02_B : 길고 강하게 공격. 상단
    • AliceTripleSlash_03_A : 짧고 약하게 공격. 02를 히트했다면 무조건 히트. 넉다운 된다.상단
    • AliceTripleSlash_03_B : 소점프 베기. 공중공격으로 분류된다.
    • AliceTripleSlash_03_B_Landing : 공격 후 딜레이.
  • 어류겐(AliceUpperSlash_A, AliceUpperSlash_B) : [→↓→A or B] 대공기. A, B는 점프높이의 차이. B의 경우 K를 눌러서 추가타를 넣을 수 있다. 상단
    • AliceUpperSlash_B_K: 추가타.
  • 발도장(AliceStomp) : [↓←K] 발을 굴러 땅을 진동시킨다. 하단
  • 매우 쎈 강베기(AliceBash) : [↓→↓→B] 초필. 하오마루의 그것. 막아도 아프다.

근사한 이름이 있었으면 좋겠다… 여튼 설정은 끝났고, 하나하나 제작해보도록 하자.

일단 가드부터.

소점프킥.

어류겐 러프.

5.17

대공기 후에 추가타를 맞으면 캐릭터는 수직 비행해야 한다. 이것의 이름에 Flying을 사용하려 했는데, 이것이 기존에 사용하던 잡기 후 날아가기와 겹친다. 따라서 기존의 Flying은 Throwing으로 바꾸고 Flying은 일직선 이동을 의미하도록 변경하는 편이 좋겠다.

이런 리팩토링 작업은 꽤 성가시지만, 문제가 너무 깊어지기 전에 해결하는 편이 나중을 위해 좋다.

어류겐 강공격후 발차기 연계 러프. 이걸 하나 하려고 Flying관련 스테이터스를 추가하고 카메라 흔들기를 구현…하고 나니 소점프킥이 고장났다.. 내일하자.

연계기 처리 리팩토리. 중복코드는 최대한 피하고 싶은데 마음처럼 깔끔하게 되지가 않는다. 선입력 때문에 키입력 시간과 스테이트 발동시간이 일치하지 않기 때문. 점점 코드에서 스파게티 맛이 난다. 흑흑

5.18

오늘의 깨달음. 익스포트 시 모션이름에 빈 칸이 있으면 데이터가 제대로 넘어가지 않는다.

앨리스의 필살기 러프 스케치. 아우. 타이밍 어려워! 조작도 어려워!

코드를 또 한 번 정리했다. 다행히 잘 돌아가는 것 같다.

필살기는 스테이트 데이터가 매우 복잡한 양상을 띈다. 내일은 필살기 나머지를 구현하고 타이밍을 맞추자.

5.19

발도장은 하단이다. 얘는 구현이 별 게 없다.

초필은 사실 넣을까 말까 많은 고민을 했다. 왜냐면 이게 조작이 어렵고, 연계기를 통한 뉴비학살 기술로 많이 쓰이기 때문이다. 때문에 진입장벽을 높이는 주원인이 되는데, 곰곰히 생각해보니 멀티를 구현할 것도 아닌데 이 화려함을 포기할 필요가 있을까? 싶어 그냥 넣기로 했다. 스파2로 시작했지만 결과적으로 KOF와 비슷해지고 있다.

내일은 초필을 맞았을 때의 스크류 데미지 처리, 그리고 방어를 구현해 보자.

5.20

맞았을 때 빙그르르. 예전 홍콩 느와르 영화에서 많이 보이던 맞기 동작이다. KOF의 료가 일격필살을 사용했을 때 데미지 모션이 꽤 인상적이었기 때문에 넣기로 했다.

방어는 꽤 어렵다. 오래전 짜 놓았던 코드 때문인지 작동은 되는데… 입력 조건을 어찌짜야할지 고민이다. 내일할까…

또 한 번 대규모 리팩토링. 그런데 또 체인콤보가 고장났다.

세컨더리 애니메이션 보강

5.14

타격 시 캐릭터는 잠깐 멈춘다. 이 때의 다이나믹 본은 많이 흐트러져 있기 때문에 그리 예쁘지가 않다. 특히 잡기의 경우, 사용자의 입력에 따라 캐릭터가 갑자기 워프하기 때문에 다이나믹본은 변화가 크다고 인식하고 엉뚱한 값을 적용해버린다.

이걸 잡아보자. 작업이 크기 때문에 일부만 작업해서 느낌을 보는 샘플 작업이 필요하다.

확실히 낫다. 영상으로 보면 큰 티가 안나지만, 이 작업의 최대장점은 스샷이 예쁘게 찍힌다는 것이다.

단점은 너무너무 귀찮다는 것.

앨리스는 닐리에 비하면 별로 할 게 없다. 쉬어가는 코스.

달래도 머리카락만 대충 맞춰주고 마무리

오로라는 머리가 짧아서 안해도 될 것 같으니 패스하자.