the example in c++ I have:
new Games project: ThirdPerson, Blueprint, Start_Content = false, name = “RefCrashTest”
create “ClampInt”:UObject
create “ActorComp”:ActorComponent
ClampInt.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ClampInt.generated.h"
/**
* Error Checking and Clamping Int
* favors max (could add control value/enum for favor: max, min, floating)
*/
UCLASS()
class REFCRASHTEST_API UClampInt : public UObject {
GENERATED_BODY()
public:
UPROPERTY(VisibleAnywhere, Category=Clamped)
int Current;
UPROPERTY(EditAnywhere, Category=Clamped)
int Min;
UPROPERTY(EditAnywhere, Category=Clamped)
int Max=100;
UPROPERTY(VisibleAnywhere, Category=Clamped)
int Missing;
void OnInit();
void OnReset();
void IncreaseCurrent(int inRHS);
void DecreaseCurrent(int inRHS);
void IncreaseMin(int inRHS);
void DecreaseMin(int inRHS);
void IncreaseMax(int inRHS);
void DecreaseMax(int inRHS);
void OnCheck();
void WreckIt();
};
ClampInt.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ClampInt.h"
void UClampInt::OnInit() {
if (Min < Max) {
Current = Max;
Missing = 0;
}
}
void UClampInt::OnReset() {
if (Min < Max) {
Current = Min;
Missing = (Max-Min);
}
}
void UClampInt::IncreaseCurrent(int inRHS) {
if (inRHS < 0) {
inRHS *= (-1);
DecreaseCurrent(inRHS);
}
else {
OnCheck();
if (Max != Min) {
if (inRHS < Missing) {
Current += inRHS;
Missing -= inRHS;
}
else {
Current = Max;
Missing = 0;
}
}
}
}
void UClampInt::DecreaseCurrent(int inRHS) {
if (inRHS < 0) {
inRHS *= (-1);
IncreaseCurrent(inRHS);
}
else {
OnCheck();
if (Max != Min) {
if (inRHS < Current) {
Current -= inRHS;
Missing += inRHS;
}
else {
Current = Min;
Missing = Max;
}
}
}
}
void UClampInt::IncreaseMin(int inRHS) {
if (inRHS < 0) {
inRHS *= (-1);
DecreaseMin(inRHS);
}
else {
OnCheck();
if (Max != Min) {
Min += inRHS;
if (Min >= Max) {
Current = Max = Min;
Missing = 0;
}
else {
Current += inRHS;
if (Current > Max) {
Current = Max;
}
Missing = Max - Current;
}
}
}
}
void UClampInt::DecreaseMin(int inRHS) {
if (inRHS < 0) {
inRHS *= (-1);
IncreaseMin(inRHS);
}
else {
OnCheck();
if (Max != Min) {
Min -= inRHS;
}
}
}
void UClampInt::IncreaseMax(int inRHS) {
if (inRHS < 0) {
inRHS *= (-1);
DecreaseMax(inRHS);
}
else {
OnCheck();
if (Max != Min) {
Max += inRHS;
Current += inRHS;
}
}
}
void UClampInt::DecreaseMax(int inRHS) {
if (inRHS < 0) {
inRHS *= (-1);
IncreaseMax(inRHS);
}
else {
OnCheck();
if (Max != Min) {
Max -= inRHS;
if (Max > Min) {
if (Current > Max) {
Current = Max;
Missing = 0;
}
else {
Missing = Max - Current;
}
}
else if (Max == Min) {
Current = Min;
Missing = 0;
}
else {
Max = Current = Min;
Missing = 0;
}
}
}
}
void UClampInt::OnCheck() {
if (!(Current > Min) && !(Current < Max)) {
OnReset();
}
if ((Current + Missing) != Max) {
OnReset();
}
}
void UClampInt::WreckIt(){
Current = Max * 2;
}
ActorComp.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "ClampInt.h"
#include "ActorComp.generated.h"
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class REFCRASHTEST_API UActorComp : public UActorComponent {
GENERATED_BODY()
public:
UPROPERTY(Instanced, EditAnywhere, Category = GameTest)
TObjectPtr<UClampInt> ClampedInt;
// Sets default values for this component's properties
UActorComp();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
UFUNCTION(BlueprintCallable)
void IncreaseMax(int inVal);
UFUNCTION(BlueprintCallable)
void DecreaseMax(int inVal);
UFUNCTION(BlueprintCallable)
void IncreaseMin(int inVal);
UFUNCTION(BlueprintCallable)
void DecreaseMin(int inVal);
UFUNCTION(BlueprintCallable)
void IncreaseCurrent(int inVal);
UFUNCTION(BlueprintCallable)
void DecreaseCurrent(int inVal);
UFUNCTION(BlueprintCallable)
void WreckIt();
void ResetObject();
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
};
ActorComp.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ActorComp.h"
// Sets default values for this component's properties
UActorComp::UActorComp() {
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
ClampedInt = NewObject<UClampInt>();
// ...
}
// Called when the game starts
void UActorComp::BeginPlay() {
Super::BeginPlay();
ClampedInt->OnInit();
}
void UActorComp::IncreaseMax(int inVal) { ClampedInt->IncreaseMax(inVal); }
void UActorComp::DecreaseMax(int inVal) { ClampedInt->DecreaseMax(inVal); }
void UActorComp::IncreaseMin(int inVal) { ClampedInt->IncreaseMin(inVal); }
void UActorComp::DecreaseMin(int inVal) { ClampedInt->DecreaseMin(inVal); }
void UActorComp::IncreaseCurrent(int inVal) { ClampedInt->IncreaseCurrent(inVal); }
void UActorComp::DecreaseCurrent(int inVal) { ClampedInt->DecreaseCurrent(inVal); }
void UActorComp::WreckIt() { ClampedInt->WreckIt(); }
void UActorComp::ResetObject() { ClampedInt->OnReset(); }
// Called every frame
void UActorComp::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) {
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// ...
}
Build in VS to Luanch Editor
Create an InputAction “IA_Debug” with Digital Bool
in IMC_Default assign “IA_Debug” to “Num0” (or the key of your choice)
in BP_ThirdPersonCharacter
in Blueprint editor: “+Add”->ActorComp to Components hierarchy
when selected Details “Game Test” {should be under Sockets} which should have a “Clamped Int” with an expandable of “ClampInt” and another expandable for the 4 ints
making sure Max is 100
create IA_Debug event
drag the “ActorComp” component into the graph
extend out the output pin (as long as “context sensitive” is true most of the nodes will come from this) to get
Save and Compile the Blueprint
Run Game, and trigger the IA_Debug event
you can find the values during Play in the Outliner-> BP_ThirdPersonCharacter0 in details select ActorComp in details section at the top is “Game Test”
final values should be 10, 10, 100, 0
the last values in the Play session are also now the values in the Blueprint
Save all and Exit
Exit Editor
re-open editor through VS
re-open BP_ThirdPersonCharacter (if you didn’t close it then there should be a notification asking if you want to re-open it anyways)
the ActorComp:actorComponent now has its ClampedInt set to None the only way I have found to get it back is to create a new instance of the ActorComp in the Hierarchy which requires re-attaching all the nodes
sometimes re-building in Editor after running this blueprint script may cause the Editor to crash…
*what am I missing to make sure that the instance of ClampedInt doesn’t get set to none when exiting/opening the editor
*BlueprintType on UClampInt doesn’t seem to make a difference, and even when I try to reproduce this in pure blueprints I get similar behavior.