Jump to content
  • Advertisement
MarcusAseth

How to #include my own header into the game?

Recommended Posts

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... :|

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
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

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

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.

Edited by cmac

Share this post


Link to post
Share on other sites

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?

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

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.

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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

Edited by MarcusAseth

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites

  • Advertisement
  • Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By Stalefish
      Automated builds are a pretty important tool in a game developer's toolbox. If you're only testing your Unreal-based game in the editor (even in standalone mode), you're in for a rude awakening when new bugs pop up in a shipping build that you've never encountered before. You also don't want to manually package your game from the editor every time you want to test said shipping build, or to distribute it to your testers (or Steam for that matter).
      Unreal already provides a pretty robust build system, and it's very easy to use it in combination with build automation tools. My build system of choice is  Gradle , since I use it pretty extensively in my backend Java and Scala work. It's pretty easy to learn, runs everywhere, and gives you a lot of powerful functionality right out of the gate. This won't be a Gradle tutorial necessarily, so you can familiarize yourself with how Gradle works via the documentation on their site.
      Primarily, I use Gradle to manage a version file in my game's Git repository, which is compiled into the game so that I have version information in Blueprint and C++ logic. I use that version to prevent out-of-date clients from connecting to newer servers, and having the version compiled in makes it a little more difficult for malicious clients to spoof that build number, as opposed to having it stored in one of the INI files. I also use Gradle to automate uploading my client build to Steam via the use of steamcmd.
      Unreal's command line build tool is known as the Unreal Automation Tool. Any time you package from the editor, or use the Unreal Frontend Tool, you're using UAT on the back end. Epic provides handy scripts in the Engine/Build/BatchFiles directory to make use of UAT from the command line, namely RunUAT.bat. Since it's just a batch file, I can call it from a Gradle build script very easily.
      Here's the Gradle task snippet I use to package and archive my client:
      task packageClientUAT(type: Exec) { workingDir = "[UnrealEngineDir]\\Engine\\Build\\BatchFiles" def projectDirSafe = project.projectDir.toString().replaceAll(/[\\]/) { m -> "\\\\" } def archiveDir = projectDirSafe + "\\\\Archive\\\\Client" def archiveDirFile = new File(archiveDir) if(!archiveDirFile.exists() && !archiveDirFile.mkdirs()) { throw new Exception("Could not create client archive directory.") } if(!new File(archiveDir + "\\\\WindowsClient").deleteDir()) { throw new Exception("Could not delete final client directory.") } commandLine "cmd", "/c", "RunUAT", "BuildCookRun", "-project=\"" + projectDirSafe + "\\\\[ProjectName].uproject\"", "-noP4", "-platform=Win64", "-clientconfig=Development", "-serverconfig=Development", "-cook", "-allmaps", "-build", "-stage", "-pak", "-archive", "-noeditor", "-archivedirectory=\"" + archiveDir + "\"" } My build.gradle file is in my project's directory, alongside the uproject file. This snippet will spit the packaged client out into [ProjectDir]\Archive\Client.
      For the versioning, I have two files that Gradle directly modifies. The first, a simple text file, just has a number in it. In my [ProjectName]\Source\[ProjectName] folder, I have a [ProjectName]Build.txt file with the current build number in it. Additionally, in that same folder, I have a C++ header file with the following in it:
      #pragma once #define [PROJECT]_MAJOR_VERSION 0 #define [PROJECT]_MINOR_VERSION 1 #define [PROJECT]_BUILD_NUMBER ### #define [PROJECT]_BUILD_STAGE "Pre-Alpha" Here's my Gradle task that increments the build number in that text file, and then replaces the value in the header file:
      task incrementVersion { doLast { def version = 0 def ProjectName = "[ProjectName]" def vfile = new File("Source\\" + ProjectName + "\\" + ProjectName + "Build.txt") if(vfile.exists()) { String versionContents = vfile.text version = Integer.parseInt(versionContents) } version += 1 vfile.text = version vfile = new File("Source\\" + ProjectName + "\\" + ProjectName + "Version.h") if(vfile.exists()) { String pname = ProjectName.toUpperCase() String versionContents = vfile.text versionContents = versionContents.replaceAll(/_BUILD_NUMBER ([0-9]+)/) { m -> "_BUILD_NUMBER " + version } vfile.text = versionContents } } } I manually edit the major and minor versions and the build stage as needed, since they don't need to update with every build. You can include that header into any C++ file that needs to know the build number, and I also have a few static methods in my game's Blueprint static library that wrap them so I can get the version numbers in Blueprint.
      I also have some tasks for automatically checking those files into the Git repository and committing them:
      task prepareVersion(type: Exec) { workingDir = project.projectDir.toString() commandLine "cmd", "/c", "git", "reset" } task stageVersion(type: Exec, dependsOn: prepareVersion) { workingDir = project.projectDir.toString() commandLine "cmd", "/c", "git", "add", project.projectDir.toString() + "\\Source\\[ProjectName]\\[ProjectName]Build.txt", project.projectDir.toString() + "\\Source\\[ProjectName]\\[ProjectName]Version.h" } task commitVersion(type: Exec, dependsOn: stageVersion) { workingDir = project.projectDir.toString() commandLine "cmd", "/c", "git", "commit", "-m", "\"Incrementing [ProjectName] version\"" } And here's the task I use to actually push it to Steam:
      task pushBuildSteam(type: Exec) { doFirst { println "Pushing build to Steam..." } workingDir = "[SteamworksDir]\\sdk\\tools\\ContentBuilder" commandLine "cmd", "/c", "builder\\steamcmd.exe", "+set_steam_guard_code", "[steam_guard_code]", "+login", "\"[username]\"", "\"[password]\"", "+run_app_build", "..\\scripts\\[CorrectVDFFile].vdf", "+quit" } You can also spit out a generated VDF file with the build number in the build's description so that it'll show up in SteamPipe. I have a single Gradle task I run that increments the build number, checks in those version files, packages both the client and server, and then uploads the packaged client to Steam. Another great thing about Gradle is that Jenkins has a solid plugin for it, so you can use Jenkins to set up a nice continuous integration pipeline for your game to push builds out regularly, which you absolutely should do if you're working with a team.
    • By MoreLion
      Hey all! we are a team of 7 looking for a game designer, im a game designer but need help as i am doing multiple things at once, the game is being developed in UE4.
      the game is a futuristic action adventure game where you play as a 21 year old female who has woken up in a simulation not knowing who or where she is, but when all is unfolding the simulation gets hacked leaving eveline with no choice but to escape before she is killed inside the simulation.
      we are also looking for other members aswell wether you be a animator a ue4 game developer or that just email me below.
      if interested email liondude12@gmail.com
    • By nihitori
      This is the official Sales topic for the acclaimed Colossal Game Music Collection (100+ five-star ratings on the Unity Asset Store) and its Lite version, the Essential Game Music Collection.

      Updates will be made here every time a sale is taking place on either the Unity Asset Store or the Unreal Engine Marketplace.

      Current Sales:

      Version 2.0 Intro Sale on the Unreal Engine Marketplace -

      - Colossal Game Music Collection at 50% OFF - https://www.unrealengine.com/marketplace/colossal-game-music-collection


      Please feel free to post here any questions you might have about either the sales or the collection itself.
    • By CountBram
      Hello I am looking for advice to what I should do next as I just completed the Unreal Developer Course on Udemy and now am at a lost as what to do farther as practice and to expand my knowledge. My background is 2 years studying college in Videogame Design and 3 years working on 4 years studying Software Engineering in college. I am mainly focusing on using my C++ knowledge with Unreal Engine to make indie games but I do also know Java, and C# as well, but I do not know Unity. I am welcoming any advice that can help with my current situation with my current skill set
    • By Silverlan
      As I understand it, you're supposed to use Unreal's Online Subsystem when doing anything with the Steam SDK. However, when I look into the available interfaces (Engine/Plugins/Online/OnlineSubsystem/Source/Public/Interfaces), there doesn't seem to be a controller interface. Does Unreal not have that (yet)?
      If so, do I have to link against the steamworks libraries manually and use the SDK directly?
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!