Direct3D의 초기화 작업에 필요한 기본 형식 및 몇 가지 기본적인 그래픽 개념을 다뤄보겠다.

 

Direct3D의 개요

  • Direct3D는 그래픽 하드웨어를 제어할 수 있는 소프트웨어 인터페이스를 제공한다.
  • Graphic Hardware가 Direct3D capable device이기만 하다면 Hardware의 구체적인 세부사항을 걱정할 필요가 없다.
    • 물론 다중 표본화 횟수 등 Hardware마다 다를 수 있는 항목들도 존재한다.
    • 그래도 Direct3D capable device는 반드시 Direct3D capability set 전체를 지원해야 한다.
  • 이는 Direct3D 9와 비교해서 가장 두드러지는 특징이다

COM(Component Object Model)

  • COM은 DirectX의 프로그래밍 언어 독립성과 하위 호환성을 가능하게 하는 기술이다.
  • C++로 DirectX Application을 개발 할  때에 세부 사항 대부분이 드러나지 않는다.
    • 프로그래머가 알아야 할 것은 COM Interface로의 포인터를 얻는 방법 뿐이다.
  • COM Interface는 C++의 new 키워드로 생성하지 않는다.
    • 또한 삭제 할 때도 delete가 아니라 Interface의 Release 메서드를 호출한다.
    • 이는 COM Object들이 자신만의 고유한 방식으로 메모리를 관리하기 때문이다.
  • COM에 관한 이야기는 이보다 훨씬 많지만, DirectX를 사용하는데 이 이상은 불필요하다.
  • 마지막으로 COM Interface들은 Class 이름이 I로 시작한다.
    • 예를 들어 DirectX11의 2차원 Texture를 나타내는 COM Interface는 ID3D11Texture2D이다.

텍스처 및 자료 자원 형식

  • 2차원 Texture는 2차원 배열로 원소 당 2차원 이미지 한 Pixel의 색상을 담는다.
  • 하지만 이것이 2차원 Texture의 유일한 용도는 아니다.
    • 예를 들어, 법선 매핑에서는 Texture의 각 원소가 색상이 아니라 3차원 Vector를 담는다.
  • Texture라고 하면 이미지 자료 저장을 떠올리지만, 실제로는 그보다 훨씬 범용적이다.
    • Texture에는 밉맵 수준들이 존재할 수도 있다.
    • GPU Filtering, 다중 표본화 등의 특별한 연산도 적용할 수 있따.
    • 더 나아가 아무 자료나 아무 자료나 담을 수 있는 것은 아니라는 점도 중요하다.
  • Texture는 DXGI_FORMAT이라는 Enumeration으로 지정된 format을 따르는 자료만 담을 수 있다.

https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format

 

DXGI_FORMAT (dxgiformat.h) - Win32 apps

Resource data formats, including fully-typed and typeless formats. A list of modifiers at the bottom of the page more fully describes each format type.

docs.microsoft.com

  • 몇가지만 예시를 들어보겠다.
    • DXGI_FORMAT_R32G32B32_FLOAT
      • 각 원소는 32비트 float 3개로 이루어진다.
    • DXGI_FORMAT_R16G16B16_UNORM
      • 각 원소는 [0, 1] 구가능로 사상되는 16비트 성분 4개로 이루어진다.
    • DXGI_FORMAT_R8G8B8A8_SINT
      • 각 원소는 [-128, 127] 구간으로 사상되는 8비트 signed int 성분 4개로 이루어진다.
  • 여기서 R, G, B, A는 빛의 삼원색과 알파(Alpha, 투명도) 성분을 뜻한다.
  • 앞서 얘기 했듯이, RGBA라 하여 반드시 Texture에 색상을 담아야 하는 것은 아니다.
    • 예를 들어 DXGI_FORMAT_R32G32B32_FLOAT에는 float로 이루어진 3차원 Vector를 담을 수 있다.
  • 또한 typeless한 Texture도 존재한다.
    • 이는 메모리만 확보해두고 자료의 구체적인 해석 방식은 나중에 Texture를 Pipeline에 묶을 때 지정한다.
    • C++의 reinterpret_cast와 비슷하다고 생각하면 된다.
    • 예를 들어, 8비트 성분 4개를 할당하되, 구체적인 자료 형식을 지정하지 않으려면 DXGI_FORMAT_R8G8B8A8_TYPELESS를 지정하면 된다.

