How to #include my own header into the game?

Started by
10 comments, last by MarcusAseth 6 years, 7 months ago

I'm trying to include my Header with helpful functions into my unreal project in order to be able to include it in many other .h classes generated from inside the Editor so that they all can access them, but I am getting a lot of Errors... :S

This is my .h file created from inside VS which I would like to use inside my project:


#pragma once
#include "Engine/World.h"
#include "Classes/Kismet/KismetSystemLibrary.h"
#include "WormGameMode.h"
#include "WormGameMode.generated.h"

//Given a position in the world, returns [row][column]ID inside the GridSlotsOccupiedMap grid.
//FVector(0.f,0.f,0.f) is the center inside the 2D Array, the 2DArray is expected to have and ODD number of elements.
UFUNCTION(BlueprintPure, Category = "Grid")
void WorldLocationToGridID(AWormGameMode* GameMode, FVector Location, int& Row, int&Column)
{
	int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
	int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
	int GridBlockSize = GameMode->GridBlockSize;
	//------------------------------------------

	Row = -Location.Z / GridBlockSize + RowMiddleID;
	Column = Location.X / GridBlockSize + ColumnMiddleID;
}


//Display red wireframe cubes at the occupied position in the grid marked inside GridSlotsOccupiedMap
UFUNCTION(BlueprintCallable, Category = "Debug")
void DebugMarkOccupiedBlocks(AWormGameMode* GameMode)
{
	TArray<TArrayBool> GridSlotsOccupiedMap = GameMode->GetGridSlotsOccupiedMap();
	int GridWidth = GameMode->GridWidth;
	int GridHeight = GameMode->GridHeight;
	int GridBlockSize = GameMode->GridBlockSize;
	int XMiddleID = (GridWidth / GridBlockSize) / 2;
	int YMiddleID = (GridHeight / GridBlockSize) / 2;
	//-----------------------------------------------

	for (int row = 0; row < GridSlotsOccupiedMap.Num(); row++)
	{

		for (int column = 0; column < GridSlotsOccupiedMap[0].BoolRow.Num(); column++)
		{
			float X = (-XMiddleID + column) * GridBlockSize;
			float Z = (YMiddleID - row) * GridBlockSize;
			FVector Center = FVector(X, 50.f, Z + GridBlockSize/2);

			if (GridSlotsOccupiedMap[row][column])
			{
				UE_LOG(LogTemp, Warning, TEXT("Block[%i][%i] is occupied"), row, column)
					UKismetSystemLibrary::DrawDebugBox(GetWorld(),
									Center, FVector(5.7f, 5.7f, 5.7f),
									FColor::Red, FRotator::ZeroRotator, 0.f, 0);
			}
		}
	}
}

As you see I've included #include "WormGameMode.generated.h" as instruction from a topic I've found online, also I've Cut/Pasted it from the Intermediate/ProjectFiles folder where VS created it and pasted into Worm/Source/Worm folder.

Here's the errors the editor is giving back:

 
Quote

CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10) : error C2065: 'AWormGameMode': identificatore non dichiarato
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10) : error C2065: 'GameMode': identificatore non dichiarato
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10) : error C2275: 'FVector': tipo non valido come espressione
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\intermediate\build\win64\ue4editor\inc\worm\WormGameMode.generated.h(11) : note: vedere la dichiarazione di 'FVector'
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10) : error C2065: 'AWormGameMode': identificatore non dichiarato
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10) : error C2065: 'GameMode': identificatore non dichiarato
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10) : error C2275: 'FVector': tipo non valido come espressione
CompilerResultsLog: Error: Z:\Asus\Documenti\Unreal Projects\Worm\Intermediate\Build\Win64\UE4Editor\Inc\Worm\WormGameMode.generated.h(11) : note: vedere la dichiarazione di 'FVector'
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10) : error C2146: errore di sintassi: ')' mancante prima dell'identificatore 'Location'z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(10): error C2146: errore di sintassi: ')' mancante prima dell'identificatore 'Location'
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(11) : error C2143: errore di sintassi: ';' mancante prima di '{'z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(11): error C2143: errore di sintassi: ';' mancante prima di '{'
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(11) : error C2447: '{': intestazione di funzione mancante. Elenco formale di tipo obsoleto?z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(11): error C2447: '{': intestazione di funzione mancante. Elenco formale di tipo obsoleto?
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(24) : error C2065: 'AWormGameMode': identificatore non dichiaratoz:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(24): error C2065: 'AWormGameMode': identificatore non dichiarato
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(24) : error C2065: 'GameMode': identificatore non dichiaratoz:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(24): error C2065: 'GameMode': identificatore non dichiarato
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(24) : error C2182: 'DebugMarkOccupiedBlocks': utilizzo non valido del tipo 'void'z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(24): error C2182: 'DebugMarkOccupiedBlocks': utilizzo non valido del tipo 'void'
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(25) : error C2448: 'DebugMarkOccupiedBlocks': l'inizializzatore di tipo funzione sembra essere una definizione di funzionez:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(25): error C2448: 'DebugMarkOccupiedBlocks': l'inizializzatore di
 tipo funzione sembra essere una definizione di funzione
