목차

     

     


     

     

     

     
    Source
        Characters
        CAnimInstance.h .cpp
    CEnemy.h .cpp 

    CPlayer.h .cpp
    ICharacter.h .cpp
        Components
        CMontagesComponent.h .cpp 
    CMovementComponent.h .cpp 
    CStateComponent.h .cpp 
    CWeaponComponent.h .cpp 
        Notifies
        CAnimNotifyState_BeginAction.h .cpp 
    CAnimNotifyState_EndAction.h .cpp
    CAnimNotify_EndState.h .cpp

    CAnimNotifyState_Collision.h .cpp 
    CAnimNotifyState_Combo.h .cpp
    CAnimNotifyState_Equip.h .cpp
        Utilities
        CHelper.h
    CLog.h .cpp
        Weapons
        CDoAction_Combo.h .cpp

    CAttachment.h .cpp
    CDoAction.h .cpp

    CEquipment.h .cpp
    CWeaponAsset.h .cpp

    CWeaponStructures.h .cpp
        Global.h
    CGameMode.h .cpp
    U2212_06.Build.cs
        U2212_06.uproject
     

     

     

     

     

    Hit Data 활용하기

     


     

     

    CWeaponStructure  -  Hit Data 추가하기

     

    CWeaponStructure.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "UObject/NoExportTypes.h"
    #include "CWeaponStructures.generated.h"
    USTRUCT()
    struct FEquipmentData
    {
    GENERATED_BODY()
    public:
    UPROPERTY(EditAnywhere)
    class UAnimMontage* Montage;
    UPROPERTY(EditAnywhere)
    float PlayRate = 1;
    UPROPERTY(EditAnywhere)
    bool bCanMove = true;
    UPROPERTY(EditAnywhere)
    bool bUseControlRotation = true;
    };
    USTRUCT()
    struct FDoActionData
    {
    GENERATED_BODY()
    public:
    UPROPERTY(EditAnywhere)
    class UAnimMontage* Montage;
    UPROPERTY(EditAnywhere)
    float PlayRate = 1;
    UPROPERTY(EditAnywhere)
    bool bCanMove = true;
    UPROPERTY(EditAnywhere)
    bool bFixedCamera;
    UPROPERTY(EditAnywhere)
    class UFXSystemAsset* Effect; //사용할 Effect 변수
    UPROPERTY(EditAnywhere)
    FVector EffectLocation = FVector::ZeroVector;//(Effect)지정 방향의 보정치.
    UPROPERTY(EditAnywhere)
    FVector EffectScale = FVector::OneVector;//Effect 크기 기본값 1 설정.
    public:
    void DoAction(class ACharacter* InOwner);
    };
    USTRUCT()
    struct FHitData
    {
    GENERATED_BODY()
    UPROPERTY(EditAnywhere)
    class UAnimMontage* Montage;
    UPROPERTY(EditAnywhere)
    float PlayRate = 1;
    UPROPERTY(EditAnywhere)
    float Power;
    UPROPERTY(EditAnywhere)
    float Launch = 100;
    UPROPERTY(EditAnywhere)
    float StopTime;
    UPROPERTY(EditAnywhere)
    class USoundWave* Sound;
    UPROPERTY(EditAnywhere)
    class UFXSystemAsset* Effect;
    UPROPERTY(EditAnywhere)
    FVector EffectLocation = FVector::ZeroVector;
    UPROPERTY(EditAnywhere)
    FVector EffectScale = FVector::OneVector;
    public:
    void SendDamage(class ACharacter* InAttacker, AActor* InAttackCauser, class ACharacter* InOther);
    void PlayMontage(class ACharacter* InOwner);
    void PlayHitStop(UWorld* InWorld);
    void PlaySoundWave(class ACharacter* InOwner);
    };
    USTRUCT()
    struct FActionDamageEvent : public FDamageEvent
    {
    GENERATED_BODY()
    public:
    FHitData* HitData;
    };
    UCLASS()
    class U2212_06_API UCWeaponStructures : public UObject
    {
    GENERATED_BODY()
    };

    FHitData 구조체 추가

    • 구조체 내에 변수 추가
      • class UAnimMontage* Montage;
      • float PlayRate = 1;
      • float Power;
      • float Launch = 100;
      • float StopTime;
      • class USoundWave* Sound;
      • class UFXSystemAsset* Effect;
      • FVector EffectLocation = FVector::ZeroVector;
      • FVector EffectScale = FVector::OneVector;
    • 함수 추가
      • void SendDamage(class ACharacter* InAttacker, AActor* InAttackCauser, class ACharacter* InOther);
      • void PlayMontage(class ACharacter* InOwner);
      • void PlayHitStop(UWorld* InWorld);
      • void PlaySoundWave(class ACharacter* InOwner);

     

     

     

    CWeaponStructure.cpp

    더보기
    #include "Weapons/CWeaponStructures.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    #include "Components/CStateComponent.h"
    #include "Components/CMovementComponent.h"
    #include "Animation/AnimMontage.h"
    void FDoActionData::DoAction(ACharacter* InOwner)
    {
    UCMovementComponent* movement = CHelpers::GetComponent<UCMovementComponent>(InOwner);
    if (!!movement)
    {
    if (bFixedCamera)
    movement->EnableFixedCamera();
    if (bCanMove == false)
    movement->Stop();
    }
    if (!!Montage)
    InOwner->PlayAnimMontage(Montage, PlayRate);
    }
    void FHitData::SendDamage(ACharacter* InAttacker, AActor* InAttackCauser, ACharacter* InOther)
    {
    FActionDamageEvent e;
    e.HitData = this;
    InOther->TakeDamage(Power, e, InAttacker->GetController(), InAttackCauser);
    }
    void FHitData::PlayMontage(ACharacter* InOwner)
    {
    if (!!Montage)
    InOwner->PlayAnimMontage(Montage, PlayRate);
    }
    void FHitData::PlayHitStop(UWorld* InWorld)
    {
    CheckTrue(FMath::IsNearlyZero(StopTime));
    TArray<ACharacter*> characters;
    for(AActor* actor : InWorld->GetCurrentLevel()->Actors)
    {
    ACharacter* character = Cast<ACharacter>(actor);
    if(!!character)
    {
    character->CustomTimeDilation = 1e-3f;
    characters.Add(character);
    }
    }
    //익명 메소드 //람다 클로저
    //람다는 외부에서 닫힌 상태로 실행되는 객체
    FTimerDelegate timerDelegate;
    timerDelegate.BindLambda([=]()
    {
    for (ACharacter* character : characters)
    character->CustomTimeDilation = 1;
    });
    FTimerHandle timerHandle;
    InWorld->GetTimerManager().SetTimer(timerHandle, timerDelegate, StopTime, false);
    }
    void FHitData::PlaySoundWave(ACharacter* InOwner)
    {
    CheckNull(Sound);
    UWorld* world = InOwner->GetWorld();
    FVector location = InOwner->GetActorLocation();
    UGameplayStatics::SpawnSoundAtLocation(world, Sound, location);
    }

    FHitData 구조체

    • 함수 정의
      • void FHitData::SendDamage(ACharacter* InAttacker, AActor* InAttackCauser, ACharacter* InOther)
      • void FHitData::PlayMontage(ACharacter* InOwner)
      • void FHitData::PlayHitStop(UWorld* InWorld)
      • void FHitData::PlaySoundWave(ACharacter* InOwner)

     

     

     


     

    CWeaponAsset

     

    CWeaponAsset.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Engine/DataAsset.h"
    #include "Weapons/CWeaponStructures.h"
    #include "CWeaponAsset.generated.h"
    UCLASS()
    class U2212_06_API UCWeaponAsset : public UDataAsset
    {
    GENERATED_BODY()
    private:
    UPROPERTY(EditAnywhere)
    TSubclassOf<class ACAttachment> AttachmentClass;
    UPROPERTY(EditAnywhere)
    FEquipmentData EquipmentData;
    UPROPERTY(EditAnywhere)
    TSubclassOf<class UCEquipment> EquipmentClass;
    UPROPERTY(EditAnywhere)
    TSubclassOf<class UCDoAction> DoActionClass;
    UPROPERTY(EditAnywhere)
    TArray<FDoActionData> DoActionDatas; //CWeaopnStructure내의 FDoActionData
    UPROPERTY(EditAnywhere)
    TArray<FHitData> HitDatas; //CWeaopnStructure내의 FHitData
    public:
    FORCEINLINE class ACAttachment* GetAttachment() { return Attachment; }//외부에 생성된 것을 리턴해줌.
    FORCEINLINE class UCEquipment* GetEquipment() { return Equipment; }//외부에 생성된 것을 리턴해줌.
    FORCEINLINE class UCDoAction* GetDoAction() { return DoAction; }//외부에 생성된 것을 리턴해줌.
    public:
    UCWeaponAsset();
    void BeginPlay(class ACharacter* InOwner);
    private:
    //UPROPERTY를 붙여 가비지 콜렉터가 제거하기 전까지 물고 있게 만든다.
    //UWeaponAsset은 UObject로부터 상속받아 Actor의 생성주기에 영향을 받지 않아 가비지 콜렉터에 영향을 받는다.
    UPROPERTY()
    class ACAttachment* Attachment;
    UPROPERTY()
    class UCEquipment* Equipment;
    UPROPERTY()
    class UCDoAction* DoAction;
    };

    변수 추가

    • TArray<FHitData> HitDatas

     

     

     

    CWeaponAsset.cpp

    더보기
    #include "Weapons/CWeaponAsset.h"
    #include "Global.h"
    #include "CAttachment.h"
    #include "CEquipment.h"
    #include "CDoAction.h"
    #include "GameFramework/Character.h"
    UCWeaponAsset::UCWeaponAsset()
    {
    AttachmentClass = ACAttachment::StaticClass();//기본값
    EquipmentClass = UCEquipment::StaticClass();//기본값
    DoActionClass = UCDoAction::StaticClass();//기본값
    }
    void UCWeaponAsset::BeginPlay(ACharacter* InOwner)
    {
    if (!!AttachmentClass)//AttachmentClass가 선택되어 있다면
    {
    FActorSpawnParameters params;
    params.Owner = InOwner;
    Attachment = InOwner->GetWorld()->SpawnActor<ACAttachment>(AttachmentClass, params);
    }
    if (!!EquipmentClass)//EquipmentClass가 선택되어 있다면
    {
    Equipment = NewObject<UCEquipment>(this, EquipmentClass);
    Equipment->BeginPlay(InOwner, EquipmentData);
    if (!!Attachment)//Attachment가 있다면
    {
    Equipment->OnEquipmentBeginEquip.AddDynamic(Attachment, &ACAttachment::OnBeginEquip);
    Equipment->OnEquipmentUnequip.AddDynamic(Attachment, &ACAttachment::OnUnequip);
    }
    }
    if(!!DoActionClass)
    {
    DoAction = NewObject<UCDoAction>(this, DoActionClass);
    DoAction->BeginPlay(Attachment, Equipment, InOwner, DoActionDatas, HitDatas);
    if (!!Attachment)
    {
    Attachment->OnAttachmentBeginCollision.AddDynamic(DoAction, &UCDoAction::OnAttachmentBeginCollision);
    Attachment->OnAttachmentEndCollision.AddDynamic(DoAction, &UCDoAction::OnAttachmentEndCollision);
    Attachment->OnAttachmentBeginOverlap.AddDynamic(DoAction, &UCDoAction::OnAttachmentBeginOverlap);
    Attachment->OnAttachmentEndOverlap.AddDynamic(DoAction, &UCDoAction::OnAttachmentEndOverlap);
    }
    }
    }

    DoAction->BeginPlay 호출 시 HitDatas도 같이 넘겨준다. 

    • if ( !!DoActionClass )  {
      DoAction = NewObject<UCDoAction>(this, DoActionClass);
      DoAction->BeginPlay(Attachment, Equipment, InOwner, DoActionDatas, HitDatas); }

     

     


     

     

    CDoAction

     

    CDoAction.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "UObject/NoExportTypes.h"
    #include "Weapons/CWeaponStructures.h"
    #include "CDoAction.generated.h"
    UCLASS(Abstract)//DoAction 그 자체로는 객체화되면 안 되기 때문에 Abstract을 붙여준다.
    class U2212_06_API UCDoAction : public UObject
    {
    GENERATED_BODY()
    public:
    UCDoAction();
    virtual void BeginPlay //재정의 할 수 있도록 virtual로 만든다.
    (
    class ACAttachment* InAttachment,
    class UCEquipment* InEquipment,
    class ACharacter* InOwner,
    const TArray<FDoActionData>& InDoActionDatas,//CWeaponStucture내의 FDoActionData
    const TArray<FHitData>& InHitDatas //CWeaponStucture내의 FHitData
    );
    public:
    //재정의 할 수 있도록 virtual로 만든다.
    virtual void DoAction();
    virtual void Begin_DoAction();
    virtual void End_DoAction();
    public:
    UFUNCTION()
    virtual void OnAttachmentBeginCollision() {}
    UFUNCTION()
    virtual void OnAttachmentEndCollision() {}
    UFUNCTION()
    virtual void OnAttachmentBeginOverlap(class ACharacter* InAttacker, AActor* InAttackCauser, class ACharacter* InOther) { }
    UFUNCTION()
    virtual void OnAttachmentEndOverlap(class ACharacter* InAttacker, class ACharacter* InOther) { }
    protected:
    bool bBeginAction;
    class ACharacter* OwnerCharacter;
    class UWorld* World;
    class UCMovementComponent* Movement;
    class UCStateComponent* State;
    TArray<FDoActionData> DoActionDatas;
    TArray<FHitData> HitDatas;
    };

     

     

     

    CDoAction.cpp

    더보기
    #include "Weapons/CDoAction.h"
    #include "Global.h"
    #include "CAttachment.h"
    #include "CEquipment.h"
    #include "GameFramework/Character.h"
    #include "Components/CStateComponent.h"
    #include "Components/CMovementComponent.h"
    UCDoAction::UCDoAction()
    {
    }
    void UCDoAction::BeginPlay(ACAttachment* InAttachment, UCEquipment* InEquipment, ACharacter* InOwner, const TArray<FDoActionData>& InDoActionDatas, const TArray<FHitData>& InHitDatas)
    {
    OwnerCharacter = InOwner;
    World = OwnerCharacter->GetWorld();
    State = CHelpers::GetComponent<UCStateComponent>(OwnerCharacter);
    Movement = CHelpers::GetComponent<UCMovementComponent>(OwnerCharacter);
    DoActionDatas = InDoActionDatas;
    HitDatas = InHitDatas;
    }
    void UCDoAction::DoAction()
    {
    State->SetActionMode();
    }
    void UCDoAction::Begin_DoAction()
    {
    bBeginAction = true;
    }
    void UCDoAction::End_DoAction()
    {
    bBeginAction = false;
    State->SetIdleMode();
    Movement->Move();
    Movement->DisableFixedCamera();
    }

     


     

    CDoAction_Combo

     

    CDoAction_Combo.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Weapons/CDoAction.h"
    #include "CDoAction_Combo.generated.h"
    UCLASS()
    class U2212_06_API UCDoAction_Combo : public UCDoAction
    {
    GENERATED_BODY()
    public:
    FORCEINLINE void EnableCombo() { bEnable = true; }
    FORCEINLINE void DisableCombo() { bEnable = false; }
    public:
    void DoAction() override;
    void Begin_DoAction() override;
    void End_DoAction() override;
    public:
    void OnAttachmentBeginOverlap(class ACharacter* InAttacker, AActor* InAttackCauser, class ACharacter* InOther) override;
    private:
    int32 Index;
    bool bEnable;
    bool bExist;
    };

    변경사항 없음

     

     

     

    CDoAction_Combo.cpp

    더보기
    #include "Weapons/DoActions/CDoAction_Combo.h"
    #include "Global.h"
    #include "GameFramework/Character.h"
    #include "Components/CStateComponent.h"
    void UCDoAction_Combo::DoAction()
    {
    CheckTrue(DoActionDatas.Num() < 1);
    if (bEnable) //bEnable이라면 Combo 구간
    {
    bEnable = false;
    bExist = true;
    return;
    }
    CheckFalse(State->IsIdleMode());
    Super::DoAction(); //첫 타격이 들어간 후에 Combo의 bEnable이 호출되어야 한다. 그래서 맨 위가 아닌 여기에 위치한다.//첫 타격 시 IsIdleMode()를 체크 통과한 후 부모의 DoAction으로 들어가 State->ActionMode()로 변경한다.
    DoActionDatas[Index].DoAction(OwnerCharacter);
    }
    void UCDoAction_Combo::Begin_DoAction()
    {
    Super::Begin_DoAction();
    CheckFalse(bExist);//다음 Combo가 없으면 바로 End_DoAction으로 이동.
    bExist = false;
    DoActionDatas[++Index].DoAction(OwnerCharacter);
    }
    void UCDoAction_Combo::End_DoAction()
    {
    Super::End_DoAction();
    Index = 0;
    }
    void UCDoAction_Combo::OnAttachmentBeginOverlap(ACharacter* InAttacker, AActor* InAttackCauser, ACharacter* InOther)
    {
    Super::OnAttachmentBeginOverlap(InAttacker, InAttackCauser, InOther);//CDoAction.h의 OnAttachmentBeginOverlap
    CheckNull(InOther);
    FActionDamageEvent e;
    e.HitData = &HitDatas[0];
    //TakeDamage 체크용 디버그
    //CLog::Log(InOther->GetName());
    //InOther->TakeDamage(20, FDamageEvent(), InAttacker->GetController(), InAttackCauser);//데미지 적용.
    //InOther->TakeDamage(e.HitData->Power, e, InAttacker->GetController(), InAttackCauser);//업캐스팅. 업캐스팅은 항상 성립한다.
    HitDatas[Index].SendDamage(InAttacker, InAttackCauser, InOther);
    }

    OnAttachment BeginOverlap 수정

     


     

     

     

    실행화면

     

     


     

     

     

     

    Effect 추가하기

     

     


     

    U2212_06.Build.cs

     

    U2212_06.Build.cs

    더보기
    using UnrealBuildTool;
    public class U2212_06 : ModuleRules
    {
    public U2212_06(ReadOnlyTargetRules Target) : base(Target)
    {
    PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
    PublicIncludePaths.Add(ModuleDirectory);
    PublicDependencyModuleNames.Add("Core");
    PrivateDependencyModuleNames.Add("CoreUObject");
    PrivateDependencyModuleNames.Add("Engine");
    PrivateDependencyModuleNames.Add("InputCore");
    PrivateDependencyModuleNames.Add("Niagara");
    }
    }

    PrivateDependencyModuleNames 추가

    • PrivateDependencyModuleNames.Add("Niagara");
      • Niagara 파티클을 사용하기 위해 추가하였다.

     

     

    CHelpers.h

     

    CHelpers.h

    더보기
    #pragma once
    #include "CoreMinimal.h"
    #include "Particles/ParticleSystem.h"
    #include "NiagaraSystem.h"
    #include "NiagaraFunctionLibrary.h"
    #define CheckTrue(x) { if(x == true) return; }
    #define CheckTrueResult(x, y) { if(x == true) return y; }
    #define CheckFalse(x) { if(x == false) return;}
    #define CheckFalseResult(x, y) { if(x == false) return y;}
    #define CheckNull(x) { if(x == nullptr) return;}
    #define CheckNullResult(x, y) { if(x == nullptr) return y;}
    #define CreateTextRender()\
    {\
    CHelpers::CreateComponent<UTextRenderComponent>(this, &Text, "Tex", Root);\
    Text->SetRelativeLocation(FVector(0, 0, 100));\
    Text->SetRelativeRotation(FRotator(0, 180, 0));\
    Text->SetRelativeScale3D(FVector(2));\
    Text->TextRenderColor = FColor::Red;\
    Text->HorizontalAlignment = EHorizTextAligment::EHTA_Center;\
    Text->Text = FText::FromString(GetName().Replace(L"Default__", L""));\
    }
    class U2212_06_API CHelpers
    {
    public:
    template<typename T>
    static void CreateComponent(AActor* InActor, T** OutComponent, FName InName, USceneComponent* InParent = nullptr, FName InSocketName = NAME_None)
    {
    *OutComponent = InActor->CreateDefaultSubobject<T>(InName);
    if (!!InParent)
    {
    (*OutComponent)->SetupAttachment(InParent, InSocketName); //이렇게 사용하면 Socket Name에 _를 사용하면 안 된다.
    return;
    }
    InActor->SetRootComponent(*OutComponent);
    }
    //CreateActorComponent 추가
    template<typename T>
    static void CreateActorComponent(AActor* InActor, T** OutComponent, FName InName)
    {
    *OutComponent = InActor->CreateDefaultSubobject<T>(InName);
    }
    template<typename T>
    static void GetAsset(T** OutObject, FString InPath)
    {
    ConstructorHelpers::FObjectFinder<T> asset(*InPath);
    *OutObject = asset.Object;
    }
    template<typename T>
    static void GetAssetDynamic(T** OutObject, FString InPath)
    {
    *OutObject = Cast<T>(StaticLoadObject(T::StaticClass(), nullptr, *InPath));
    }
    template<typename T>
    static void GetClass(TSubclassOf<T>* OutClass, FString InPath)
    {
    ConstructorHelpers::FClassFinder<T> asset(*InPath);
    *OutClass = asset.Class;
    }
    template<typename T>
    static T* FindActor(UWorld* InWorld)
    {
    for (AActor* actor : InWorld->GetCurrentLevel()->Actors)
    {
    if (!!actor && actor->IsA<T>())
    return Cast<T>(actor);
    }
    return nullptr;
    }
    template<typename T>
    static void FindActors(UWorld* InWorld, TArray<T*>& OutActors)
    {
    for (AActor* actor : InWorld->GetCurrentLevel()->Actors)
    {
    if (!!actor && actor->IsA<T>())
    OutActors.Add(Cast<T>(actor));
    }
    }
    template<typename T>
    static T* GetComponent(AActor* InActor)
    {
    return Cast<T>(InActor->GetComponentByClass(T::StaticClass()));
    }
    template<typename T>
    static T* GetComponent(AActor* InActor, const FString& InName)
    {
    TArray<T*> components;
    InActor->GetComponents<T>(components);
    for (T* component : components)
    {
    if (component->GetName() == InName)
    return component;
    }
    return nullptr;
    }
    static void AttachTo(AActor* InActor, USceneComponent* InParent, FName InSocketName)
    {
    InActor->AttachToComponent(InParent, FAttachmentTransformRules(EAttachmentRule::KeepRelative, true), InSocketName);
    }
    static void PlayEffect(UWorld* InWorld, UFXSystemAsset* InAsset, const FTransform& InTransform, USkeletalMeshComponent* InMesh = nullptr, FName InSocketName = NAME_None)
    {
    UParticleSystem* particle = Cast<UParticleSystem>(InAsset);
    UNiagaraSystem* niagara = Cast<UNiagaraSystem>(InAsset);
    FVector location = InTransform.GetLocation();
    FRotator rotation = FRotator(InTransform.GetRotation());
    FVector scale = InTransform.GetScale3D();
    if(!!InMesh) //InMesh에 붙어있다면
    {
    if(!!particle) //particle이라면
    {
    UGameplayStatics::SpawnEmitterAttached(particle, InMesh, InSocketName, location, rotation, scale);
    return;
    }
    if(!!niagara) //niagara라면
    {
    UNiagaraFunctionLibrary::SpawnSystemAttached(niagara, InMesh, InSocketName, location, rotation, scale, EAttachLocation::KeepRelativeOffset, true, ENCPoolMethod::None);//Pooling풀링 사용.
    return;
    }
    }
    if(!!particle) //어디에 붙어있지 않고 particle이면
    {
    UGameplayStatics::SpawnEmitterAtLocation(InWorld, particle, InTransform);//해당 위치에서 실행
    return;
    }
    if (!!niagara) //어디에 붙어있지 않고 niagara면
    {
    UNiagaraFunctionLibrary::SpawnSystemAtLocation(InWorld, niagara, location, rotation, scale);//해당 위치에서 실행
    return;
    }
    }
    };

    헤더 추가

    • #include "Particles/ParticleSystem.h"
    • #include "NiagaraSystem.h"
    • #include "NiagaraFunctionLibrary.h"

    Effect 추가

    • static void PlayEffect(UWorld* InWorld, UFXSystemAsset* InAsset, const FTransform& InTransform, USkeletalMeshComponent* InMesh = nullptr, FName InSocketName = NAME_None)

     

     


     

    오브젝트 풀링 (Object Pooling)

     

    필요한만큼 미리 생성해서 필요할 때 꺼내 사용한다. 배열보다 vector를 사용하는게 좋다. vector가 수정하기도 체크하기도 더 낫다. 속도 차이는 없다고봐도 무방하다.

     

    장점: 메모리 단편화를 방지할 수 있다.

    단점: 처음에 메모리 구간이 많이 소요될 수 있다.