객체를 직접 컨테이너 내에서 생성하여 임시 객체 생성을 피함
생성자 인자를 직접 받아 인플레이스(in-place)로 객체를 구성
emplace_back이 일반적으로 더 효율적
그러나 가변 인자로 모든 생성자를 호출 가능해 의도치 않은 타입 변환이 발생할 수 있음
기존 객체를 복사하거나 이동시킬 때 사용
객체를 인자로 받아 컨테이너 끝에 복사/이동하며, 복사생성자가 호출되어 비효율적
또 emplace_back과 다르게 명시적 타입만 허용해 컴파일 오류로 잡음
push_back(std::move(obj))을 이용하면 복사가 발생하지 않고 이동 생성자가 호출되어 자원을 효율적으로 이동시킴
lvalue가 아닌 rvalue를 인자로 사용하면 자동으로 이동시켜줌
팀프로젝트를 하면서 원래 적 AI를 기본적으로 서있는 상태로 만들었었음
근데, 기어다니는 좀비를 새로 추가하게 되었고, 피격판정을 위해 캡슐도 눕히려고 하였음

근데 기존 캐릭터를 상속받았기 때문에, 캡슐컴포넌트가 루트라 돌릴수가 없었음
따라서 생성자에서 새로운 Scene Component를 만들어 루트로 설정하고, 캡슐컴포넌트를 이 루트에 붙여서 돌리고자 하였음
RootComp = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
RootComponent = RootComp;
GetCapsuleComponent()->SetupAttachment(RootComponent);
근데 캡슐 돌리고 하기도 전에 AI가 이동을 제대로 못 하고 부들부들 거리는 이상한 현상이 발견됨
찾아보니 캐릭터 충돌/이동 시스템이 캡슐을 전제로 짜여 있어서, 권장하지 않는 방법이었음
그래서 캡슐은 그대로 냅두고, 좀비 피격판정을 skeletal mesh를 기준으로 하기로 하였음
#include "Animation/AnimMontage.h"
void AMyAICharacter::Attack()
{
UAnimInstance* AnimInst = GetMesh()->GetAnimInstance();
if (AnimInst)
{
PlayAnimMontage(AM_Attack);
GetCharacterMovement()->DisableMovement(); // 이동불가
FOnMontageEnded OnMontageEnded;
// 델리게이트랑 호출할 함수랑 연동
OnMontageEnded.BindUObject(this, &AMyAICharacter::OnAttackMontageEnded);
// 애님몽타주랑 델리게이트 연결
AnimInst->Montage_SetEndDelegate(OnMontageEnded, AM_Attack);
}
}
void AMyAICharacter::OnAttackMontageEnded(UAnimMontage* Montage, bool bInterrupted)
{
bIsAttack = false;
if (bInterrupted) return; // 다른 몽타주 재생에 의해 끊긴거면 종료
GetCharacterMovement()->SetMovementMode(MOVE_Walking);
}
델리게이트 이용하여 몽타주 종료 시 함수 호출되게 가능
PlayAnimMontage함수의 반환값이 몽타주 재생시간이라 타이머를 이용해도 되지만, 네트워크 지연/interrupt 같은 상황이 존재할 수 있어 Delegate 사용이 좋음
좀비의 vision mesh를 피하기 위해 캐릭터가 좀비 뒤에서 접근하여도, 좀비가 인식하는 현상이 발생
캐릭터가 뒤에 있어도, Vision Mesh와 Overlap이 발생하였음
오버랩은 액터 단위로 오버랩이 발생하는 것이 아니라, 액터가 가지는 컴포넌트 별로도 오버랩 이벤트가 발생 가능하다는 것을 알게됨
다른 팀원이 캐릭터에 추가한 콜리젼 컴포넌트가 좀비의 vision mesh와 오버랩이 발생하였던 것
그래서 오버랩 일으킨 other comp가 캐릭터 캡슐일 때만 인지하도록 수정하였음