교환 사실과 페이지 전환

  • 페이지 전환은 애니메이션이 깜빡대는 현상을 방지하기 위한 최선의 방법은 버퍼링이다.
    • 애니메이션 한 프레임 전체를 후면 버퍼에 그린 뒤, 하나의 프레임으로 화면에 표시를 한다.
    • 이는 사용자에게 프레임이 그려지는 과정을 나타내지 않는다는 장점이 있다.
  • 버퍼링을 구현 할 때에는 Hardware로 두 개의 Texture Buffer를 관리한다.
    • 화면 모니터에 표시되는 이미지 자료를 담는 것은 전면 버퍼(front buffer)
    • 화면 밖에서 현재 화면에 표시되고 있는 프레임 다음 것을 담는 것은 후면 버퍼(back buffer)
    • Front Buffer가 화면에 표시되면 Back Buffer와 역할을 맞바꾼다.
  • Back Buffer를 Front Buffer와 교환하여 화면에 표시되게 하는 것을 제시(Presenting)이라 부른다.
  • Presenting은 Buffer의 내용이 아니라 각 Buffer의 Pointer를 맞바꾸는 매우 효율적인 연산이다.
  • Front Buffer와 Back Buffer는 하나의 교환 사슬(Swap Chain)을 형성한다.
    • 이는 IDXGISwapChain이라는 Interface로 대표된다.
    • 이 Interface는 Front Buffer와 Back Buffer를 담을 수 있다.
    • 또한 Buffer 크기 변경을 위한 ResizeBuffers와 Presenting을 위한 Present 메소드를 제공한다.
  • 물론 2개 이상의 Buffer를 사용할 수도 있다. 하지만 일반적으로 2개면 충분하다.

깊이 버퍼링(Depth Buffer)

  • Depth Buffer는 이미지 자료를 담지 않는 Texture의 한 예로 각 Pixel의 깊이 정보를 담는다.
    • Pixel의 깊이는 [0.0, 1.0]으로 값이 작을수록 관찰자와 가깝다.
  • Depth Buffer는 Back Buffer의 Pixel들과 일대일 대응 관계이다.
    • 구체적으로 Buffer의 크기와 대응하는 Pixel들의 Index까지 동일하다.
  • Direct3D에서는 한 물체의 Pixel들이 다른 물체 앞에 있는지 판정 하기 위해 Depth Buffering 혹은 Z-Buffering을 사용한다.
  • Depth Buffering에서는 그리는 순서는 중요하지 않다.
    • 실제로 먼 물체부터 그리는 방법으로 깊이 문제를 해결하기도 한다.
    • 하지만 이는 크게 두가지 문제가 발생한다.
      • 하나는 커다란 자료 집합을 정렬 해야 한다는 것.
      • 다른 하나는 맞물린 형태의 물체들은 제대로 처리하지 못한다는 것.
    • 이에 반해 Depth Buffering은 Graphic Hardware 안에서 공짜로 일어나며, 맞물린 물체도 제대로 처리해준다.

Depth Buffer의 작동 방식

  • 먼저 Back Buffer를 흰색이나 검은색과 같은 기본 색으로 지운다.
    • 이 때 Depth Buffer의 기본 값인 1.0으로 초기화 된다.
  • 이후 Rendering 할 물체의 Depth Buffer 값을 비교한다.
    • 물체의 Depth 값이 Depth Buffer 값보다 작을 경우, Depth Buffer와 함께 Back Buffer 값이 갱신된다.
  • Depth 값이 작을수록 관찰자와 가까운 곳에 위치한다는 점을 생각한다면 실로 합당한 알고리즘이다.
  • Depth Buffer도 하나의 Texture이므로 특정한 자료 형식을 지정해서 생성해야 한다.
    • 이 또한 DXGI_FORMAT이란 Enumeration을 따른다.
  • 몇가지 예시를 들어보자.
    • DXGI_FORMAT_D32_FLOAT_S8X24_UINT
      • 각 Texel은 32bit의 float형의 depth 값을 가진다.
      • Stencil은 [0, 255] 구간으로 사상되는 8bit의 unsigned int형의 값을 가진다.
      • 마지막으로 용도 없이 채우는 용으로만 쓰이는 24bit의 padding으로 구성된다.
    • DXGI_FORMAT_D32_FLOAT
      • 각 Texel은 하나의 32bit float형의 depth 값을 가진다.
    • DXGI_FORMAT_D24_UNORM_S8_UINT
      • 각 Texel은 [0, 1] 구간으로 사사오디는 unsigned 24bit의 depth 값을 가진다.
      • Stencil은 [0, 255]구간으로 사상되는 8bit unsigned int형의 값을 가진다.
  • 사실 Depth Buffer는 Depth-Stencil Buffer이라 부르는 것이 더 정확하다.
    • Stencil Buffer를 사용하려면 반드시 Depth Buffer에 부착해야 하기 때문이다.

텍스처 자원 뷰

  • Rendering Pipeline에 Texture를 bind 할 수 있는 단계는 여럿 있따.
  • 흔한 용도는 다음 두가지이다.
    • Texture를 Render 대상으로 묶는 것.
      • Direct3D가 Texture에 Rendering하는 경우.
    • Shader Resource로서 묶는 것
      • Shader 안에서 Texture를 추출하는 경우
  • 이 두가지 용도의 Texture를 생성할 때에는 다음과 같이 Texture를 bind 할 단계를 지정하는 bind flag를 사용한다.
