리눅스에서 서버를 돌릴 경우 크래시 덤프를 뜨기가 힘들다.

이번에는 윈도우와 리눅스 둘 다 사용이 가능한 breakpad로 리눅스 덤프를 뜨는 방법을 알아보고자 한다.

 

리눅스는 ubuntu를 사용한다.

 


1. 필요한 라이브러리 인스톨

breakpad에서 필요한 라이브러리들을 미리 인스톨한다.

 

①GIT

 

 

② DEPOT TOOLS

break pad를 사용하기 위해 선행적으로 받아야한다.

 

사이트는 아래와 같다.

https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up

 

 

1) git을 이용해 depot_tools를 받아온다

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

 

 

2) PATH 설정을 한다.

export PATH=/path/to/depot_tools:$PATH

여기에서 ['path/to']는 나의 PATH를 입력한다.

 

 

 

③ make / g++

 

sudo apt install make
sudo apt install g++

 

c++ 빌드 환경을 만들기위해 make와 g++을 설치해준다.

 

 

④ zlib1g-dev

 

sudo apt install zlib1g-dev

 

zlib1g dev버전으로 설치해준다.

 

 


2. BREAK PAD 설치

break pad의 홈페이지는 아래와 같다.

https://chromium.googlesource.com/breakpad/breakpad/

 

breakpad/breakpad - Git at Google

Breakpad Breakpad is a set of client and server components which implement a crash-reporting system. Getting started (from main) First, download depot_tools and ensure that they’re in your PATH.Create a new directory for checking out the source code (it

chromium.googlesource.com

 

 

 

git clone https://chromium.googlesource.com/breakpad/breakpad

 

git으로 breakpad를 clone해온다.

 

 

 

 

[

[Myproject]에 breakpad 폴더를 만든 후 fetch 해준다.

 

-. 폴더 만들기

mkdir breakpad
cd breakpad

 

-. fetch

fetch breakpad

 

 

 

 

fetch가 완료되었으면

src폴더로 이동해,

configure과 make를 이용해 breakpad를 빌드해준다

 

cd src
./configure
make

 

 


 

3. BREAK PAD사용

 

 

내부에서 null에러를 일으키는 임시 코드를 작성했다.

 

 

① exception handler import

 

② dump callback 작성

홈페이지에 있는 예시 그대로 작성하였다.

 

 

#include <iostream>
#include <thread>
#include "client/linux/handler/exception_handler.h"

static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* context, bool succeeded) {
  printf("Dump path: %s\n", descriptor.path());
  return succeeded;
}


void ThreadFunction(int* ptr)
{
        std::cout<<*ptr<<std::endl;
}

int main()
{
          google_breakpad::MinidumpDescriptor descriptor("/tmp");
          google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);
        //null PTR을 cout : nullptr에러를 일으킨다
        int* ptr = nullptr;
        std::thread threadTest(ThreadFunction, ptr);

        //쓰레드 종료시까지 대기
        threadTest.join();
        return 0;
}

 

③빌드

g++ -I/home/ubuntu/MyProject/breakpad/src/src BreakPadTest.cpp -o test.out -lbreakpad_client

 


 

4. 덤프 확인

 

크래시가 나면 덤프는 PATH설정한 곳으로 나오게 된다.

예시의 경우 /tmp에 덤프가 생성된다.

 

① 덤프 심볼릭 만들기

 

breakpad/src/src/tools/linux/dump_syms/dump_syms ./test.out > test.out.sym

 

덤프 심볼릭을 만든다.

이때 심볼릭은 빌드파일과 같은 이름으로 해야한다.

 

 

② 심볼릭 고유 코드 확인

 

head -n1 test.out.sym

head -n1을 이용하여 심볼릭이 어디를 나타내는지 확인한다

 

③ 심볼릭의 헤더와 같은 위치로 폴더 만들기

 

심볼릭의 헤더가 가리키는 위치에 폴더를 만든다.

그렇게 하지않으면 덤프에서 심볼릭을 찾을 수 없다.

mkdir -p ./symbols/test.out/C742B6BB5BEBFBC5F73889A0908E34610
mv test.out.sym ./symbols/test.out/C742B6BB5BEBFBC5F73889A0908E34610/

 

④ 크래시가 난 위치 확인

 

마지막으로,

breakpad/src/src/processor/minidump_stackwalk 68d64630-fceb-4e30-ba3ee3bc-e3aacc30.dmp ./symbols

 