CompilerResultsLog: Error: Z:\Asus\Documenti\Unreal Projects\Worm\Intermediate\Build\Win64\UE4Editor\Inc\Worm\WormGameMode.generated.h(14) : fatal error C1189: #error:  "WormGameMode.generated.h already included, missing '#pragma once' in WormGameMode.h"z:\asus\documenti\unreal projects\worm\intermediate\build\win64\ue4editor\inc\worm\WormGameMode.generated.
h(14): fatal error C1189: #error:  "WormGameMode.generated.h already included, missing '#pragma once' in WormGameMode.h"
CompilerResultsLog: Error: Z:\Asus\Documenti\Unreal Projects\Worm\Intermediate\Build\Win64\UE4Editor\Inc\Worm\WormGameMode.generated.h(14) : fatal error C1189: #error:  "WormGameMode.generated.h already included, missing '#pragma once' in WormGameMode.h"
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\intermediate\build\win64\ue4editor\inc\worm\WormGameMode.generated.h(14) : fatal error C1189: #error:  "WormGameMode.generated.h already included, missing '#pragma once' in WormGameMode.h"
CompilerResultsLog: ERROR: UBT ERROR: Failed to produce item: Z:\Asus\Documenti\Unreal Projects\Worm\Binaries\Win64\UE4Editor-Worm-9504.dll

Apologize, I didn't yet figured out how to set my Unreal Engine in English... :|

Advertisement

UP: I've changed into the following code and I am getting less errors:


#pragma once
#include "Engine/World.h"
#include "Classes/Kismet/KismetSystemLibrary.h"
#include "WormGameMode.h"
#include "WormHelperFunctions.generated.h"

//Given a position in the world, returns [row][column]ID inside the GridSlotsOccupiedMap grid.
//FVector(0.f,0.f,0.f) is the center inside the 2D Array, the 2DArray is expected to have and ODD number of elements.
UFUNCTION(BlueprintPure, Category = "Grid")
void WorldLocationToGridID(AWormGameMode* GameMode, FVector Location, int& Row, int& Column)
{
	int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
	int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
	int GridBlockSize = GameMode->GridBlockSize;
	//------------------------------------------

	Row = -Location.Z / GridBlockSize + RowMiddleID;
	Column = Location.X / GridBlockSize + ColumnMiddleID;
}


//Display red wireframe cubes at the occupied position in the grid marked inside GridSlotsOccupiedMap
UFUNCTION(BlueprintCallable, Category = "Debug")
void DebugMarkOccupiedBlocks(AWormGameMode* GameMode)
{
	TArray<TArrayBool> GridSlotsOccupiedMap = GameMode->GetGridSlotsOccupiedMap();
	int GridWidth = GameMode->GridWidth;
	int GridHeight = GameMode->GridHeight;
	int GridBlockSize = GameMode->GridBlockSize;
	int XMiddleID = (GridWidth / GridBlockSize) / 2;
	int YMiddleID = (GridHeight / GridBlockSize) / 2;
	//-----------------------------------------------

	for (int row = 0; row < GridSlotsOccupiedMap.Num(); row++)
	{

		for (int column = 0; column < GridSlotsOccupiedMap[0].BoolRow.Num(); column++)
		{
			float X = (-XMiddleID + column) * GridBlockSize;
			float Z = (YMiddleID - row) * GridBlockSize;
			FVector Center = FVector(X, 50.f, Z + GridBlockSize/2);

			if (GridSlotsOccupiedMap[row][column])
			{
				UE_LOG(LogTemp, Warning, TEXT("Block[%i][%i] is occupied"), row, column)
					UKismetSystemLibrary::DrawDebugBox(GetWorld(),
													   Center, FVector(5.7f, 5.7f, 5.7f),
													   FColor::Red, FRotator::ZeroRotator, 0.f, 0);
			}
		}
	}
}