D3D11_BIND_RENDER_TARET | D3D11_BIND_SHADER_RESOURCE

 

 

https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_bind_flag

 

D3D11_BIND_FLAG (d3d11.h) - Win32 apps

Identifies how to bind a resource to the pipeline.

docs.microsoft.com

  • 사실 Texture Resource가 Pipeline이 단계에 직접 묶이는 것은 아니다.
    • 실제로는 Texture가 연고나된 Resource View를 Pipeline 단계에 묶는다.
  • 어떤 용도이든 Direct3D에서 Texture를 사용하려면 초기화 시점에서 그 Texture의 Resource View를 생성해야 한다.
  • 이러한 절차는 효율성을 위한 것으로, SDK에는 다음과 같이 나와 있다.
    • 이렇게 하면 실행시점 Runtime과 Driver가 유효성 점검과 매핑을 뷰 생성 시점에서 수행할 수 있기 때문에 결속 시점에서의 형식 점검이 최소화 된다.
  • 따라서 Texture를 Render 대상과 Shader Resource로 사용하기 위해서는 두 개의 View를 생성할 필요가 있다.
    • 하나는 Render 대상 View인 ID3D11RenderTargetView
    • 다른 하나는 Shader Resource View인 ID3D11ShaderResourceView
  • Resource View는 본질적으로 두가지 일을 한다.
    • 하나는 DirectEd에게 Resource의 사용 방식(Pipeline의 어떤 단계에 묶을 것인지)을 알려주는 것.
    • 다른 하나는 생성 시점에서 Typeless Resource의 Type을 지정하는 것.
      • 이 경우, Texture 원소를 한 Pipeline 단계에서는 float로 사용하고, 다른 단계에서는 int로 사용할 수 있다.
  • 어떤 Resource에 대한 View를 생성할 수 있으려면 애초에 해당 Resource을 생성 할 때 Bind Flag를 지정해야 한다.
    • 예를 들어 D3D11_BIND_DEPTH_STENCIL flag를 지정하지 않고 생성한 자원은 ID3D11DepthStencilView를 생성할 수 없다.
    • 무작정 생성하려 하면 다음 오류 메시지가 뜬다
D3D11: ERROR: ID3D11Device::CreateDepthStencilView: A DepthStencilView 
cannot be created of a Resource that did not specify 
D3D11_BIND_DEPTH_STENCIL.

다중표본화의 이론

  • 모니터의 Pixel들은 무한히 작지 않기 위해, 임의의 선을 완벽하게 나타내는 것은 불가능하다.
    • 때문에 Aliasing 효과가 나타나기도 한다.
  • 모니터 해상도를 키워 Pixel 크기를 줄이면 문제를 완화할 수도 있다.
  • 그러나 모니터 해상도를 키우는 것으로 해결 못할 때도 있는데, 이를 위해 Anti Aliasing 기법이 존재한다.
    • 다중표본화(Super Sampling)도 그 중 하나이다.
  • Super Sampling에서는 Back Buffer와 Depth Buffer를 화면 해상도의 4배로 크게 잡는다.
  • 3차원 장면을 4배 크기의 해상도에서 Back Buffer에 Rendering한다.
  • 이를 화면에 출력 할 때는 원래 크기로 Resolving(혹은 down sampling)한다.
  • 이 Resolving 공정은 4개의 Pixel 블록의 각 색상의 평균을 최종 색상으로 사용한다.
    • 간단히 말해서, Super Sampling은 화면 해상도를 Software 상에서 증가하는 것이라 할 수 있다.
  • Super Sampling은 Pixle 처리량과 메모리 소비량이 4배라서 비용이 크다.
    • Direct3D는 이를 대신해 다중표본화(Multi Sampling)라는 절충안을 지원한다.
  • Multi Sampling은 일부 계산 결과를 부분 Pixel들 사이에서 공유하기 때문이 Super Sampling보다 비용이 적다.
    • 4X Multi Sampling의 경우 Super Sampling처럼 해상도 4배의 Depth Buffer와 Back Buffer를 사용한다.
    • 그러나 이미지 색상을 각 부분 Pixel마다 계산하는 것이 아니다.
      • Pixel마다 1번씩만 계산하고, 그 색상과 부분 Pixel들의 가시성과 포괄도를 이용해 최종 색을 결정한다.
        • 가시성: 이를 위해 부분 Pixel당 Depth, Stencil 판정이 일어남
        • 포괄도: 부분 Pixel을 다각형이 어느정도나 덮고 있는지를 뜻하는 값
  • Multi Sampling과 Super Sampling의 차이를 잘 파악하자.
    • Super Sampling은 Pixel별로 계산되므로 한 Pixel당 부분 Pixel의 값이 다를 수 있다.
    • 반면 Multi Sampling은 Pixel당 한번 계산되어 덮인 모든 가시 부분 Pixel에 계산된다.
  • 색을 계산하는 것은 매우 무거운 연산이다.
    • 때문에 Multi Sampling이 Super Sampling에 비해 상당한 비용 절감을 이룬 방식이다.
    • 하지만 더 정확하한 Texture와 Shader Aliasing 처리는 Super Sampling이 월등하다.
  • 하나의 Pixel을 부분 Pixel로 분할하는 패턴은 Hardware 제조사마다 다를 수 있다.