를 이용하면 아래와 같은 결과가 나온다.

 

0 test.out의 ThreadFunction의 14번째 줄에서 크래시가 난 것을 알 수 있다.

 

 

 

정확히 크래시가 난 곳의 위치 확인이 가능하다.

 

 


윈도우에서는 visual studio에 덤프를 넣기만 해도 디버깅이 가능한 것으로 알고있다.

리눅스에서 뽑은 덤프도 visual studio에서 가능한지는 확인해볼 필요가 있어보인다.

2022.12.04 네이버 블로그에 업로드했던 글을 이전한 게시글입니다.

 

 

 

 

Unity로 MVC, MV(R)P, MVVM패턴을 구현해보려고한다.

MVC, MVP, MVVM에대한 설명은 많았지만 유니티로 구현한 설명은 적은것같아 공부겸 정리해보려고한다.

 

 

간단하게

체력 100인 캐릭터가 존재하며

Attack을 누르면 체력이 10씩 깎이며

Heal을 누르면 5씩 늘어나는 기능을 만들어보려고 한다.

 


[VIEW와 MODEL]

각 패턴의 공통인 View와 Model부터 작성한다

●Model

사용되는 데이터의 모임이다.

데이터와 데이터를 처리하는 부분을 Model 이라고 한다.

 

우선 HP가 필요하므로 Model에 HP를 작성한다.

public class Model
{
    private int _hp;
    public int HP { get=>_hp; set=>_hp = value; }
}

 

 

●VIEW

사용자에게 보여지는 UI부분이다.

현재 상태로는 버튼과 HP를 표현하는 텍스트가 있다.

변하는값은 HP를 표현하는 텍스트이므로 텍스트만 우선 작성한다

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;
}

 

 

 

 


[ MVC 패턴 ]

MVC패턴은 Model, View, Controller이다.

Model과 View가 연결되어있고, Controller에서 입력을 담당한다.

현재의 기능으로 설명하면,

  1. 버튼을 누르는 Action이 Controller로 들어온다.
  2. Controller에서 Model에게 HP값 변경을 요청한다.
  3. Model에서는 HP를 변경하고 이 값을 View에서 표시한다

●Controller

 

 

Controller에서는 버튼이 눌렸는지 확인만 담당한다.

 

 

using UnityEngine;
using UnityEngine.UI;

public class Controller : MonoBehaviour
{
    [SerializeField]
    private Button _attactButton;
    [SerializeField]
    private Button _healButton;

    [SerializeField]
    private Model _model;
    
    private void Start()
    {
        //Attack버튼이 눌리면 Model의 Attack을 호출한다
        _attactButton.onClick.AddListener(() =>
        {
            _model.Attack();
        });

        //Heal버튼이 눌리면 Model의 Heal을 호출한다
        _healButton.onClick.AddListener(() =>
        {
            _model.Heal();
        });
    }
}

 

 

●View

 

 

View에서는 받은 값을 사용자가 보는 화면에 표시만 한다.

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;

    public void ShowHPTxt(int hpValue)
    {
        _hpTxt.text = hpValue.ToString();
    }
}

 

●Model

Model에서 실제 데이터 처리와 View와의 연동을 담당한다.

using UnityEngine;

public class Model : MonoBehaviour
{
    private int _hp = 100;

    [SerializeField]
    private View _view;

    /// <summary>
    /// Attack버튼이 눌렸을 때
    /// hp - 10
    /// View에 표시요청
    /// </summary>
    public void Attack()
    {
        _hp -= 10;
        _view.ShowHPTxt(_hp);
    }

    /// <summary>
    /// Heal버튼이 눌렸을 때
    /// hp + 5
    /// View에 표시요청
    /// </summary>
    public void Heal()
    {
        _hp += 5;
        _view.ShowHPTxt(_hp);
    }
}

 


 

[ MVP 패턴 ]

MVP(MV(R)P)패턴은 Model, View, Presenter이다.

Model에서 데이터, View에서 화면을 담당하고 중간에 중개자 역할을 하는 Presenter가 존재한다.

 

 

 

현재의 기능으로 설명하면,

  1. 버튼을 누르는 Action이 View로 들어온다.
  2. View에서 Presenter에게 HP값 변경을 요청한다.
  3. Presenter는 Model에게 정보를 요청하고 받아온 정보를 View로 재송신한다

●View

이제 View에서 버튼 액션을 확인한다.

 

 

 

