오늘의 코드카타
금과 은 운반하기
- 최적화 문제 = 결정 문제 + 이분 탐색
- parametric search
- LV3 - 17% (복습 필요)
-> 문제 풀이
오늘의 공부
GAS 공부
1. Gameplay Tag & Gameplay Cue 시스템
- AGameplayCueNotify_Actor : 복잡한 연출에서 활용
- Tag를 통해 GameplayCue가 자동으로 실행되게 함
bool AGameplayCue_Status_Poisoned::OnActive_Implementation(AActor* Target, const FGameplayCueParameters& Parameters) {
int32 StackCount = 1;
// Tag를 활용해 Gameplay Effect에서 스택 수 받아오기
UAbilitySystemComponent* ASC = Parameters.EffectContext.GetOriginalInstigatorAbilitySystemComponent();
if (ASC)
{
FGameplayEffectQuery Query = FGameplayEffectQuery::MakeQuery_MatchAnyOwningTags(
FGameplayTagContainer(FGameplayTag::RequestGameplayTag("Status.Poisoned")));
TArray<FActiveGameplayEffectHandle> ActiveEffects = ASC->GetActiveEffects(Query);
if (ActiveEffects.Num() > 0)
{
const FActiveGameplayEffect* ActiveGE = ASC->GetActiveGameplayEffect(ActiveEffects[0]);
if (ActiveGE)
{
StackCount = ActiveGE->Spec.GetStackCount();
}
}
}
// 스택 수 별로 다른 사운드 이펙트 설정
USoundBase* PoisonSound = nullptr;
float SoundVolume = 1.0f;
switch (StackCount)
{
case 1:
PoisonSound = LightPoisonSound;
SoundVolume = 0.3f;
break;
case 2:
PoisonSound = ModeratePoisonSound;
SoundVolume = 0.5f;
break;
case 3:
case 4:
PoisonSound = HeavyPoisonSound;
SoundVolume = 0.7f;
break;
case 5:
default:
PoisonSound = LethalPoisonSound;
SoundVolume = 1.0f;
break;
}
if (PoisonSound)
{
PoisonAudioComponent = UGameplayStatics::SpawnSoundAttached(
PoisonSound,
Target->GetRootComponent()
);
if (PoisonAudioComponent)
{
PoisonAudioComponent->SetVolumeMultiplier(SoundVolume);
}
}
...
}
2. Gameplay Effect에 태그 할당 시 주의사항
UHealCooldownEffect::UHealCooldownEffect()
{
UTargetTagsGameplayEffectComponent* TargetTags = CreateDefaultSubobject<UTargetTagsGameplayEffectComponent>(TEXT("TargetTagsComp"));
FInheritedTagContainer TagChanges = TargetTags->GetConfiguredTargetTagChanges();
TagChanges.Added.AddTag(FGameplayTag::RequestGameplayTag("Cooldown.Heal"));
TargetTags->SetAndApplyTargetTagChanges(TagChanges);
}
- 동작 과정
- 태그를 할당하기 위해
SetAndApplyTargetTagChanges() 호출
- 실행(Development) 모드에서는 동작이 되나, 디버그 모드에서는 크래시 발생
- 원인
UGameplayEffect는 기본적으로 GameplayEffectComponent(추가적인 기능 컴포넌트)들을 GEComponents 배열로 관리
UTargetTagsGameplayEffectComponent가 생성이 되지만, GEComponents에 등록되지 않아서 엔진 내부 로직에서 접근할 때 nullptr 예외가 발생
- 해결법
GEComponents에 직접 GameplayEffectComponent 등록
GEComponents.Add(TargetTags);
오늘의 CS
컴퓨터의 물리적 메모리 계층
- 성능순 : 레지스터 > 캐시 > RAM (주기억장치) > SSD/HDD (보조기억장치)
- 성능과 용량, 비용은 역순
1. 레지스터
- CPU 내부에 존재, 가장 빠른 메모리
- CPU가 연산할 때 사용하는 저장 공간
- 크기가 매우 작음
2. 캐시 메모리
- CPU와 RAM 사이에 위치 (속도 차이를 해결하기 위한 기억 장치)
- 자주 쓰는 데이터를 보관해 CPU가 빠르게 접근할 수 있도록 함
- 3계층
- L1 캐시 : CPU 코어 내부에 있고, 각 코어가 독점적으로 사용. 가장 빠름.
- L2 캐시 : 코어별로 할당되는 경우가 많음. L1보다 크고 느림.
- L3 캐시 : 모든 코어가 공유하는 캐시. 가장 크고 가장 느림.
3. RAM (주기억 장치)
- 실행 중인 프로그램과 데이터를 저장하는 휘발성 기억 장치
- 접근 속도가 하드 디스크보다 빠름
- CPU가 캐시 미스가 발생하면 RAM에서 데이터를 가져옴
4. SSD / HDD (보조기억 장치)
- 프로그램, 파일 등을 영구 저장
- RAM보다 훨씬 느리지만, 훨씬 용량이 크고 저렴함
- SSD (Solid State Drive)
- 구조 : 플래시 메모리를 사용 -> 반도체 기반
- 특징
- 전자적으로만 동작 -> 기계적 부품 없음
- 접근 속도 빠름
- 가격은 비쌈
- HDD (Hard Disk Drive)
- 구조 : 자기 디스크가 고속 회전하면서, 기계적 헤드가 데이터를 읽고 씀
- 특징
- 기계적 동작 -> 물리적 마모, 충격에 취약
- 용량 대비 가격이 매우 저렴
- 속도는 느림