Custom game instance

So I created a custom Game Instance and I am trying to utilize it elsewhere. It fails to compile. I’m not sure if I have not set up my Game Instance correctly, or if my attempt to use it elsewhere was wrong. For reference, I am working off of the PuzzleGrid C++ example using UE 4.7.6.

The compile error:


Error D:\Programs\Epic Games\4.7\Engine\Source\Runtime\CoreUObject\Public\Templates\Casts.h(135)  : error C2664: 'BCInstance *TCastImpl<From,To,UObjectToUObject>::DoCast(UObject *)' : cannot convert argument 1 from 'UGameInstance *' to 'UObject *'
Info         with
Info         
Info             From=UGameInstance
Info ,            To=BCInstance
Info         ]
Info         Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Info          D:\Unreal\BalloonCollector\Source\BalloonCollector\BalloonCollectorBlockGrid.cpp(26)  : see reference to function template instantiation 'To *Cast<BCInstance,UGameInstance>(From *)' being compiled
Info         with
Info         
Info             To=BCInstance
Info ,            From=UGameInstance
Info         ]
Info BCInstance.cpp

Instance CPP


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

#include "BalloonCollector.h"
#include "BCInstance.h"

BCInstance::BCInstance()
{
	// 0 = Mansion, 1 = park
	view = 0;

	struct FConstructorStatics
	{
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> TileMesh;
		ConstructorHelpers::FObjectFinderOptional<UMaterialInstance> ParkTileMaterial;
		ConstructorHelpers::FObjectFinderOptional<UStaticMesh> ParkBenchMesh;
		ConstructorHelpers::FObjectFinderOptional<UMaterialInstance> ParkBenchMaterial;
		FConstructorStatics()
			: TileMesh(TEXT("/Game/Park/Mesh/tilerounded_ao.tilerounded_ao"))
			, ParkTileMaterial(TEXT("/Game/Park/Material/MI_Tile_Park.MI_Tile_Park"))
			, ParkBenchMesh(TEXT("/Game/Park/Mesh/bench_ao.bench_ao"))
			, ParkBenchMaterial(TEXT("/Game/Park/Material/MI_Bench.MI_Bench"))
		{
		}
	};
	static FConstructorStatics cs;

	TileMesh = cs.TileMesh.Get();
	ParkTileMaterial = cs.ParkTileMaterial.Get();
}

BCInstance::~BCInstance()
{
}

Instance header


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

#pragma once

class BALLOONCOLLECTOR_API BCInstance
{
public:
	int view;

	class UStaticMesh* TileMesh;
	class UMaterialInstance* ParkTileMaterial;

	BCInstance();
	~BCInstance();
};

Segment of file attempting to utilize the Game Instance


void ABalloonCollectorBlockGrid::BeginPlay()
{
	Super::BeginPlay();

	BCInstance* gi = Cast<BCInstance>(GetGameInstance());

	// Number of blocks
	const int32 NumBlocks = Size * Size;

	// Loop to spawn each block
	for(int32 BlockIndex=0; BlockIndex<NumBlocks; BlockIndex++)
	{
		const float XOffset = (BlockIndex/Size) * BlockSpacing; // Divide by dimension
		const float YOffset = (BlockIndex%Size) * BlockSpacing; // Modulo gives remainder

		// Make postion vector, offset from Grid location
		const FVector BlockLocation = FVector(XOffset, YOffset, 0.f) + GetActorLocation();

		// Spawn a block
		ABalloonCollectorBlock* NewBlock = GetWorld()->SpawnActor<ABalloonCollectorBlock>(BlockLocation, FRotator(0,0,0));

		// Tell the block about its owner
		if(NewBlock != NULL)
		{
			NewBlock->OwningGrid = this;
			NewBlock->BlockMesh->SetStaticMesh(gi->TileMesh);
			NewBlock->BlockMesh->SetMaterial(0, gi->ParkTileMaterial);
		}
	}
}

Sorry if this problem seems simple, I am a novice!

It looks like you’re trying to cast your BCInstance class to a class that BCInstance does not inherit/is not a child of.

Your BCInstance should be a child of UGameInstance, otherwise it won’t work.

Ok well I made some changes. First, renaming it UBCInstance from BCInstance. Secondly, inheriting from UGameInstance. And might I add… what’s the point of selecting the class “UGameInstance” in the Add code to project wizard if it doesn’t actually do anything?


#pragma once

#include "Engine/GameInstance.h"

UCLASS()
class UBCInstance : public UGameInstance
{
	//GENERATED_UCLASS_BODY()
public:
	int view;

	class UStaticMesh* TileMesh;
	class UMaterialInstance* ParkTileMaterial;

	UBCInstance();
};

This gives the error “error : In BCInstance: Expected a GENERATED_UCLASS_BODY() at the start of class D:\Unreal\BalloonCollector\Source\BalloonCollector\BCInstance.h 21”

If I uncomment that line, it gives the error “IntelliSense: expected a ‘)’ d:\Unreal\BalloonCollector\Source\BalloonCollector\BCInstance.h” highlighting the line.

I am confused. What does the compiler want? I tried doing from the Unreal editor File -> Refresh Visual Studio project and it still gives the same error.

You can ignore IntelliSense errors in this context, some macros are just to complex to be parsed correctly. It should compile just fine.

IntelliSense has some various errors until you compile, it should work perfectly fine however if you hit Build as it’ll do the necessary work to make that line of code work.

As for inheriting does A LOT. It’s a fundamental block actually. Whenever you inherit from a class, your new class can now do everything the class you inherited could do, plus whatever you code in. That “public UGameInstance” is telling your class how to do all of those things UGameInstance has already programmed in for you. This saves a lot of headaches and time during development.

The problem was it was not compiling correctly. I did a compile from the UE Editor and it gave a much more meaningful error: did not include generated.h file. After doing that VS no longer complained either.

That said, I have a separate, strange problem now. Utilizing the code in the BlockGrid causes the memory usage to climb until it crashes.


UBCInstance* gi = Cast<UBCInstance>(GetGameInstance());
NewBlock->BlockMesh->SetStaticMesh(gi->TileMesh);
NewBlock->BlockMesh->SetMaterial(0, gi->ParkTileMaterial);

Sounds like a run-away loop to me. Loops crash if they go on for too long. I’m not sure how many objects you are trying to loop through, but try setting your “Size” to something small ,like 4 so that you’re only working with 16 blocks (if I’m understanding the code right) and see if it still crashes. If so, that loop probably isn’t closing off.

If it works fine, then you may just have way too many objects you are trying to iterate through in a single go, and could use some optimization by splitting it up.

Literally uncommenting those lines though and it no longer presents any problems. (The problem function is the one in the original post, the last code block). The size is currently 6.

Simply commenting out


NewBlock->BlockMesh->SetStaticMesh(gi->TileMesh);
NewBlock->BlockMesh->SetMaterial(0, gi->ParkTileMaterial);

and recompiling the error does not happen.

To humor you, I set NumBlocks to 4 with the same results.

To further test that the loop in my code is not the culprit, I completely commented out the for loop only leaving one NewBlock being created and assigned anything. Problem persists.

EDIT *****
This problem is solved. I simply forgot to change the GameInstance in the project settings to my BCInstance… this seems like an odd error to result from that forgetfulness, however. Thanks for the help!