Error: NewObject() No Instance of Overloaded Function Matches Argument List

Hello,

I have been working on my Unreal Engine framework. I am currently stuck on an issue that is preventing me from finishing my leveling system component.

When I try to use “NewObject”, my class that I try to plug in keeps returning the following error (at least by Intellisense):

"No instance of overloaded function 'NewObject' matches the argument list".

I am not sure why this is happening so I am coming to the community for an answer as I cannot seem to find any elsewhere.

SKILL TREE COMPONENT:
.h

// Copyright William Antonio Pimentel-Tonche and Rapidfire Computer Entertainment. All rights reserved.

#pragma once

#include "CoreMinimal.h"
#include "CF_ActorComponent.h"
#include "CF_Skill_Base.h"
#include "CF_SkillComponent.generated.h"

// Nested containers (i.e. an array within a map) is generally considered terrible programming practice to my knowledge, but in this case, hey, it works.

USTRUCT(BlueprintType) struct FSkillObjectArray
{
	GENERATED_BODY()

public:

	UPROPERTY(BlueprintReadWrite)
	TArray<UCF_Skill_Base*> SkillObjectArray;

};

USTRUCT(BlueprintType) struct FSkillClassArray
{
	GENERATED_BODY()

public:

	UPROPERTY(BlueprintReadWrite)
	TArray<TSubclassOf<UCF_Skill_Base>> SkillClassArray;
};


/**
 * The Skill Component is a component that provides skill tree based behavior for any Actor, such as your player character.
 * You can have as many of these components on one Actor as you'd like.
 * You can also choose to set up passively activated perks that are unlocked at set levels.
 * If you are looking for a system that would allow for accessory upgrades, such as a cybernetic hardware system, then use the Accessory Component instead.
 */
UCLASS()
class CONNIPTIONFRAMEWORK_API UCF_SkillComponent : public UCF_ActorComponent
{
	GENERATED_BODY()

public:
	// The "root" of the skill tree. This holds all of your skills in a map of categories (strings) to skills (skill arrays).
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Configuration")
	TMap<FString, FSkillClassArray> MainSkillClasses;

	// To set up passively-activated perks/skills, add them here. The key is the level and the value is the array of any desired unlocks at that level. Note that for these, you must set the category manually within the skill base.
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Configuration")
	TMap<int, FSkillClassArray> PassiveSkillClasses;

	// Internal container for skill objects spawned in-game. This is what's actually used by the component internally at runtime.
	UPROPERTY(BlueprintReadOnly, Category = "Skill Tree")
	TMap<FString, FSkillObjectArray> MainSkillObjects;

	// Same as above, but for leveling perks.
	UPROPERTY(BlueprintReadOnly, Category = "Skill Tree")
	TMap<int, FSkillObjectArray> PassiveSkillObjects;

	// Current level.
	UPROPERTY(BlueprintReadOnly, Category = "Skill Tree")
	int Level = 0;

	// Current amount of points.
	UPROPERTY(BlueprintReadOnly, Category = "Skill Tree")
	int SkillPoints = 0;

public:
	// The function that initiates the skill tree component.
	void InitializeSkills();

	// Adds skills to the tree, in arrays of skills.
	void AddSkillArray(FString Category, TArray<UCF_Skill_Base*> SkillArray);

	// Local function for handling skill acquisition requests.
	void OnSkillAcquisitionRequested(FString Category, UCF_Skill_Base* Skill);
	
};

.cpp [this is where the error is]

// Copyright William Antonio Pimentel-Tonche and Rapidfire Computer Entertainment. All rights reserved.


#include "CF_SkillComponent.h"
#include "CF_Skill_Base.h"

void UCF_SkillComponent::InitializeSkills()
{
	// For some reason, in C++ this spits out a set instead of an array.
	TSet<FString> ClassKeys;
	MainSkillClasses.GetKeys(ClassKeys);

	// No big deal, we'll just move it ourselves.
	TArray<FString> ClassKeyArray = ClassKeys.Array();

	// We also need an array of these skills as OBJECTS, not just classes.
	TArray<UCF_Skill_Base*> LocalSkillObjectArray;

	// My stupid OCD brain has some irrational fear of this containing anything at load (it won't) so I'll waste a cycle to make 101% sure it's empty first.
	if(!LocalSkillObjectArray.IsEmpty()){ LocalSkillObjectArray.Empty(0); }

	// Now, we need to run over every category. With a car. Off the edge of a cliff.
	for(FString CurrentCategory : ClassKeyArray)
	{
		// Check if this category is valid.
		if(FSkillClassArray* LocalSkillClasses = MainSkillClasses.Find(CurrentCategory))
		{
			// It is, so let's continue this nest of if() statements and for() loops, yay!
			for(TSubclassOf<UCF_Skill_Base> CurrentClass : LocalSkillClasses->SkillClassArray)
			{
				// Create the new object, assign the category here, and move along.
				UCF_Skill_Base* GeneratedObject = NewObject<CurrentClass>(this);
				GeneratedObject->SkillCategory = CurrentCategory;
				LocalSkillObjectArray.Add(GeneratedObject);
			}
			AddSkillArray(CurrentCategory, LocalSkillObjectArray);
			LocalSkillObjectArray.Empty(0);
		}
	}
}

