묻고 답해요
158만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
랜덤박스에 waepon이 생기지 않습니다
Weapon이 primaryasset으로 안들어가서 그런가 싶어서 weapon의 데이터를 봤는데Primary Asset Type은 ABItemData(비쥬얼스튜디오에서는 복사붙여넣기로 넣은거라 이름이 다를 리는 없을 거같습니다.)로 들어가있었습니다. 근데 박스가 생성될 때 assets의 num을 찍어보니 3이 아닌 2가 나오는거 보니 인식이 안되는 거 같은데 엔진의 문제일 수도 있나요?
-
미해결[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버
Stack Frame 구조 질문 (section2 스택메모리와 스택프레임 10분~12분경)
강의에서 설명된 내용 기준으로 argument 10 및 return address가 main함수의 스택 프레임에 있는 것으로 설명되었는데, 실제 코드에서 main함수에서 Test함수를 argument 10을 주면서 호출할 시에 매개변수 10에 대한 값과 추후에 다시 main 함수로 돌아오게 될 위치에 대한 리턴 어드레스 값은 메인 스택 프레임이 아닌 그 아래에 위치할 Test함수의 스택 프레임에 있는 것이 더 정확하지 않나에 대한 질문드립니다.
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
2강 - 입력 매핑 컨텍스트 오류가 발생했습니다.
BeginPlay 함수를 오버라이딩 하실 때 void AABCharacterPlayer::BeginPlay(){Super::BeginPlay();APlayerController* PlayerController = CastChecked<APlayerController>(GetController());if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController)){Subsystem->AddMappingContext(DefaultMappingContext, 0);// Subsystem->RemoveMappingContext(DefaultMappingContext);}}와 같이 정의하셨는데, ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController) 이 함수에서 인수가 일치하지 않는다는 오류가 발생합니다. 선생님 코드를 보면 동일한 코드임에도 실행이 잘 되던데, 저는 이 부분 때문에 빌드가 안되고 있습니다. 인수가 ULocalPlayer가 들어와야 한다고 해서, APlayerController이 아닌 ULocalPlayer로 캐스팅도 해봤는데, 런타임에서 바로 터집니다. 혹시 어느 부분이 문제일까요?모듈에는 EnhancedInput 추가했고, 로그에 해당 오류 말고 다른 오류가 발생하고 있지는 않습니다.
-
해결됨이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
Unreal 애니메이션이 기본적으로 MultiThread 옵션이 켜져있는 점에 대해서.
아마 성능을 위해 애니메이션 블루프린트 로직이 작업자 스레드에서 돌아가도록 옵션 켜는게 있는 것 같은데요. 많은 다른 예제에서 블루프린트 EventGraph 대신 Blueprint Thread Safe Update Animation 이라는 블루프린트 함수를 대신 사용하고 또, C++ 로도 NativeUpdateAnimation() 대신 NativeThreadSafeUpdateAnimation() 가 있더라구요. 그리고 블루프린트 전용 함수에서도 ThreadSafe 옵션을 켜고 끄는게 있는데 이걸 켜면 일반적인 C++ 함수를 호출할 수 없고, C++ 함수에 Meta = (BlueprintThreadSafe) 지정자를 설정하면 보이긴 하는데요. 여기서 NativeThreadSafeUpdateAnimation() 함수나 Meta = (BlueprintThreadSafe) 지정자를 붙인 C++ 함수에는동기화 기법( mutex 같은)을 사용해서 정말 내부적으로도 멀티스레드 프로그래밍 같이 코드를 짜야 하는건가요???
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
21 : 41 OnGameClear OnGameOver 이벤트 노드
앞서 만든 코드에서는 OnGameClearCpp, OnGameOverCpp 이름으로 나오도록 했는데 미리 만드신것에선 이름을 다르게 지으신건가요?OnGameClear, OnGameOver이름이 다르길래 질문드립니다. +수정강의 뒤에 내용을 듣다보니 OnGameClearCpp, OnGameOverCpp 도 가져와 연결시켜주네요..미리만들어진것말고 제가 직접 만들어보고 있는데 저노드가 안보이는데 어떻게 추가를하면 될까요?
-
미해결[입문자를 위한 UE5] Part2. 언리얼 엔진 2D 게임 개발 입문
에러메세지 뜨면서 막히는데 뭐가 잘못된건지 잘모르겠어요
플레이하면 정상작동되고 몬스터를 한대라도치면 HP가 안달고 esc로 종료하면 해당 메시지가 뜹니다.이 메세지는 왜 뜨는 건가요 ~?
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
1강 Default Pawn Class가 바로 변경되지 않는 이유
안녕하세요1강 23:03 에서 강의 영상에서는 Ctrl+Alt+F11을 눌러 에디터 빌드를 완료를 하면 Default Pawn Class가 바로 ThridPersonCharacter로 변경이 되는데, 제 컴퓨터에서는 바로 변경이 되지 않습니다. cpp의 생성자 부분만 변경했음에도, 에디터를 끈 후 비주얼스튜디오에서 빌드를 한 후 다시 에디터를 실행해야 변경된 것이 확인되는데 왜 그럴까요? 제가 놓친 설정이나 빌드 방법이 있는지 궁금합니다.
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
22:53분에서 나오는 FClassFinder 함수 질문입니다.
게임모드에 언리얼에서 제공하는 3인칭 템플릿 캐릭터 에셋을 디폴트 폰 클래스로 지정할 때 ConstructorHelpers::FClassFinder 함수에 템플릿으로 APawn을 지정해주셨는데 캐릭터는 폰을 상속받은 클래스인데 ACharacter로 지정하면 안되는 이유가 있나요? 해보니깐 컴파일 오류가 나던데요ACharacter로 클래스를 찾아야 오히려 더 명확하게 찾는게 아닌가 싶어서 질문드립니다.
-
미해결[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버
온라인 환경에서 Arrow, 제거와 발사 시 동기화 문제
안녕하세요 Rookis님.강의를 모두 완강하고 포트폴리오를 개선하고 있는 중입니다.강의 중에 화살을 온라인에 추가할 것이라면 Creature와 GameObject 내용을 수정해야 한다고 하셔서 코드 이사는 완료한 상태입니다.지금 Arrow는 MyPlayer에서 입력을 받고 State와 WeaponType을 체크하면 Player에서 Scene에 Arrow를 스폰해주는 방식으로 알고 있습니다.이걸 서버에서는 몬스터나 플레이어를 만드는 GameObject::Create 함수를 파줘서 Arrow를 make_shared로 만들어서 발사 처리를 하게 만들었는데요서버에서 몬스터가 제거되면 클라이언트에서도 정상적으로 몬스터가 제거되는걸 확인은 했습니다.그러나 문제가 몇 가지 있습니다.Arrow 스마트 포인터가 해제되지 않는 현상Arrow 동기화가 종종 씹히는 현상입니다. 먼저 1번입니다.make_shared로 생성된 Arrow가 해제되지 않음void Player::UpdateSkill() { if (room == nullptr) return; if (info.weapontype() == Protocol::WEAPON_TYPE_SWORD) { // 내 앞에 있는 좌표 CreatureRef creature = room->GetCreatureAt(GetFrontCellPos()); if (creature) { if (creature->GetType() == Protocol::OBJECT_TYPE_PLAYER) { SetState(IDLE); return; } // 몬스터가 플레이어에게 피격 creature->OnDamaged(shared_from_this()); } } else if (info.weapontype() == Protocol::WEAPON_TYPE_BOW) { ArrowRef arrow = CreateArrow(); arrow->SetDir(GetLookAtDir(GetFrontCellPos())); arrow->SetOwner(shared_from_this()); arrow->room = room; arrow->info.set_posx(info.posx()); arrow->info.set_posy(info.posy()); arrow->SetState(IDLE, true); room->AddObject(arrow); } SetState(IDLE); }서버쪽의 UpdateSkill 함수인데 여기에서 arrow를 CreateArrow로 만들어서 room에 AddObject로 _arrows map을 만들어 관리를 하고 있습니다. (사실 룸에서 발사체를 관리하는 것이 옳은지도 의문이긴 합니다)void GameRoom::Update() { for (auto& item : _players) { item.second->Update(); } for (auto& item : _monsters) { item.second->Update(); } for (auto& item : _arrows) { item.second->Tick(); } }그리고 Update 함수, AddObject, RemoveObject도 _arrows map을 처리하게 만들었습니다.이렇게 처리하다 보니 화살을 제거할 때 몬스터가 피격받는 순간에 해당 화살을 RemoveObject를 실행하니 삭제 이후에 for문을 돌 때 오류가 발생하며 크래시가 발생했습니다.Arrow가 _arrows 맵에서 관리되어서 스마트 포인터가 해제가 안되는 것 같은데, 화살을 어떤 때에서 제거해야 될지 모르겠습니다.지금은 임시적으로 vector에 참조로 받아와서 Update 하단에서 erase하는 방법을 사용하고 있습니다. 화살 동기화 문제 클라이언트에서는 Projectile 클래스에서 _owner에 대한 정보를 들고 있고 Arrow를 Scene에서 소환할 때 GetOwner 함수로 화살의 주인에 대한 포인터를 들고 있도록 했습니다.기존에 발사할 때도 S_Move 패킷을 그대로 이용해서 Arrow의 _owner 포인터를 이용해서 위치를 초기화해주고 있습니다.그런데 두 클라이언트를 접속시켜서 2를 눌러 WeaponType을 Bow로 바꿔서 공격 키로 테스트해보면 종종 반대쪽 플레이어의 화살이 안보이는 경우가 있습니다.여기에 몇 개의 질문이 있는데요1) 화살을 생성하고 클라이언트에서 패킷을 전송하는 것이 맞는지2) 맞다면 어떤 정보를 패킷에 담아야 하는지3) 서버에서는 어떤 처리를 해주어야 하는지잘 모르겠습니다.일단은 Make, Handle 함수를 파서 ObjectInfo를 넣어놓긴 했습니다.하루 종일 코드를 조작해봐도 해결을 못하고 있습니다.. 도와주세요..
-
미해결[입문자를 위한 UE5] Part2. 언리얼 엔진 2D 게임 개발 입문
언리얼엔진 MMORPG 2D
언리얼엔진으로 만든 MMORPG 2D는 뭐가 있나요?
-
해결됨[입문자를 위한 UE5] Part3. 언리얼 엔진 3D 게임 개발 입문
git push 오류, C++ 연동 관련
강의를 다 보고 개인 포트폴리오를 준비하고 있는데 프로젝트의 파일 크기가 너무 커서 git에 push 가 안되고 있습니다. 에러코드는 이렇습니다. error: RPC failed; HTTP 500 curl 22 The requested URL returned error: 500해결방법으로 git config --global https.version HTTP/1.1git config --global http.postBuffer 157286400명령어로 HTTP 버전변경이나 버퍼 크기를 늘려보라는 답이 나와서 해봤는데 다 안먹히더라구요 그러면 그냥 push할 파일의 크기가 커서 그렇다고하는데 이럴때 어떻게 버전관리를 하시나요? 그냥 로컬에서만 하는것으로는 나중에 포트폴리오 제출할때 불편할것 같아요 두번째 궁금한것은 언리얼엔진과 C++의 연동입니다. 파트.4 가 그에 관한 내용이라고 들었는데 아직 안나왔더라구요 그래서 이전에 언리얼엔진4 버전 강의가 있던데 그것을 기반으로 언리얼엔진5 에도 적용해도 될까요?
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
블루프린트(에디터)에서 지정한 ComboActionData가 null이 되는이유
안녕하세요AI시스템 구현도중 ComboActionData를 불러올수 없는 문제가 생겨서 질문 드립니다.우선 이것저것 바꿔서 실습 해보는 중이라 강의 코드랑 다른부분이 있을순 있습니다만 베이스는 강의코드입니다...void ATLStageGimmick::OnOpponentSpawn() { const FTransform SpawnTransform(GetActorLocation() + FVector::UpVector * 88.0f); ATLCharacterNonPlayer* OpponentCharacter = GetWorld()->SpawnActorDeferred<ATLCharacterNonPlayer>(OpponentClass, SpawnTransform); if (OpponentCharacter) { OpponentCharacter->OnDestroyed.AddDynamic(this, &ATLStageGimmick::OnOpponentDestroyed); OpponentCharacter->SetLevel(CurrentStageNum); OpponentCharacter->FinishSpawning(SpawnTransform); } }우선 기믹 코드쪽에서 이렇게 스폰을 해주는데요,(예제랑 같습니다) CharacterNonPlayer를 상속받아 BP_EliteBoss라는 이름으로 블루프린트를 만든뒤 기믹 엑터에 이렇게 설정을 해줬습니다. 그리고 BP_EliteBoss안에 필요한 몽타주와 ComboActionData를 설정해줬는데요 그래서 게임을 실행해보면 정상적으로 스폰도 되고 이동도 합니다. 그런데 정작 공격을 진행하면 ComboActionData가 없다는것 아니겠습니까..? 저는 분명 블루프린트에서 ComboActionData를 넣었는데 말이죠.. 혹시 SpawnActorDeferred하게되면 에디터에서 지정한 에셋들은 사용할 수 없는건가요??? 해결방법을 찾다 안돼서 질문 드립니다...
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
GetAuthGameMode를 통해 IABGameInterface를 캐스팅하려는 문제
현재 ABStageGimmick.cpp에서 빌드 에러가 납니다.void AABStageGimmick::OnOpponentDestroyed(AActor* DestroyedActor) { IABGameInterface* ABGameMode = Cast<IABGameInterface>(GetWorld()->GetAuthGameMode()); // 에러 SetState(EStageState::REWARD);; } 에러 내용은 아래와 같습니다.1>C:\Program Files\Epic Games\UE_5.3\Engine\Source\Runtime\CoreUObject\Public\Templates\Casts.h(85): error C2027: use of undefined type 'AGameModeBase'1>C:\Program Files\Epic Games\UE_5.3\Engine\Source\Runtime\Engine\Classes\Engine\GameInstance.h(29): note: see declaration of 'AGameModeBase'1>C:\UnrealProject\UE5_GameFrameWork\ArenaBattle\Source\ArenaBattle\Gimmick\ABStageGimmick.cpp(288): note: see reference to function template instantiation 'To Cast<IABGameInterface,AGameModeBase>(From )' being compiled1> with1> [1> To=IABGameInterface,1> From=AGameModeBase1> ] 현재 리서치해본 결과 ABGameMode가 어떤 클래스인지 파악 못해서 GameModeBase.h파일을 추가해줘야 한다고 합니다.아니면 UObject로 형변환 한 뒤에 캐스팅해오라고 되어있습니다. void AABStageGimmick::OnOpponentDestroyed(AActor* DestroyedActor) { IABGameInterface* ABGameMode = Cast<IABGameInterface>((UObject *)(GetWorld()->GetAuthGameMode())); if (ABGameMode) { ABGameMode->OnPlayerScoreChanged(CurrentStageNum); if (ABGameMode->IsGameCleared()) { return; } } SetState(EStageState::REWARD);; } 그래서 이렇게 수정하니 해결이 되었는데 혹시 왜 저는 강사님처럼 코드를 작성하면 되지 않는지 아직 이해가 가지 않습니다.알려주시면 감사하겠습니다!
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
FSoftObjectPtr과 TSoftObjectPtr차이점
9강 44분쯤 약참조를 위해 FSoftObjectPtr를 쓰시는데 이전에는 TSoftObjectPtr를 쓰셧던거같아, 구글에 검색해보니 TSoftObjectPtr는 FSoftObjectPtr를 UObject로 랩핑한 ptr이라고 하는데요, 그런데 굳이 이걸 명시적으로 나누어진이유가 있을것이고 교수님께서 사용하신 의도가 있는거같아서 궁금해서 여쭈어봅니다 해당부분에서는 FSoftObjectPtr 대신 TSoftObjectPtr를 사용해도 같은 결과를 내긴했습니다. 교수님께서는 그냥 예시를 위해 사용하신건지 아니면 특별한 이유가 있는건지 궁금합니다.
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
9강 20분쯤에 딜리게이트래퍼 질문있습니다.
StateChangeAction.Add(EStageState::READY, FStageChangedDelegateWrapper(FOnStageChangedDelegate::CreateUObject(this, &AABStageGimmick::SetReady)));이부분을 구조체를 선언해서 사용하는 이유가 궁금합니다. StateChangeAction.Add(EStageState::READY, FOnStageChangedDelegate::CreateUObject(this, &AABStageGimmick::SetReady)); 이런식으로 Value를 딜리게이트 자체를 넘겨줄수있는데,굳이 저렇게 구조체를 만드는 이유가 뭔가해서요, 예측하건데 파라미터도 동시에 넣어줄수있도록 하기위함인가요 아니면 따른 이유가 있는건가요 ?
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
점프 공격 시 캡슐 위치 질문입니다.
루트 모션 관련해서 알아보다가 실습 마지막 콤보 모션이 생각나서 확인해보니, 점프했다가 찍는데 캡슐 콜리젼 위치는 변하지 않는 것을 확인했습니다. 애니메이션 시퀀스에서 루트모션을 활성화 시키고 해봐도 더 이상해지는 듯하여 질문드렸습니다...캡슐 콜리전이 애니메이션을 따라가게 하려면, 시퀀스 에셋에서 루트모션 활성화하는 것과 애니메이션 블루프린트에서 루트 모션 모드를 활성화하는 것 말고 다른게 있을까요???
-
미해결[입문자를 위한 UE5] Part1. 언리얼 엔진 블루프린트
섹션2 흐름제어 연습문제: Min,Max,Clamp 부분 질문
여기서 처음에 연습문제로Hp를 100으로 두고 MaxHp를 150으로 두었을때1번 키 입력시 데미지 10을 입게하고2번 키 입력시 체력 20을 회복하게 하는 기능을 만드는 연습문제였는데 제가 좀 더 추가해서현재 체력을 확인하는 기능이나0이하로 떨어졌을시 데미지도 더이상 입을수없고 회복도 불가능하게 하거나최대체력이면 최대체력이라서 회복이 불가능하다라는 문구가 나온다거나하는식의 몇가지 응용아닌 응용해서 좀 더 살을 붙여서 풀고있었는데 의문이 드는 버그? 같은게 있어서이게 어째서 일어나는가 싶어서 질문을 드립니다 [현재 HP 확인 노드]키보드 3을 누를 시 HP를 카운트하여 알려준다. [데미지 받는 노드]키보드 1을 누를 시 HP가 0보다 작을 경우 당신은 죽었습니다 라는 문구가 나온다.키보드 1을 누를 시 HP에서 데미지를 마이너스한 HP를 카운트하여 알려준다. [체력회복하는 노드1]키보드 2를 누를시 HP가 0보다 작을 경우 이미 사망하여 회복할 수 없습니다 라는 문구가 나온다.키보드 2를 누를시 HP가 0보다 크고 HP가 MaxHP보다 크거나 같을경우 이미 최대 체력입니다 라는 문구가 나온다.키보드 2를 누를시 HP가 0보다 크고 HP가 MaxHP보다 작은데 HP에 Heal(20)이 되는 수치만큼 더한 HP가 MaxHP보다 작을 경우 회복된 이후의 HP를 카운트하여 알려준다. [체력회복하는 노드2]키보드 2를 누를시 HP가 0보다 크고 HP가 MaxHP보다 작은데 HP에 Heal(20)이 되는 수치만큼 더한 HP가 MaxHP보다 클 경우 HP를 MaxHP로 세팅하고 최대 체력으로 회복하였습니다라는 문구와 함께 최대HP를 카운트하여 알려준다. 여기서체력확인이랑 데미지는 문제없었는데체력을 회복할 때다른곳에서는 문제가 전혀없었는데체력이 120일때 회복을 하면 현재체력 120+ 체력회복 20으로 체력이 140이 되어야하는데140을 건너뛰고 150으로 가더라구요...데미지 입을때는 140 130 120 110 100 90 80 쭉쭉 건너뛰지않고 잘 내려가고회복할때도 40일때 회복하면 60, 60일때 회복하면 80, 100 120 잘 가다가120일때만 30이 회복되는게 왜그런가 궁금합니다!
-
미해결[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버
disassembly 창
dissasembly 창을 띄우고 싶은데, 이처럼 설정을 해줘도 창이 띄워지지 않습니다. 이런 경우, 어떻게 해야 하는지 문의드립니다.
-
미해결[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버
RemoveItem 함수에서 아이템 포인터를 nullptr로 바꾸기 전에 delete를 하지 않는 이유가 있나요?
강의에 나온 예제 에서는 Clear 함수로 모든 아이템을 delete하는데 이때 RemoveItem 함수에서 이미 nullptr로 지정된 아이템은 따로 delete 연산을 하지 않아서 Clear 이후에 배열의 포인터는 nullptr인데 힙 메모리에는 데이터가 남는 게 아닌가 싶어서 질문 드립니다.실제로 RemoveItem을 실행하는 아니템들을 따로 배열에 모아 Clear 함수 이후에 데이터를 확인해 보니 아이템들이 존제하는 것을 확인 했습니다.bool Inventory::RemoveItem(Item* _item){ if (_item == nullptr) return false; int slot = FindItemSlot(_item); if (slot < 0) return false; //delete mItem[slot]; // 제거되는 아이템 모음 mRemove[mRemoveIndex] = mItem[slot]; mRemoveIndex++; mItem[slot] = nullptr; mItemCount--; return true;}위에 mRemove에 아이템을 모아 Clear 이후에 중단점을 걸어 데이터를 확인해 보니 아이템의 데이터가 남아있는 것을 확인했습니다.혹시 의도적의로 delete연산을 하지 않은 것 인지 궁금하여 질문 드립니다.
-
미해결이득우의 언리얼 프로그래밍 Part2 - 언리얼 게임 프레임웍의 이해
16:29 uint8*을 FABCharacterStat*로 다시 형변환 하는이유
항상 친절한 답변 감사합니다. 왜 DataTable의 Value는 uint8*를 쓰게 됐을까가 궁금합니다. TArray<uint8*> ValueArray; DataTable->GetRowMap().GenerateValueArray(ValueArray);GenerateValueArray함수로 데이터 테이블의 모든 벨류를 복사 할때 uint8*형식으로 복사를 진행한후 다시 FABCharacterStat*으로 형변환 하는데요 템플릿으로 FABCharacterStat을 받으면 형변환하지 않고 편하게 사용할 수 있을거 같은데 말이죠.. GPT의 답변인데 이게 맞을까요?DataTable의 각 셀에 저장되는 값은 FString이 아니라 uint8* (unsigned 8-bit integer pointer)로 저장될 때가 있습니다. 이는 다양한 데이터 형식을 다루기 위한 유연성을 제공합니다. uint8*는 메모리의 원시 데이터를 가리키는 포인터로, 이를 사용하여 다양한 데이터 형식을 저장할 수 있습니다. 예를 들어, DataTable에서는 문자열, 숫자, 구조체 등 다양한 데이터를 저장할 수 있습니다. uint8*는 이러한 데이터 형식을 표현하는 데 사용됩니다. 그리고 데이터를 사용할 때는 필요에 따라 해당 데이터 형식으로 변환하여 사용할 수 있습니다.따라서 DataTable이 uint8*를 사용하는 이유는 데이터의 다양성과 유연성을 제공하기 위함이며, 이를 통해 사용자가 필요에 따라 다양한 데이터 형식을 DataTable에 저장하고 활용할 수 있습니다.