Direct3D의 Multi Sampling

  • Multi Sampling을 위해서는 DXGI_SAMPLE_DESC라는 구조체를 채워야 한다.
typedef struct DXGI_SAMPLE_DESC
{
    UINT Count;
    UINT Quality;
} DXGI_SAMPLE_DESC;
  • Count
    • Pixel당 추출할 표본의 개수
  • Quality
    • 원하는 품질 수준을 지정한다.
      • "품질 수준"에 대한 구체적인 의미는 Hardware 제조사마다 다를 수 있다.
  • 표본 개수가 많을수록, 품질 수준이 높을수록 렌더링 비용이 증가한다.
    • 때문에 비용과 속도 사이에 절충선을 잘 잡아야 한다.
  • 품질 수준들의 범위는 Texture type과 Pixel당 표본 개수에 의존한다.
  • 주어진 Texture type과 표본 개수의 조합에 대한 품질 수준들의 개수를 알고 싶을때는 다음 메소드를 사용한다.
    • 주어진 Texture type과 표본 개수의 조합을 장치가 지원하지 않으면 0을 반환한다.
    • 그 외에는 주어진 조합에 대한 품질 수준 개수가 pNumQualityLevels에 저장된다.
      • 하나의 Texture type과 표본 개수 조합에 대한 유효한 품질 수준은 [0, *pNumQualityLevels - 1]이다.
HRESULT ID3D11Device::CheckMultisampleQualityLevels(
  DXGI_FORMAT Format,
  UINT        SampleCount,
  UINT        *pNumQualityLevels
);
  • D3D12에서는 해당 객체에 이 메서드를 찾을 수 없었다. 대신 다음 구조체를 발견할 수 있었다.
typedef struct D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS {
  DXGI_FORMAT                           Format;
  UINT                                  SampleCount;
  D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS Flags;
  UINT                                  NumQualityLevels;
} D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS;
  • 한 Pixel당 추출할 수 있는 최대 표본 개수는 다음과 같이 정의된다.
#define	D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT	( 32 )
  • 그러나 실제로는 Multi Sampling의 성능과 메모리 비용을 합리적인 수준으로 유지하기 위해 4개나 8개만 추출한다.
  • Multi Sampling을 하고 싶지 않으면 표본 개수를 1로, 품질 수준을 0으로 설정하면 된다.

기능 수준(Feature Level)

  • Direct3D 11에서 도입된 Feature Level은 엄밀한 기능성 집합을 정의한다.
typedef 
enum D3D_FEATURE_LEVEL
    {
        D3D_FEATURE_LEVEL_1_0_CORE	= 0x1000,
        D3D_FEATURE_LEVEL_9_1	= 0x9100,
        D3D_FEATURE_LEVEL_9_2	= 0x9200,
        D3D_FEATURE_LEVEL_9_3	= 0x9300,
        D3D_FEATURE_LEVEL_10_0	= 0xa000,
        D3D_FEATURE_LEVEL_10_1	= 0xa100,
        D3D_FEATURE_LEVEL_11_0	= 0xb000,
        D3D_FEATURE_LEVEL_11_1	= 0xb100,
        D3D_FEATURE_LEVEL_12_0	= 0xc000,
        D3D_FEATURE_LEVEL_12_1	= 0xc100
    } 	D3D_FEATURE_LEVEL;
  • 이 기능의 핵심은, 사용자의 Hardware가 특정 Feature Level을 지원하지 않는다면 그보다 더 낮은(오래된) Feature Level로 내려가서 Application을 실행한다는 것이다.
    • 이를 위해 Application은 Feature Level 지원 여부를 최신서부터 오래된 순서로 하나씩 점검해나간다.

 

------------------------------------------------

책에서 4-1챕터에 해당하는 내용들입니다.

이론적인 부분과 코드 부분이 많아서 분리해서 올리고자 합니다.

다음에는 5챕터에 해당하는 내용을 정리하고, 그 다음에는 4-2부터 남은 4챕터의 내용을 코드와 함께 정리하겠습니다.

오늘 Spawn Trap 문제를 해결하다가 남은 기간동안 더 진행이 힘들다고 판단하여 제출을 하였습니다.