View의 버튼이 눌리면 Presenter에 값 변경을 요청한다.

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;
    [SerializeField]
    private Button _attactButton;
    [SerializeField]
    private Button _healButton;
    [SerializeField]
    private Presenter _presenter;
    private void Start()
    {
        //Attack버튼이 눌리면 Model의 Attack을 호출한다
        _attactButton.onClick.AddListener(() =>
        {
            _presenter.Attack();
        });

        //Heal버튼이 눌리면 Model의 Heal을 호출한다
        _healButton.onClick.AddListener(() =>
        {
            _presenter.Heal();
        });
    }

    public void ShowHPTxt(int hpValue)
    {
        _hpTxt.text = hpValue.ToString();
    }
}

 

●Presenter

 

Presenter에서는 Model의 값을 가지고있고,

View에서 요청한 값을 Model에서 받아와

다시 View 표시한다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Presenter : MonoBehaviour
{
    private Model _model = new Model();
    [SerializeField]
    private View _view;

    public void Attack()
    {
        _view.ShowHPTxt(_model.Attack());
    }

    public void Heal()
    {
        _view.ShowHPTxt(_model.Heal());
    }
}

 

 

●Model

 

Model은 데이터 처리만을 담당한다.

public class Model
{
    private int _hp = 100;

    /// <summary>
    /// Attack버튼이 눌렸을 때
    /// hp - 10
    /// View에 표시요청
    /// </summary>
    public int Attack()
    {
        return _hp -= 10;
    }

    /// <summary>
    /// Heal버튼이 눌렸을 때
    /// hp + 5
    /// View에 표시요청
    /// </summary>
    public int Heal()
    {
        return _hp += 5;
    }
}

 

MVP방식의 장점은 View와 Model의 의존성이 줄어든 것이지만

반대로 View와 Presenter와의 의존성이 높다.

 

 

 


 

[ MVVM 패턴 ]

MVVM패턴은 Model, View, View Model이다.

Model에서 데이터, View에서 화면을 담당하고

Model의 데이터를 View에 맞게 파싱해주는 ViewModel이 존재한다.

 

View에 맞게 파싱해주는 역할이므로 View의 갯수만큼 ViewModel이 늘어난다.

 

 

현재의 기능으로 설명하면,

  1. 값을 받아오는 것 까지는 MVP패턴과 비슷하다.
  2. Presenter의 중재자역할 대신 ViewModel에서는 Model에서 받아온 값을 View에 맞게 파싱한다.

●ViewModel

 

이번엔 ViewModel에서 View용 데이터를 가지고있고,

Model에서 받아온 데이터를 View용으로 파싱한 후 이 값을 View에서 표시한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ViewModel : MonoBehaviour
{
    [SerializeField]
    private View _view;
    [SerializeField]
    private Model _model;

    private string _hpStr = string.Empty;
    public void Attack()
    {
        _hpStr = _model.Attack().ToString();
        _view.ShowHPTxt(_hpStr);
    }

    public void Heal()
    {
        _hpStr = _model.Heal().ToString();
        _view.ShowHPTxt(_hpStr);
    }
}

 

●Model

 

using UnityEngine;

public class Model : MonoBehaviour
{
    private int _hp = 100;

    /// <summary>
    /// Attack버튼이 눌렸을 때
    /// hp - 10
    /// View에 표시요청
    /// </summary>
    public int Attack()
    {
        return _hp -= 10;
    }

    /// <summary>
    /// Heal버튼이 눌렸을 때
    /// hp + 5
    /// View에 표시요청
    /// </summary>
    public int Heal()
    {
        return _hp += 5;
    }
}

 

●View

 

 

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour
{
    [SerializeField]
    private Text _hpTxt;
    [SerializeField]
    private Button _attactButton;
    [SerializeField]
    private Button _healButton;
    private ViewModel _viewModel = new();
    private void Start()
    {
        //Attack버튼이 눌리면 Model의 Attack을 호출한다
        _attactButton.onClick.AddListener(() =>
        {
            _viewModel.Attack();
        });

        //Heal버튼이 눌리면 Model의 Heal을 호출한다
        _healButton.onClick.AddListener(() =>
        {
            _viewModel.Heal();
        });
    }

    public void ShowHPTxt(string hpValue)
    {
        _hpTxt.text = hpValue;
    }
}

 

 

Unity에서는 MVVM패턴이 잘맞지않는다는 의견이 있었다.

웹에 잘 맞는 패턴

디자인패턴은 개인의 자유이며 프로젝트의 요구사항에 따라 편한 패턴을 선택해서 사용하는것이 좋을 것 같다