void UCF_SkillComponent::AddSkillArray(FString Category, TArray<UCF_Skill_Base*> SkillArray)
{
	// Make sure the array has anything at all. We can't do anything with an empty array.
	if(SkillArray.IsEmpty()) { return; }

	// Set our first skill in the category to "Available" so that we can purchase it given enough points.
	SkillArray[0]->SkillState = ESkillStatus::Available;

	// Fill a structure to match our main skill objects array.
	FSkillObjectArray LocalSkillArray;
	LocalSkillArray.SkillObjectArray = SkillArray;
	MainSkillObjects.Add(Category, LocalSkillArray);

	// Loop over every skill, and configure a bind for each one under "On Acquire Request".
	for(UCF_Skill_Base* Skill : SkillArray)
	{
		Skill->OnAcquireRequest->Bind(&UCF_SkillComponent::OnSkillAcquisitionRequested, Category, Skill);
	}
	return;

}

void UCF_SkillComponent::OnSkillAcquisitionRequested(FString Category, UCF_Skill_Base* Skill)
{
	// Verify that we have enough points to purchase our skill.
	if(SkillPoints < Skill->SkillPrice) { return; }

	// We have enough skill points if we made it this far, so reduce our points to atoms.
	// If it was just 1 point per upgrade, we could just decrement, but we don't know how expensive each one will be.
	// The true cost of freedom... (joking of course)
	SkillPoints = SkillPoints - Skill->SkillPrice;

	// Find an array in our map that matches this key.
	FSkillObjectArray* LocalFoundSkillArray = MainSkillObjects.Find(Category);
	if(LocalFoundSkillArray == nullptr) { return; }

	// Save our skill and skill array here.
	TArray<UCF_Skill_Base*> FoundSkillArray = LocalFoundSkillArray->SkillObjectArray;
	int FoundSkill = FoundSkillArray.Find(Skill);

	// At this rate there should be no way this index is invalid, but if there is a way, I'd rather us not find out in a shipped build.
	if(!FoundSkillArray.IsValidIndex(FoundSkill)) { return; }

	// Set this skill as acquired.
	FoundSkillArray[FoundSkill]->SkillState = ESkillStatus::Acquired;

	// Move to the next index in the array.
	int NextSkill = FoundSkill + 1;

	// Make sure the next index is valid, i.e. there's a skill sitting behind the one we just purchased.
	if(FoundSkillArray.IsValidIndex(NextSkill))
	{
		FoundSkillArray[NextSkill]->SkillState = ESkillStatus::Available;
	}

	// Acquire and apply our newly purchased skill.
	FoundSkillArray[FoundSkill]->ApplySkill(GetOwner());
	return;

}

SKILL BASE:
.h

// Copyright William Antonio Pimentel-Tonche and Rapidfire Computer Entertainment. All rights reserved.

#pragma once

#include "CoreMinimal.h"
#include "CF_Skill_Base.generated.h"

UENUM(BlueprintType) enum ESkillStatus
{
	Locked,
	Available,
	Acquired
};

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRequestSkillAcquisition, FString, Category, UCF_Skill_Base*, Skill);

/**
 * This is the base class for all skills under the Conniption Framework's skill tree leveling system.
 */
UCLASS(Abstract)
class CONNIPTIONFRAMEWORK_API UCF_Skill_Base : public UObject
{
	GENERATED_BODY()

public:
	UCF_Skill_Base();
	~UCF_Skill_Base();

public:
	// Event dispatcher to handle requesting acquisitions of skills.
	UPROPERTY(BlueprintAssignable, BlueprintCallable)
	FRequestSkillAcqusition OnAcquireRequest;

	// If this class will be used as a leveling perk, set the category here. Otherwise, the category will be set in the skill component and this will be ignored.
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Skill Configuration|Miscellaneous")
	FString SkillCategory = "A Category for Leveling Perks (Read my Tooltip!)";

	// Name of this skill.
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Skill Configuration")
	FString SkillName = "A Very Cool Skill";

	// Description of this skill.
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Skill Configuration")
	FString SkillDescription = "Trust me, this skill is pretty cool.";

	// Points required to purchase this skill.
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Skill Configuration")
	int SkillPrice = 1;

	// Thumbnail for this skill.
	UPROPERTY(BlueprintReadOnly, EditAnywhere, Category = "Skill Configuration")
	class UTexture2D* SkillThumbnail;

	// Status for this skill.
	UPROPERTY(BlueprintReadOnly)
	TEnumAsByte<ESkillStatus> SkillState;

	// Requests aquisition of a skill.
	UFUNCTION(BlueprintCallable)
	void RequestAcquireSkill();

	// Applies a skill. This function should be overridden in each skill class.
	UFUNCTION(BlueprintImplementableEvent)
	void ApplySkill(AActor* Owner);

};

.cpp

// Copyright William Antonio Pimentel-Tonche and Rapidfire Computer Entertainment. All rights reserved.


#include "CF_Skill_Base.h"

UCF_Skill_Base::UCF_Skill_Base()
{
}

UCF_Skill_Base::~UCF_Skill_Base()
{
}

Any and all help is greatly appreciated. Thanks!

Should be something like this instead

check(CurrentClass);
NewObject<UCF_Skill_Base>(this, *CurrentClass);

Thanks! It’s all working now. On a side note, could you explain how check() works? Opening AssertionMacros.h isn’t telling me all too much but it appears it will assert if the class is invalid yes?

The check() is completely optional. NewObject will call CheckIsClassChildOf_Internal which does the same check internally (depending on some defines). And it also makes sure the given class actually is the same as or a child of UCF_Skill_Base in your case. I always tend to have checks for things that need to be configured in a certain way for the class to function as intended. There may be a better place to put the check in your code so you know as early as possible that you haven’t setup the SkillClassArray correctly.

With a debugger attached any check that fails will cause the debugger to break within the check allowing you to inspect the state of the involved objects and variables. Depending on the code, execution may then resume as normal. In case of NewObject though, StaticConstructObject_Internal is called which directly accesses the class that it gets passed along. In case the class is invalid the game/editor crashes.

1 Like