I am also including this from the player class file generated by Unreal Editor, with #include "WormHelperFunctions.h"

Errors:

Quote

CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(5) : fatal error C1083: Non ? possibile aprire il file inclusione: 'WormHelperFunctions.generated.h': No such file or directory
CompilerResultsLog: Error: z:\asus\documenti\unreal projects\worm\source\worm\WormHelperFunctions.h(5) : fatal error C1083: Non ? possibile aprire il file inclusione: 'WormHelperFunctions.generated.h': No such file or directory
CompilerResultsLog: ERROR: UBT ERROR: Failed to produce item: Z:\Asus\Documenti\Unreal Projects\Worm\Binaries\Win64\UE4Editor-Worm-7380.dll

This seems to be the important point:

fatal error C1083:  'WormHelperFunctions.generated.h': No such file or directory

I don't know where I am fucking up, I am including it even though it doesn't exist, but isn't Unreal supposed to create it when I compile? What am I doing wrong? x_x

If a definition is in a header file it should be marked with the inline keyword. You should avoid putting definitions in a header in general however except when necessary (eg. templates). Try separating the definitions into a .cpp file and only make declarations in the header.

I tried that, didn't solved the problem :/

Still missing a .generated.h, which I believe is needed, according to what I've readed online.

Maybe I should actually re-formulated my initial question, without starting from that assumption that this can work:

Is it possible from Visual Studio to create a .h and .cpp files that contains a collection of functions that I can then use inside all of my Blueprint inside the Blueprint Editor? 

Something like the base nodes you get inside a blueprint that are common/shared to all the blueprints.

Can I make this same thing but with functions made by me?

Solved it! :D

The solution is to created this class as well inside the engine and inherit from UBlueprintFunctionLibrary, and let the engine sort it out xD

The code I've below works (the second function at least, the first one crashes for different reason, because I'm somehow fucking up with casts...)

But keep reading below, I have a new question xD

WormHelperFunctions.h


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Classes/Kismet/KismetSystemLibrary.h"
#include "WormGameMode.h"
#include "WormHelperFunctions.generated.h"

/**
 *
 */
UCLASS()
class WORM_API UWormHelperFunctions : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

		//Given a position in the world, returns [row][column]ID inside the GridSlotsOccupiedMap grid.
		//FVector(0.f,0.f,0.f) is the center inside the 2D Array, the 2DArray is expected to have and ODD number of elements.
		UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Grid", meta = (WorldContext = "WorldContextObject"))
		static void WorldLocationToGridID(UObject* WorldContextObject, FVector Location, int& Row, int& Column);

	
	//Display red wireframe cubes at the occupied position in the grid marked inside GridSlotsOccupiedMap
	UFUNCTION(BlueprintCallable, Category = "Debug", meta = (WorldContext = "WorldContextObject"))
		static void DebugMarkOccupiedBlocks(AWormGameMode* GameMode, UObject* WorldContextObject);
		
};

WormHelper.Functions.cpp


// Fill out your copyright notice in the Description page of Project Settings.

#include "WormHelperFunctions.h"
#include "Engine/World.h"

void UWormHelperFunctions::WorldLocationToGridID(UObject* WorldContextObject, FVector Location, int& Row, int& Column)
{
	//UWorld* World = (UWorld*)WorldContextObject;
	//AWormGameMode* GameMode = static_cast<AWormGameMode*>(World->GetAuthGameMode());
	//int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
	//int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
	//int GridBlockSize = GameMode->GridBlockSize;
	//------------------------------------------

	//Row = -Location.Z / GridBlockSize + RowMiddleID;
	//Column = Location.X / GridBlockSize + ColumnMiddleID;
}