평소와 같은 개발이지만 "기간 내에 해야한다."라는 압박이 있어서인지 유난히 더 지친 감이 없지 않습니다.

그래서 이번주 일요일까지는 남은 기간에는 간단하게 알고리즘 문제만 풀고, 

다음주에는 주 2회 Unreal과 주 4회 전공책 읽기를 하고자 하고자 합니다.

 

때문에 12일까지는 일지가 없을 예정입니다.

오늘 쓰는 것은 현재 직면한 문제점과 추가 이슈, 간단한 예상 해결 방안입니다.

 

1. Spawn 된 Object의 Activate 설정 문제

크게 두가지 문제가 있다.

하나는 Host에게서만 Object가 숨겨져 있고 Client에서는 숨겨져 있지 않은 것.

C++ Script에서 작성한 동작이 Host는 정상적으로 작동하지만, 

Client에서는 전혀 작동하지 않을 뿐더러 2배로 생성되어 있다.

Actor를 보이지 않게 하는 함수도 Script에 선언되어 있으나 작동하지 않는다.

Blueprint에서 따로 선언해줘야 한다.

 

다른 하나는 Object의 Collision이 제대로 Inactive 되지 않는 것.

C++ Script에서 같은 함수를 선언했으나 작동하지 않고 따로 BeginPlay에서 선언해줘야 작동한다.

 

이 부분은 Actor들에게 임시로 CollisionDisable 함수를 생성해서 해결하고자 한다.

우선은 이렇게 해놓고, 차후 Interface로 교체하려 한다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.16 개발일지  (0) 2020.07.16
20.07.15 개발일지  (0) 2020.07.15
20.07.09 개발일지  (0) 2020.07.09
20.07.08 개발일지  (0) 2020.07.08
20.07.07 개발일지  (0) 2020.07.07

오늘은 하루종일 Spawn Trap 계열에서 발생하는 문제를 해결하려 하였으나 아직 해결하지 못했습니다.

과제 내용을 정리하는 것까지 합하면 내일이나 모래까지 해당 내용을 수정하고,

그 다음날에 내용 정리해서 제출해야 할 것 같습니다.

 

때문에 오늘은 간단히 이슈만 정리합니다.

1. virtual void Activate()에서 Object가 게임 시작 시 눈에 보이지 않도록 하고 있는데 SpawnTrap은 이것이 작동하고 FireTrap은 client에서 projectile이 2배로 많이 보인다.

2. SetCollisionEnable을 호출하면 크래시가 난다.

 

이 두 부분만 해결하면 이 Trap도 완벽히 작동한다고 장담할 수 있을 것 같습니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.15 개발일지  (0) 2020.07.15
20.07.10 개발일지  (0) 2020.07.10
20.07.08 개발일지  (0) 2020.07.08
20.07.07 개발일지  (0) 2020.07.07
20.07.06 개발일지  (0) 2020.07.06

어제 문제가 있었던 Block Trap의 Wall이 Replicated 되지 않는 문제를 수정하였습니다.

이는 모든 함수가 RPC 함수임에도 객체 그 자체가 Replicated 설정이 되어있지 않아서 생긴 문제였습니다.

이를 설정하였더니 정상적으로 벽이 움직였고, 이를 토대로 다른 Block Trap을 상속받는 Trap들을 수정했습니다.

결과적으로 Block Trap 계열은 모두 Multiplay상에서 잘 작동하고 있습니다.

 

그 다음에는 Puzzle을 수정할지 다른 Trap을 수정할지 고민을 하였습니다.

Puzzle은 수정된 Block Trap과 직접 연관된 것이고, Trap은 작업이 일관적이기 때문입니다.

잠깐 고민하다가 그래도 Trap을 다 끝내놓는게 좋다고 판단하여 Trap을 마저 수정하였습니다.

 

그래서 고른 다음 타겟은 Spawn Trap 계열입니다.

간단한 RPC 함수들을 생성하여 작업을 하였는데, 몇가지 문제가 발생하였습니다.

Spawn Trap 자체는 Server에서는 정상적으로 작동하는 반면,

Client에서는 Spawn될 Actor가 숨겨지지 않은 채로 존재합니다.

그러다가 Trap이 Activate 될 때 다른 Actor가 하나 더 Spawn 됩니다.

 

Spawn Trap 계열인 Projectile Trap은 Projectile이 Character와 충돌 판정은 나나, 화면에 보이지 않습니다.

정리하자면, 두 Trap 모두 기능적으로는 어느정도 잘 작동하는 반면 시각적인 부분이 잘못 처리되고 있다는 것입니다.

 

개인적으로 조금 더 욕심을 내서 오늘 문제를 해결하고 싶었으나, 조금 멀미가 나서 내일로 작업을 미루었습니다.

