Static variables error

Hello.

I’ve been trying to get static variables to work, but with no luck. I get an error when I compile which says:

Error 1 error LNK2001: unresolved external symbol "public: static class TArray<class UItemBase *,class FDefaultAllocator> UItemList::itemList" (?itemList@UItemList@@2V?$TArray@PEAVUItemBase@@VFDefaultAllocator@@@@A)

My .h file:

#pragma once
#include "Engine.h"
#include "ItemBase.h"
#include "ItemList.generated.h"

UCLASS()
class UItemList : public UObject
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = Item)
	static void InitializeItems();

	UFUNCTION(BlueprintCallable, Category = Item)
	static UTexture* GetTexture(FString textureName);

	//UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item)
	static TArray<UItemBase*> itemList;

	//UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item)
	static TArray<FAssetData> assetDataTextures;

	//UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item)
	static UObjectLibrary* libTextures;
};

And my .cpp file:

#include "projectsurvive.h"
#include "ItemList.h"
#include "Engine.h"
#include "ItemConsumable.h"
#include "ItemWeapon.h"

void UItemList::InitializeItems()
{
	// Load textures
	libTextures = UObjectLibrary::CreateLibrary(UTexture::StaticClass(), true, GIsEditor);
	libTextures->AddToRoot();
	libTextures->LoadAssetDataFromPath(TEXT("/Game/Textures/ItemIcons"));
	libTextures->GetAssetDataList(assetDataTextures);


	// Initialize items
	itemList.Add(static_cast<UItemBase*>(UItemConsumable::NewConsumable("Food", GetTexture(""), 2000, FVector2D(3, 3), 20)));

	for (int32 i = 0; i < itemList.Num(); ++i)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, itemList[i]->itemName);
	}
}

UTexture* UItemList::GetTexture(FString textureName)
{
	for (int32 i = 0; i < assetDataTextures.Num(); ++i)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, assetDataTextures[i].GetAsset()->GetName());
		if (textureName == assetDataTextures[i].GetAsset()->GetName())
			return static_cast<UTexture*>(assetDataTextures[i].GetAsset());
	}
	return NULL;
}

Any ideas?

I don’t think you can have static TArrays, the whole point of them is to be Dynamic.

The error is stating that you have no definition of that static variable anywhere in the translation unit. For this to work you’ll have to add something like the following to your cpp:

TArray<UItemBase*> UItemList::itemList;
TArray<FAssetData> UItemList::assetDataTextures;
UObjectLibrary* UItemList::libTextures;

But I’m a little concerned that this isn’t really what you want - I can see that you’re adding libTextures to the root, but it seems like these things would be better housed within an instance of a singleton, rather than all being static themselves. As such they’d better afford the protection of being UPROPERTIES.

1 Like

UE4 reflaction system is not dealing well with global and static (except functions) things

Instead of making static function and variables create non-static manager class which you spawn and attack to PlayerController or Character (considering you want to create inventory system), then for easy access you can create a static function which gets manager from player controller or if you gonna have only single character with that menager you cna do the same with character or pawn

In UE3 inventory system (which got removed in UE4 as it was mainly done for shooters) Inventory was managed by InventoryManager class which was attached to pawns (so every pawn could have inventory even if it’s AI), check it out for inspiration:

I tried adding those three lines to my .cpp, and then I get this error: Error 1 error C2655: 'UItemList::itemList' : definition or redeclaration illegal in current scope

By the way, I’m not very good at c++ yet, I’m just trying to learn at the moment.

Those definitions need to exist at the global scope, rather than inside a function. I should reiterate though, making all this stuff static isn’t advisable. You’re better off not having any of this static, and accessing the data through an instance of UItemList

Alright, I guess that would be better. I just wanted to only do this on the server later on, and I thought this was the best option.

EDIT: It works now after making them in the global scope.

Thanks, I’ll take a look at it. :slight_smile:

404 error on that url