Hey Everyone!
I’m having a few issues getting to grasps with the HUD system in UE4.
My current setup is based off of a BluePrinted GameMode Class, which has BluePrinted versions of my custom HUD and PlayerController. (ScreenCap is in the attachments).
Somewhat based off of the HUD tutorial on the UE4 Wiki.
Although, even though I’m having successful builds I can’t get my HUD to work for the life of me.
What I wanted to recreate was an object orientated version of Unity’s OnGUI system, so I could have buttons, boxes, sliders, etc,
all managing there own internal variables, and weren’t being re-instantiated on every DrawHUD call.
For some reason my Client messages won’t work, even though I’m using “ThePC->ClientMessage()”.
My problem is either, I’m being stupid and not creating my objects properly in the HUD class, or I’m not correctly accessing my PC class/BP.
Is there some kind of global debug “`Log()” system like there was in UDK?
My Issues:
- I need to find out why I can’t debug log like I need to…
- I need the above to find out what’s going on in my HUD script
- How do I make my material in HUDObjects an instantiate object, rather than a pointer of a pointer of a point?
- Am I passed a HUD reference correctly into my DrawBackground Function?
- After I created a new class derived from UObject, my compile times shot up to like 130+ seconds, any ideas why? (I think it has something to do with so many header referencing back and forth… but I’m not sure)
Any and all help will be immensely helpful!
I love going all out in Unreal Engines, and the amount of custom systems I made for myself and my team in UDK was just so much fun.
Learning my problems here and the solutions would help me such a long way.
Thanks!
Here’s my project so far!
**SSPlayerController.h
**
#pragma once
//Input
#include "InputCoreTypes.h"
#include "GameFramework/PlayerController.h"
#include "SSPlayerController.generated.h"
UCLASS()
class ASSPlayerController : public APlayerController
{
GENERATED_UCLASS_BODY()
};
**SSPlayerController.cpp
**
#include "SleepStep.h"
#include "SSPlayerController.h"
ASSPlayerController::ASSPlayerController(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
}//Constructor
**SSGameMode.h
**
#pragma once
#include "GameFramework/GameMode.h"
#include "SSGameMode.generated.h"
UCLASS()
class ASSGameMode : public AGameMode
{
GENERATED_UCLASS_BODY()
};
**SSGameMode.cpp
**
#include "SleepStep.h"
#include "SSGameMode.h"
#include "SSPlayerController.h"
#include "SSHUD.h"
ASSGameMode::ASSGameMode(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
//Backup PC Class
PlayerControllerClass = ASSPlayerController::StaticClass();
//BP Referenced version of our PC Class
static ConstructorHelpers::FObjectFinder<UBlueprint> VictoryPCOb(TEXT("Blueprint'/Game/Blueprints/BL_SSPlayerController.BL_SSPlayerController'"));
//If the referenced PC class BP isn't null
if (VictoryPCOb.Object != NULL)
{
//Set our PC class as the BP object
PlayerControllerClass = (UClass*)VictoryPCOb.Object->GeneratedClass;
}//if
//Backup HUD Class
HUDClass = ASSHUD::StaticClass();
//BP Referenced version of our HUD Class
static ConstructorHelpers::FObjectFinder<UBlueprint> VictoryHUDOb(TEXT("Blueprint'/Game/Blueprints/BL_SSHUD.BL_SSHUD'"));
//If the referenced HUD class BP isn't null
if (VictoryHUDOb.Object != NULL)
{
//Set our HUD class as the BP object
HUDClass = (UClass*)VictoryHUDOb.Object->GeneratedClass;
}//if
}//Constructor
**SSHUD.h
**
#pragma once
#include "GameFramework/HUD.h"
#include "SSPlayerController.h"
#include "HUDObjects.h"
#include "SSHUD.generated.h"
UENUM()
namespace GAMESTATE
{
enum Type
{
GamePlay,
Cinematic,
Paused,
};
}
UENUM()
namespace HUDSTATE
{
enum Type
{
Standard,
Options,
Audio,
Graphics,
GraphicsAdv,
Exit,
};
}
UCLASS()
class ASSHUD : public AHUD
{
GENERATED_UCLASS_BODY()
// Infiltrace
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SSHUD)
UFont* InfiltraceFont;
// Font scale
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SSHUD)
float DefaultFontScale;
// Materials
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Materials)
UMaterialInterface* MaterialBackground;
// Draw Hud?
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Options)
bool NoHUD;
//Scaling
float CenterHorizontal(float Width);
float CenterVertical(float Height);
float ScaleWidth(float Width);
float ScaleHeight(float Height);
//Core
public:
APlayerController* ThePC;
ASSPlayerController* SSPC;
TEnumAsByte<GAMESTATE::Type> HudState;
TEnumAsByte<HUDSTATE::Type> PausedState;
//PauseMenu
UHUDObjects* ResumeButton;
UHUDObjects* OptionsButton;
UHUDObjects* QuitButton;
//Screen Sizes
float SizeX;
float SizeY;
protected:
//SetUp
void SetUpLabels();
void SetUpTextures();
void SetUpAnims();
void SetUpButtons();
//Draw HUD
virtual void DrawHUD() OVERRIDE;
/** after all game elements are created */
virtual void PostInitializeComponents() OVERRIDE;
};
**SSHUD.cpp
**
#include "SleepStep.h"
#include "SSHUD.h"
ASSHUD::ASSHUD(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{
//Draw HUD?
NoHUD = false;
//Scale
DefaultFontScale = 0.7;
//Default Screen Size
SizeX = 1920;
SizeY = 1080;
//States of the HUD and pause menu
HudState = GAMESTATE::GamePlay;
PausedState = HUDSTATE::Standard;
//Set up buttons in a similar format to OnGUI from Unity
SetUpButtons();
}//Constructor
void ASSHUD::SetUpButtons()
{
//Instantiate new object and assign reference to the pointer
ResumeButton = NewObject<UHUDObjects>();
//If the pointer has an object
if (ResumeButton != NULL)
{
//Set up the HUD Object
ResumeButton->Init(ObjectType::Button, MaterialBackground, CenterHorizontal(50), ScaleHeight(100), ScaleWidth(50), ScaleHeight(50), 1);
}//if
}//SetUpButtons
float ASSHUD::ScaleWidth(float Width)
{
return (Width / 1920)*SizeX;
}///Scale Width
float ASSHUD::CenterHorizontal(float Width)
{
return (SizeX / 2) - (ScaleWidth(Width) / 2);
}//CenterHorizontal
float ASSHUD::ScaleHeight(float Height)
{
return (Height / 1920)*SizeY;
}//ScaleHeight
float ASSHUD::CenterVertical(float Height)
{
return (SizeY / 2) - (ScaleHeight(Height) / 2);
}//CenterVertical
//Core
void ASSHUD::PostInitializeComponents()
{
Super::PostInitializeComponents();
//Grab the PC
ThePC = GetOwningPlayerController();
//If the PC isn't null
if (ThePC != NULL)
{
//Grab the custom player controller
ASSPlayerController* YourChar = Cast<ASSPlayerController>(ThePC);
//If the custom controller isn't null
if (YourChar != NULL)
{
//Set it to the global var
SSPC = YourChar;
}//if
}//if
//How to Get The Character
//ASSCharacterClass* YourChar = Cast<ASSCharacterClass>(GetOwningPawn());
}//PostInitializeComponents
void ASSHUD::DrawHUD()
{
//If the PC is NULL
if (!ThePC)
{
//Try to get the PC
ThePC = GetOwningPlayerController();
//If there still isn't a PC, then return
if (!ThePC) return;
}//if
//Check that the PC's input exists, otherwise, return
if (!ThePC->PlayerInput) return;
//Draw HUD?
if (NoHUD) return;
//Super
Super::DrawHUD();
//No Canvas?
if (!Canvas) return;
//Assign the canvas sizes to the global vars for use outside of DrawHUD
SizeX = Canvas->SizeX;
SizeY = Canvas->SizeY;
//Debug logging the canvas is working
ThePC->ClientMessage("Canvas Working");
//If the button pointer isn't null
if (ResumeButton != NULL)
{
//Debug logging the object is working
ThePC->ClientMessage("Object Working");
//Pass this hud to the button
ResumeButton->DrawBackground(this);
}//if
}//DrawHUD
**HudObjects.h
**
#pragma once
#include "GameFramework/HUD.h"
#include "HUDObjects.generated.h"
UENUM()
namespace ObjectType
{
enum Type
{
Button,
Anim,
};
}
USTRUCT()
struct FShapeStruct
{
GENERATED_USTRUCT_BODY()
//Vars
float x;
float y;
float w;
float h;
//default properties
FShapeStruct()
{
x = 0;
y = 0;
w = 0;
h = 0;
}
};
UCLASS()
class UHUDObjects : public UObject
{
GENERATED_UCLASS_BODY()
//State handler
TEnumAsByte<ObjectType::Type> objType;
//Shape and positioning of this object
FShapeStruct ShapeAndPos;
//This object's backgroun material reference
UMaterialInterface* BackGround;
//Scale of the text
float ScaleAmount;
//Functions
public:
bool CheckInside(FSHVector2 MousePos);
void DrawBackground(AHUD* HUDRef);
void Init(TEnumAsByte<ObjectType::Type> Type, UMaterialInterface* BackgroundMaterial, float x, float y, float w, float h, float Scale);
};
**HUDObjects.cpp
**
#include "SleepStep.h"
#include "HUDObjects.h"
UHUDObjects::UHUDObjects(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
{}
void UHUDObjects::Init(TEnumAsByte<ObjectType::Type> Type, UMaterialInterface* BackgroundMaterial, float x, float y, float w, float h, float Scale)
{
//Initialise global variables with passed parameters
objType = Type;
ShapeAndPos.x = x;
ShapeAndPos.y = y;
ShapeAndPos.w = w;
ShapeAndPos.h = h;
ScaleAmount = Scale;
//This material pointer is assigned as another pointer isn't it?
//So how would I make is it's own dynamic instance?
BackGround = BackgroundMaterial;
}//Init
bool UHUDObjects::CheckInside(FSHVector2 MousePos)
{
//This will be used to check if the cursor is inside it
return false;
}//CheckInside
void UHUDObjects::DrawBackground(AHUD* HUDRef)
{
//If the BG material reference isn't null, and the passed HUD isn't null
if (BackGround != NULL && HUDRef != NULL)
{
//Draw the material as assigned
HUDRef->DrawMaterialSimple(BackGround, ShapeAndPos.x, ShapeAndPos.y, ShapeAndPos.w, ShapeAndPos.h, ScaleAmount, false);
}//If
}//DrawBackground
Sorry about the size guys, but I’m new to C++ for the most part… And I’m still trying to get my head around proper pointer referencing, etc,
so posting it all was really my best option for avoiding any ambiguity with you guys trying to help me!
-