고로 내일은 Spawn Trap 계열의 Trap들의 문제를 수정할 예정입니다.

그 다음에는 Teleport Trap을 넘어가고 Puzzle을 수정하고자 합니다.

Teleport Trap은 구조가 다른 Trap들과 상이하여 구조적 개선이 필요하기 때문입니다.

만약 과제에 포함이 되더라도, Puzzle을 먼저 수정해놓고 추가사항으로 하고자 합니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.10 개발일지  (0) 2020.07.10
20.07.09 개발일지  (0) 2020.07.09
20.07.07 개발일지  (0) 2020.07.07
20.07.06 개발일지  (0) 2020.07.06
20.07.05 개발일지  (0) 2020.07.05

오늘은 BlockTrap의 구현체 중 하나인 TwoSideBlockTrapExample의 벽 움직임을

구현된 Multiplay 상에서의 Character 출입 인식 함수들로 교체 작업을 진행했습니다.

 

하지만 잘 작동할것만 같았던 기능은 RPC 함수를 사용했음에도 벽이 Server에서만 움직이고,

Client에서는 전혀 움직이지 않고 있습니다.

 

이 부분을 내일 집중적으로 해결하고, 해결이 되는대로 다른 두 구현체도 이와 같은 방식으로 기능을 변경하고자 합니다.

그리고 운이 좋은건지 나쁜건지, 대부분의 Puzzle은 BlockTrap을 사용하고 있습니다.

때문에 내일 BlockTrap을 완성하면 Puzzle 기능 완성까지도 꽤 가까워집니다.

 

이래저래 시간이 오래 걸릴 것 같은 기분이 다분하지만, 가능하면 기한 내로 끝내보도록 하겠습니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.09 개발일지  (0) 2020.07.09
20.07.08 개발일지  (0) 2020.07.08
20.07.06 개발일지  (0) 2020.07.06
20.07.05 개발일지  (0) 2020.07.05
20.07.04 개발일지  (0) 2020.07.04

오늘은 외식을 하느라 개발 시간이 반토막이 나버렸습니다.

 

오늘은 Multiplay상에서 Character의 출입이 인식되도록 구현을 완료했습니다.

어제 일지를 쓰고나서 자려고 누우면서 문뜩 출입을 파악하는 변수들을 모두 Replicated 하고

RPC함수로 Queue 출입을 관리해야 할 것 같았는데

오늘 실제로 구현해보니 예상이 정확히 들어맞았습니다.

거의 두번. 아니 세번을 한달씩 시간을 꼴아박으며 얻은 교훈이 드디어 몸에 습득이 되어가는 것 같습니다.

 

남은 시간에 BlockTrap을 수정하다가 외식과 운동으로 남은 하루를 다 보냈습니다.

내일 열심히 해도 잘 될지 모르겠습니다.

화요일 전에 끝내면 Trap을 과제에 포함할까 했는데 이를 수요일까지 좀 두고볼까 합니다.

 

오버워치 리그도 이번주 휴일이고 열심히 하면 될것도 같습니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.08 개발일지  (0) 2020.07.08
20.07.07 개발일지  (0) 2020.07.07
20.07.05 개발일지  (0) 2020.07.05
20.07.04 개발일지  (0) 2020.07.04
20.07.03 개발일지  (0) 2020.07.03

일지를 쓰기 시작한 이후로 일주일 내내 개발을 한 적이 없습니다.

항상 일요일은 쉬는 날로 잡았고, 아무리 바빠도 이 날은 개발하지 않았습니다.

그 이유는 일주일 내내 개발을 하면 7일째부터 능률이 반토막이 나고, 의욕도 그만큼 떨어지기 때문이었습니다.

오늘 정말 오랜만에 일주일 내내 개발을 하였고, 역시 능률이 나지 않았습니다.

 

우선 THActorBase를 상속받아 따로 구현되던 여러 Trap들의 공통된 기능들에 대한 선언을 THTrapBase에 옮기고,

상속 관계를 수정하여 모든 Trap들이 THTrapBase를 상속받도록 하였습니다.

 

그리고 Character와의 Collision에 따른 이벤트 발생도 선언을 해두었고, 약간의 테스트를 해보았습니다.

방식은 Replicated 된 Queue 두개를 두고, 하나는 Character가 Trap의 Area 안에 들어올 때 담는 역할을,

다른 하나는 Trap이 Activate 될 때 첫번째 Queue의 내용을 두번째 Queue에 복사합니다.

Trap의 Activate 조건은 첫번째 Queue 길이가 요구치보다 크거나 같을 경우입니다.

따로 메모리를 두지는 않지만, 이 부분은 Semaphore를 따라가고 있습니다.

 

우선은 Character가 들락날락 하는 것에 대한 인식은 하고 있는 상태입니다.