void UWormHelperFunctions::DebugMarkOccupiedBlocks(AWormGameMode* GameMode, UObject* WorldContextObject)
{
	TArray<TArrayBool> GridSlotsOccupiedMap = GameMode->GetGridSlotsOccupiedMap();
	int GridWidth = GameMode->GridWidth;
	int GridHeight = GameMode->GridHeight;
	int GridBlockSize = GameMode->GridBlockSize;
	int XMiddleID = (GridWidth / GridBlockSize) / 2;
	int YMiddleID = (GridHeight / GridBlockSize) / 2;
	//-----------------------------------------------

	for (int row = 0; row < GridSlotsOccupiedMap.Num(); row++)
	{

		for (int column = 0; column < GridSlotsOccupiedMap[0].BoolRow.Num(); column++)
		{
			float X = (-XMiddleID + column) * GridBlockSize;
			float Z = (YMiddleID - row) * GridBlockSize;
			FVector Center = FVector(X, 50.f, Z + GridBlockSize / 2);

			if (GridSlotsOccupiedMap[row][column])
			{
				UE_LOG(LogTemp, Warning, TEXT("Block[%i][%i] is occupied"), row, column)
					UKismetSystemLibrary::DrawDebugBox(WorldContextObject->GetWorld(),
													   Center, FVector(5.7f, 5.7f, 5.7f),
													   FColor::Red, FRotator::ZeroRotator, 0.f, 0);
			}
		}
	}
}

 

Ok, so now for the final question, focusing on the first function that crash everything:


void UWormHelperFunctions::WorldLocationToGridID(UObject* WorldContextObject, FVector Location, int& Row, int& Column)
{
	//UWorld* World = (UWorld*)WorldContextObject;
	//AWormGameMode* GameMode = static_cast<AWormGameMode*>(World->GetAuthGameMode());
	//int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
	//int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
	//int GridBlockSize = GameMode->GridBlockSize;
	//------------------------------------------

	//Row = -Location.Z / GridBlockSize + RowMiddleID;
	//Column = Location.X / GridBlockSize + ColumnMiddleID;
}

the first commented line is good (since I did a test using it in the second function instead of WorldContextObject->GetWorld() and it worked.

But the variable in the second commented line, if I try to access a public variable of it (like GridHeight in the line below it), the engine immediately crash. I haven't the slightest idea of why... Any guess of what is happening? :/

Btw, in the second line a AGameModeBase* is returned, and I am casting it to AWormGameMode* since my game mode class inherit from it.

The only reason it crashes during runtime and there is no compilation error is because GameMode is a NULL pointer. Put checks or debug if World or GameMode are Nulls.

you mean like this?


void UWormHelperFunctions::WorldLocationToGridID(UObject* WorldContextObject, FVector Location, int& Row, int& Column)
{
	UWorld* World = (UWorld*)WorldContextObject;
	AWormGameMode* GameMode = static_cast<AWormGameMode*>(World->GetAuthGameMode());
	if (GameMode->IsValidLowLevel())
	{
		int RowMiddleID = (GameMode->GridHeight / GameMode->GridBlockSize) / 2;
		int ColumnMiddleID = (GameMode->GridWidth / GameMode->GridBlockSize) / 2;
		int GridBlockSize = GameMode->GridBlockSize;
		------------------------------------------

		Row = -Location.Z / GridBlockSize + RowMiddleID;
		Column = Location.X / GridBlockSize + ColumnMiddleID;
	}
}

IsValidLowLevel

I've also tried the more classic "GameMode != nullptr", but still crashing :P

Different problems belong in different threads!

Don't use static_cast or C-style casts for Unreal actors. There is a Cast<> function which is more like dynamic_cast, and which will give you a nullptr if the object is of an incompatible type.

And for some reason, after being advised to check for a null pointer, your new code does not check for a null pointer.

And when something is crashing, use the debugger, find out EXACTLY where it crashes. There's no reason why you can't pinpoint the exact line.

18 minutes ago, Kylotan said:

Different problems belong in different threads!

My bad, I'll make a new one, sorry :P  

Thanks for the cast suggestion, I fixed that as well (though still crashing)

Quote

And for some reason, after being advised to check for a null pointer, your new code does not check for a null pointer.

Not sure what do you mean, the line 


if (GameMode->IsValidLowLevel())

should be taking care of that

Quote

And when something is crashing, use the debugger, find out EXACTLY where it crashes. There's no reason why you can't pinpoint the exact line.

I think I need more instructions on this point if possible, I had tried placing a break point in VS and it doesn't "talk" to UE apparently, I also tried with a break point into the blueprint and stepping trough the code but it crashes suddenly without explanation... :/

Anyway I'll make a new topic then :P

if ( GameMode->something )   is not a check for a NULL pointer. A check for a NULL pointer is exactly checking if a pointer is NULL:


 


if ( GameMode == NULL )
{
  // do NOT access GameMode
}

 

God, this message editor is driving me nuts!

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

This topic is closed to new replies.

Advertisement