2022.04.11 네이버 블로그에 올린 글을 이전한 게시글입니다.

 

 

UNITY로 칼리굴라 이펙트2 전투씬에 나오는 배경투명화 영상을 제작해보았다

 

 

우선 결과물.

 

 

 

칼리굴라의 느낌으로 카메라도 이동시켜 보았다.

 

 

영상원본은 망상감상대상연맹이다

이유는 알파추출이 쉬워보여서:)

 

https://youtu.be/8pGRdRhjX3o

 


1. Davinci Resolve로 배경투명 영상 만들기

 

유니티 공식홈페이지의 Videoplayer 설명을 보면

webm파일포멧과 VP8비디오 코덱이 있으면 비디오에 알파적용이 가능하다는 설명이 있다

https://docs.unity3d.com/kr/2020.3/Manual/VideoTransparency.html

 

우선 다빈치 리졸브를 이용하여 알파를 뺀다.

 

 

[다빈치 리졸브로 영상 알파 빼기]

하단의 [Color]탭에 이동한 후,

노드부분에 마우스 오른쪽 클릭 -> [Add Alpha Output]을 클릭한다.

[Add Alpha Output]을 클릭하면 파란색 노드가 추가된다

 

 

스포이드툴을 선택한 후 알파를 뺄 곳에(투명화를 할 곳에) 클릭한다.

 

선택한 부분의 알파를 뺄것이므로 반전을 눌러

선택한 부분의 알파값을 빼준다.

만약 크로마키 영상이 필요하다면 크로마키도 이와 같은 방법으로 진행한다.

렌더세팅

알파값을 함께 빼야하므로 [Export Alpha]를 체크해준다

[FFmpeg를 이용하여 포멧설정]

 

webm 포멧 코덱을 위해서는 FFmpeg를 사용해야한다

https://ffmpeg.org/download.html#build-windows

 

 

[설치폴더/bin]위치에 알파값을 뺀 영상을 넣는다

 

​[FramesToWebm.bat] 파일을 생성하여 실행시킨다

ffmpeg -i AlphaTest_Audio.mov -vcodec libvpx -auto-alt-ref 0 -codec:a libvorbis OutputAudio.webm

pause

 

-i AlphaTest_Audio.mov : 출력파일 이름

-vcodec libvpx : 사용코덱

-codec:a libvorbis OutputAudio.webm : 입력파일이름

[유니티에서 확인]

영상의 알파가 제대로 빠졌는지 확인한다

 

[Assets] - [Import New Asset]을 이용하여 만들어진 영상을 임포트한다

VideoPlayerPlayer로 플레이해보면 알파값이 잘 빠진것을 확인할 수 있다.

 


2. 굽어진(커브드) 캔버스 만들기

칼리굴라에선 둥글게 기울어진 캔버스를 사용하므로 기울어진 캔버스를 만들어보도록한다.

캔버스를 기울일 방법이 없으므로 다른 모델링을 이용하여 그 위에 매쉬랜더링을 하는 방법을 이용한다.

[Unity ProBuilder를 이용하여 커브드 캔버스 모델링 만들기]

 

[Package Manager]를 사용해 ProBuilder를 임포트해준다.

 

 

임포트에 성공했다면 [Tool]-[ProBuilder Window]로 프로빌더 윈도우를 활성화시킬 수 있다.

Unity ProBuilder는 유니티상에서 간단한 모델링이 가능하도록 지원해주는 기능이다

 

[New Shape]를 이용해 원뿔을 만들어준다

SideCount는 둥글게 보이도록 14로 설정했다

 

면 선택버튼을 누른 후 안쪽면을 제외한 바깥쪽 면들을 선택 -> [Delete Faces]를 클릭하여 내부면만 남겨둔다

 

 

 

 

내부의 면들만 남은 모습

 

 

 

 

UV에디터를 이용하여 UV를 정리해준다

 

 

 

 

처음 UV에디터를 켜면 UV가 정리되지않은 모습을 볼 수 있다

이를 정리해준다

[영상플레이용 머테리얼 생성하기]

 

 

 

[Create]-[Material]을 눌러 새로운 머테리얼을 추가한다

 

 

투명화를 지원해야하므로 Redering Mode를 [Transparent]로 설정해준다

 

 

 

 

VideoPlayer에 연결한다

 

 

결과물

영상의 알파값이 잘 빠진 모습이다

+ Recent posts