내일은 그 뒤의 조건부를 제대로 수정하여 Multiplay 상에서 제대로 Character의 출입이 인식되도록 하고자 합니다.

그 뒤에 따로 구현 했던 기능들을 새 함수로 이전할 계획입니다.

 

하루면 될 줄 알았던 일이 하루 넘어가는 것으로 보아

Trap 부분만 어느정도 손봐도 목요일 쯤이 될 가능성이 높은 것 같습니다.

수요일 0시를 기준으로 그 전에 Trap 문제가 해결이 되면 Puzzle도 시도를 해보고,

그렇지 않다면 그 시점에서 내용을 정리해서 과제를 제출하고자 합니다.

 

과제 제출한 후에는 일주일~열흘 가량은 본 프로젝트는 일주일에 1, 2회만 하고

나머지는 전공책 읽기와 알고리즘 문제 풀기를 할 생각입니다.

이는 여태까지 하지 못했던 것을 보충하기 위함입니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.07 개발일지  (0) 2020.07.07
20.07.06 개발일지  (0) 2020.07.06
20.07.04 개발일지  (0) 2020.07.04
20.07.03 개발일지  (0) 2020.07.03
20.07.03 개발일지 2  (0) 2020.07.03

오늘은 길고 길었던 Climb 기능을 일단락 하게 되었습니다.

 

우선 어제 가장 문제가 되었던 Top Exit에 대해 3가지 해결법을 준비했습니다.

1. Top Exit 시 Teleport

2. Top Exit 시 모든 Collision을 제거

3. 이동키에서 손을 뗄 시 그 즉시 정지(관성도 없음)

 

이 중 3번을 함으로써 해결법이 가시권에 들어왔습니다.

해결법은 MaxFlySpeed와 BrakingDecelerationFlying였습니다.

MaxFlySpeed는 MOVE_Fly 상태에서의 최대 속도를, BrakingDecelerationFlying은 비 이동 시 가속도를 지칭합니다.

즉, MaxFlySpeed가 50이고 BrakingDecelerationFlying이 50이면 1초동안 감속운동을 하며 멈추게 되는 것입니다.

저는 BrakingDecelerationFlying을 MaxFlySpeed의 10배로 잡아 0.1초만에 바로 정지하도록 만들었습니다.

 

이렇게 하고 나자 비로서 원하던 것이 보였습니다.

Exit From Top의 Notify는 정상 작동을 하고 있었습니다.

심지어 Animation이 벽에 막혀 재생되지 않은 것이 아니었습니다.

앞이 막혀 있다면 뒤로 밀려서 재생이 되었습니다.

그 뒤는 Input을 제한하고, ExitClimb를 지정하면서 실질적인 움직임을 맞추는 것이었습니다.

 

하지만 결국 Climb Animation 이후 실질적으로 벽에 오르지 못하는 문제에 직면했고,

이 부분을 Teleport로 해결했습니다.

Collision으로 해결하지 않은 이유는 Animation이 벽에 막혔을 때 재생되지 않은 것이 아니라, 

뒤로 밀려서라도 재생이 되기 때문이었습니다.

어차피 Character 위치는 재조정을 해야 했기 때문에, 굳이 Collision을 건들지 않고 Teleport만 사용했습니다.

 

이전에는 Teleport를 할 때 Character가 붕 뜨는 것 같아서 이를 꺼려했습니다.

하지만 이는 처음 테스트 한 Rope의 경우였고, Ladder와 Wall에서는 그렇게까지 어색하게 보이지는 않았습니다.

이는 Rope의 Animation이 더 위쪽을 잡고 올라가는 형식이라 그런 것으로 판단됩니다.

때문에 현재 상황에서는 고칠 수 없는 문제라 판단하고 이슈에서 제거했습니다.

 

많은 문제들이 해결되었지만 아직 완벽한 것은 아닙니다.

Wall은 Enter/Exit From Bottom과 Climb Up/Down Animation이 없어서 임시로만 해놓은 상태입니다.

때문에 기능도 완벽하게 작동하지 않습니다.

 

또한 Teleport 할 때 Rotation이 정상적으로 적용되지 않습니다.

Rotation을 잘못 계산한 것인지는 잘 모르겠지만,

여러 방안을 시도 했음에도 Teleport 할 때 뒤를 돈 채로 이동하지 않고 있습니다.

때문에 Enter From Top도 모든 Climb에 대해 정상적으로 작동하지 않고 있습니다.

 

그럼에도 이 기능을 이쯤에서 멈춘 이유는 과제로 제출해야하기 때문입니다.

현재 구현된 기능 중 문제가 발생하는 기능들이 존재하기 때문에 이 부분을 먼저 구현하고자 합니다.

 

그래서 다음 진행중인 일은 Trap의 MultiPlay 상에서의 기능 작동입니다.

Trap 자체는 사실 Character가 들어와 있으면 기능이 작동하기만 합니다.

