27:03 부분에서, target이 is not set으로 시작하여 오른쪽 시퀀스의 하위 테스크를 순차적으로 실행중인 상황에서, 만약 target이 detect에 의해 감지되어 is set이 되면 blackboard:target is not set <- 이 데코레이터는 실시간으로 target 값을 감지하여, detect로 인해 데코레이터의 target이 is set으로 될 경우 실행중이던 task는 즉시 failed를 반환한 후 abort를 하게 되는건가요? (데코레이터도 service처럼 tick 함수가 호출되나요?) 이것이 참이라면, abort가 된 후에 root로 돌아가는것이 아니라 상위 노드인 selector로 돌아가서 평가를 다시 하게 되는 원리인가요? 아니면 root로 돌아가게 되나요?
우선 제가 알고있는 바로는 UABCharacterStatComponent::BeginPlay() 가 호출될 시, 내부에서 SetHp 함수가 호출되며 그 안에 있는 OnHpChanged.Broadcast(CurrentHp); 가 호출되므로, 그 전에 OnHpChanged가 바인딩되어 있어야 한다. UABHpBarWidget::NativeConstruct() 내부에 SetupCharacterWidget(this) 가 호출되고, 이 안에서 Stat->OnHpChanged.AddUObject를 통해 &UABHpBarWidget::UpdateHpBar 를 바인딩한다. --- 먼저 OnHpChanged 에 어떤 함수를 바인딩 후에 1. 처럼 Broadcast 를 하는것이 순서로 알고 있는데, 위젯의 NativeConstruct() 는 스탯컴포넌트의 BeginPlay() 보다 늦게 호출되는 것으로 알고 있어서 만약 이것이 사실이라면, 2. 의 바인딩 과정 이전에 이미 스탯컴포넌트의 BeginPlay를 통해서 바인딩되지 않은 OnHpChanged를 Broadcast를 해버리는 결과가 생길수도 있는건가요?
[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버
34분 50초 ObjectManager::Remove(Object* object)에서 auto it = std::remove(...); _objects.erase(it, _objects.end()); 대신에 _objects.erase(findIt); 를 해도 findIt 에는 object에 대한 iterator 값이 저장되어 있으니 erase함수만 사용해도 제거할 object를 vector에서 삭제할 수 있지 않을까 해서 질문드립니다
예를들어 13:50 에서 "친구에게 간다" 가 "친구와 약속"이라는 데코레이터를 만족하여 "약속장소로 이동"을 수행하고 이를 성공적으로 수행했다면, "친구에게 간다"라는 시퀀스는 root에게 성공을 반환하게 되고, 나머지 두 개의 시퀀스는 검토하지 않고 바로 트리 전체를 종료하는 원리인건가요?
45:30 부분에서 에서 세 데이터에셋의 블루프린트를 하나로 묶고 Reload 후 Save All을 했을때, Reload 된 각각의 에셋들이 실제로는 Reload가 안된 채로 저장이 되는 것 같습니다.(다만, 마우스를 갖다대면 primary Asset Type은 표면적으로 변경된것처럼 보입니다.) 반면, 묶음으로 Reload를 한 후, 개별적으로 블루프린트를 열고 일일이 저장버튼을 누르면 그제서야 Reload가 적용이 되는지, ensure()이 통과가 됩니다. 예를들어 에러를 띄우기 위해 ,ABItemData.h 에 있는 코드 return FPrimaryAssetId("ABItemData", GetFName()); 부분에 태그ID 를 "ABItemData3333", GetFName()) 로 바꾼 후, ABItemBox.cpp 에서 FPrimaryAssetId SpecificAssetId(TEXT("ABItemData"), TEXT("ABIS_ScrollTest")); FSoftObjectPtr AssetPtr(Manager.GetPrimaryAssetPath(SpecificAssetId)); 로 바꿔서 아이템 전부를 의도적으로 Scroll 자산으로 설정하고 에디터 실행 후에 설명하신 대로 전체묶음+Reload+save all 을 한 후 플레이를 누르면, 아이템이 생성되는 시점에 ensure(Item) 에서 에러가 발생되길 기대했지만 에러가 발생하지 않고 여전히 정상적으로 아이템박스 인스턴스가 생성이 됩니다. 반면 세묶음으로 Reload를 한 후 세이브는 데이터에셋 블루프린트 각각을 열어 개별저장 한 후에 다시 플레이를 하면 원하던 에러가 뜹니다. 아무래도 save all 이 Reload한 데이터 에셋들을 제대로 저장시키지 못하고 있는게 아닌가 싶습니다. 버그인지 아닌지는 모르겠지만..
[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버
c++ crt detected that the application wrote to memory after end of heap buffer 이라는 오류가 뜹니다. 이걸 무시하면 그대로 원하는 값은 나오기는 합니다. 근데 이걸 그냥 지나칠 수는 없어서 질문해봅니다. f11눌러가면서 에러나는 부분을 찾았는데 reserve에 delete[] _buffer; 를 실행하니 오류가 났습니다. [Vector.h] #pragma once #include<assert.h> class Vector { using T = int; public: explicit Vector() { } ~Vector() { if(_buffer) delete[] _buffer; } int size() { return _size; } int capacity() { return _capacity; } void push_back(const T& data) { if (is_full()) { int newCapacity = static_cast<int>(_capacity * 1.2f); if (_capacity == newCapacity) newCapacity++; reserve(newCapacity); } buffer[ size] = data; _size++; } void reserve(int capacity) { if (capacity <= _capacity) return; _capacity = capacity; T* newBuffer = new T(_capacity); for (int i = 0; i < _size; i++) { newBuffer[i] = _buffer[i]; } if (_buffer) delete[] _buffer; _buffer = newBuffer; } T& operator[](int index) { assert(index >= 0 && index < _size); return _buffer[index]; } int is_full() { return _ size == _ capacity; } int is_empty() { return _size == 0; } private: T* _buffer = nullptr; int _size = 0; int _capacity = 0; }; 해결방법이 있을까요?
[게임 프로그래머 입문 올인원] C++ & 자료구조/알고리즘 & STL & 게임 수학 & Windows API & 게임 서버
안녕하세요 Rookiss님, 섹션11-3 Scene과SceneManager의 중간~32분 정도에서 작성중인 코드입니다. 이렇게 newScene에 DevScene()과 GameScene()을 넣는 부분에 형식지정자 없음과 구문 오류가 발생합니다... Scene클래스와 DevScene, GameScene 클래스 코드도 동영상을 몇번씩 돌려보면서 확인했는데 어디가 문제인지 잘 모르겠습니다... 혹시 어느 부분이 문제가 될지 확인 한 번 부탁드려도 될까요? 감사합니다!
안녕하세요 먼저 좋은 강의 감사드립니다. ABCharacterStatComponent.cpp의 SetLevelStat함수에서 CurrentLevel에 대한 Clamp의 MinValue가 1, MaxValue가 CharacterMaxLevel로 설정되어있는데 인덱스값이므로 MinValue = 1, MaxValue = CharacterMaxLevel - 1로 수정이 필요할 것 같습니다.
안녕하세요, GA, GE 등은 그래도 객체 정보를 담을 수 있게 C++에서 기본적인 작업을 하고 BP로 만든 객체를 세팅해주고 구현이 되는데, GC는 BP로 만든 객체를 세팅 없이 Tag로 바로 발동 되는 거 같습니다. AbilitySystem에서 GamePlayCue로 설정된 Tag의 Asset들을 Tracking하여 따로 관리하는 것일까요?
HUDWidget 같은 경우 CreateWidget함수로 위젯을 만들잖아요,. 근데 HpBarWidget같은 경우 CreateWidget함수가 안 보이더라고요. 어디서 만들어지는거죠? 제가 이해한 바로는 다음과 같습니다. Base클래스 생성자에서 HpBar라는 위젯컴포넌트에 주소 참조해서 가져온 HpBarWidget클래스를 HpBar->SetWidgetClass함수에 넣으면 CreateWidget함수처럼 위젯을 생성한다. 이렇게 이해하는게 맞을까요? 만약 맞다면 언리얼에서 Widget 생성하는 방법은 이렇게 2가지 있을까요? 1. CreateWidget 사용 (HUD 만들 때 사용) 2. 위젯 클래스를 주소참조해 가져와 위젯컴포넌트에 담기 (Actor를 따라다닐 UI 만들 때 사용 )
SetupCharacterWidget 인터페이스 핵심 사용 이유가 액터와 위젯 생성 주기를 고려해 원하는 시점에 초기화 해주기 위함이 맞을까요? 인터페이스를 사용하지 않고, BeginPlay에 다음과 같이 코드를 작성해도 오류는 안 나더라고요. 대신 처음에 플레이어 HP바가 다 채워지지 않은 상태로 시작하는 버그는 있지만요. 아무래도 InitWidget , NativeConstruct 함수가 초기화되지 않았기 때문이겠죠? void AABCharacterBase::BeginPlay() { Super::BeginPlay(); UABHpBarWidget* HpBarWidget = Cast<UABHpBarWidget>(HpBar->GetWidget()); ensure(HpBarWidget); HpBarWidget->UpdateStat(Stat->GetBaseStat(), Stat->GetModifierStat()); HpBarWidget->UpdateHpBar(Stat->GetCurrentHp()); Stat->OnHpChanged.AddUObject(HpBarWidget, &UABHpBarWidget::UpdateHpBar); Stat->OnStatChanged.AddUObject(HpBarWidget, &UABHpBarWidget::UpdateStat); } 호출해도
part2에서 만든 모든 캐릭터들은 CharacterBase 클래스를 상속받아서 동작하고 있는데, 그럼 만약에 적 캐릭터들을 좀 더 플레이어와는 다르게, 적군 만의 어떤 공통적인 기능들이나 스탯 설정같은걸 추가하려면 플레이어용 PlayerCharacterBase와 EnemyCharacterBase 뭐 이런식으로 따로 베이스 클래스를 만들어서 작성하는게 나을까요, 아니면 그냥 기본 바탕은 CharacterBase로 통일시키되 override를 하거나 해서 만드는 것이 나을까요? 막상 베이스 클래스를 2개 만들어서 하려다보니 많이 비효율적인 방식인지 궁금해져서 질문드립니다
8강 아이템 시스템 마지막에 강참조된 아이템들을 약참조로 바꾸는 부분을 공부하다가 질문드립니다 인터넷에서 강참조와 약참조에 대해 좀 더 자세히 공부하다보니 강참조 = TStrongObjectPtr / 약참조 = TSoftObjectPtr 를 사용하며, TObjectPtr과 강참조가 관련된 정보는 없길래 TObjectPtr에 대해 궁금증이 생겼습니다 TObjectPtr에 대해 검색해본 바로는 TObjectPtr은 기존에 사용하던 원시 포인터를 대체하는 포인터를 이용한 단순한 참조에 불과하며, 그러므로 댕글링 포인터 문제 또한 발생할 수 있다. 보통 강참조라고 하는 것은, 객체의 소유권을 가지고 Ref Count를 올리는 역할을 수행해야 하는데, TObjectPtr은 단순히 객체를 참조하는 역할만 하므로 강참조라고 볼 수는 없다 라고 나와 있던데 강의에서 TObjectPtr이 강참조라고 하셨던 것은 어떤 의미인지 궁금합니다 그리고 만약에 TObjectPtr이 강참조가 아니라면, 이는 어떠한 정도의 참조인건지요...? 중참조? 이런 단어는 없는거같던데.. TObjectPtr은 TStrongObjectPtr(강참조) 와 TSoftObjectPtr(약참조) 사이의 어딘가에 있는 애매한 정도의 참조인것인지요?? 추가질문) 약참조를 공부하는데 약참조에도 또 TSoftObjectPtr과 TWeakObjectPtr의 2가지가 존재하더라구요... TSoftObjectPtr 리소스의 주소는 갖고 있되, 로딩은 시켜놓지 않는 경우에 사용 아직 현재 월드에 인스턴스화되지 않은 객체를 참조할 때 사용 TSoftObjectPtr은 FSoftObjectPath를 감싸는 TWeakObjectPtr이다 TWeakObjectPtr Ref Count를 증가시키지 않아야 하는 경우 / 소유권이 없지만 참조는 필요한 경우에 사용 참조하고 있는 오브젝트가 GC에 넘어간 경우, nullptr로 바뀌며 validation 체크를 가능하게 함 이렇게 알고있는데 제가 학습한 내용이 맞는건지요??
먼저, 강의 흐름대로 위젯 블루프린트를 하나 만든 후 'PbHpBar' f라는 ProgressBar를 추가하였으며 그 블루프린트의 부모를 ABHpBarWidget으로 설정해 둔 상태입니다. 여기서 궁금한 점은 ABHpBarWidget은 부모클래스이며, 따라서 자식클래스에서 생성한 'PbHpBar' 라는 위젯의 존재를 알지 못할텐데, 어떻게 HpProgressBar 에 'PbHpBar' 라는 위젯의 존재를 찾아서 주소를 반환할 수 있는것인지 궁금합니다. (만약 부모자식 관계가 바뀌어있다면, 자식에서 부모의 PbHpBar 라는 녀석의 존재를 찾아 포인트를 반환하는게 논리적으로 뭔가 납득이 가는데, 강의의 내용은 마치 상속관계가 반대의 상황인데도 불구하고 가능한것 처럼 보여집니다.) NativeConstruct() 라는 생성자는 제가 모르는 뭔가 특별한 기능을 가진 생성자이며, 따라서 부모클래스임에도 불구하고 자식클래스인 블루프린트 클래스에 있는 위젯의 정보들까지 미리 전부 탐색할 수 있기 때문에 자식에 있는 PbHpBar까지도 찾아서 포인터를 반환할 수 있는 것인가요?
5.1 버전의 강의를 다 듣고, 5.4 깃허브 업데이트 되어서 다시 복습하다가 제목과 같이 스킬 사용할 때 범위 시각화(배포용) 기능을 구현해보고 싶더라구요. 일단, 캐스캐이드가 Legacy 기능이다보니 나이아가라로 다른 스킬 구현은 완료했고, 스킬의 범위를 바닥에 표현하고 싶은데 GAS 프레임워크에서 스킬 범위를 표기할 때 좋은 class가 따로 구현되어 있을까요? 현재 나이아가라 데칼을 써서 해볼까 실험은 하고있는데, 정석적인 방법(?)이 있다면 먼저 그런 방법으로 해보고 싶어서 질문드려요.