하지만 그 구조가 졸속이다 보니 MultiPlay에서 한 Character로 인해 발동된 Trap이

다른 Character의 InRange로 인해 해제가 되기도 합니다.

또한 이 방식은 Trap이 1명의 Character에게만 반응하게 되어있습니다.

 

이 문제들을 해결하기 위해 Character의 InRange를 Semaphore나 Queue로 구현을 하고자 합니다.

그리고 이에 따라 ATHActorBase에서 각자 따로 구현되었던 ATH-Trap들을

ATHTrapBase 하위 Actor들로 통합하려 합니다.

오늘은 생성을 하고, 기존의 Trap들에게 있는 공통적인 선언부분만 선언해둔 상태입니다.

 

우선은 공통 기능을 구현한 뒤 상속 관계를 수정하여 무사히 Build를 하는 것이 내일 첫 목표입니다.

그 다음에는 구현한 기능을 개선하고자 합니다.

하루만에 하기 힘들 수 있지만, 내일 개발이 끝나고 시간이 남는다면 BreakPuzzle을 먼저 수정해보려 합니다.

 

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.06 개발일지  (0) 2020.07.06
20.07.05 개발일지  (0) 2020.07.05
20.07.03 개발일지  (0) 2020.07.03
20.07.03 개발일지 2  (0) 2020.07.03
20.07.03 개발일지  (0) 2020.07.03

Notify가 호출되지 않은 이유는 이것을 받기 위해서는 Character가 아니라

AnimInstance에서 Delegate를 생성해야 하기 때문이었습니다.

 

AnimInstance에 Notify 이벤트를 생성하고 나서, 이벤트가 호출되는 것을 확인했습니다.

다만 Top에서는 발생하지 않았는데, 구조적 문제보다는 다른 원인 때문이라 생각합니다.

 

현재는 두가지 원인을 예측합니다.

1. 이전부터 Top Exit Animation은 정상재생 되지 않고 있었다.
벽이 있을 경우 막히기 때문에 끝까지 Animation이 재생되지 않아 Notify가 발생하지 않았다.

2. Exit 한 이후로 계속해서 Character가 움직이면서 Notify에 도달하지 못했다.

 

이를 위해 3가지 방안을 생각 중입니다.

1. Top Exit 시 Teleport를 한다.

2. Top Exit 시 Character의 모든 Collision을 없애서 벽을 통과 할 수 있도록 한다.

3. 이동 키에서 손을 뗼 경우 이동속도는 물론 관성까지 모두 0으로 처리하여 완벽히 멈추도록 한다.

 

이 중 3번은 무조건 적용이 되어야 할 사항입니다.

그렇지 않으면 이벤트가 중복으로 호출될 수 있기 때문입니다.

1번은 한번 시도했던 방안이지만, 실제로 적용하면 Character가 매우 붕 뜨기 때문에 어디까지나 차선책입니다.

결국 2번이 제대로 작동 되느냐에 따라 완성도가 달라질 것 같습니다.

 

우선 내일은 3번부터 적용을 하고, Notify 발생 여부를 확인해가며 1번과 2번 중 적절한 것을 먼저 시도할 예정입니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.05 개발일지  (0) 2020.07.05
20.07.04 개발일지  (0) 2020.07.04
20.07.03 개발일지 2  (0) 2020.07.03
20.07.03 개발일지  (0) 2020.07.03
20.07.02 개발일지  (0) 2020.07.02

새벽에 쓴게 사실 어제 써야 할 것이 12시가 넘어서 오늘 날짜로 적었습니다.

 

어제 Animation에 Notify를 받아서 Climb를 처리하는 것에 여러 문제를 남긴채로 개발을 멈췄습니다.

오늘은 이 중 Enter From Bottom, Move up, Move Down의 Animation이 정상적으로 작동되도록 하였습니다.

오랫동안 확인해본 결과 Idle 상태에서 Move 상태로 갔을 때

바로 Exit 조건까지 만족해버려서 Exit의 한 포즈로 고정이 되어버린 것이었습니다.

Exit 조건을 바꿨더니 문제를 해결할 수 있었습니다.

 

현재 Exit까지는 조건이 만족을 하지만,

Animation이 재생이 안된는지 Notify가 받아지지 않은지 이후 진행이 되지 않습니다.

그리고 Notify를 하면서 동시에 입력 금지와 이동속도, 관성 초기화를 하여 그 즉시 멈추도록 하고자 합니다.

'개발일지 > Treasure Hunter' 카테고리의 다른 글

20.07.04 개발일지  (0) 2020.07.04
20.07.03 개발일지  (0) 2020.07.03
20.07.03 개발일지  (0) 2020.07.03
20.07.02 개발일지  (0) 2020.07.02
20.07.01 개발일지  (0) 2020.07.01

+ Recent posts