Visualize game stat in the editor's viewport

In previous postings we implemented the ability to manage game content using 'Customize Buffer Visualization' and 'TextRenderComponent'.
https://gameenginebread.blogspot.com/2017/12/customize-buffer-visualization-for-rpg.html

However, depending on the situation, it can be more convenient if the changed value is automatically applied to the 'TextRenderComponent'.

So in this post, let's create a class with 'TextRenderComponent' to use this feature.

Step 1.

We will implement a class to find the variable of the specified 'Parent(Owner) Actor' and output the value as text.
Create a 'VariableWatcherComponent' class that inherits from 'TextRenderComponent'.


Step 2.

Let's skip the long explanation and see the results. This is the final code. This code only supports numeric variables.

VariableWatcherComponent.h
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/TextRenderComponent.h"
#include "VariableWatcherComponent.generated.h"

/**
 * GameEngineBread.
 * https://gameenginebread.blogspot.com/2017/12/visualize-game-stat-in-editors-viewport.html
 */
UCLASS(ClassGroup = Game, hidecategories = (Object, LOD, Physics, TextureStreaming, Activation, "Components|Activation", Collision), editinlinenew, meta = (BlueprintSpawnableComponent = ""))
class TEST01_API UVariableWatcherComponent : public UTextRenderComponent
{
 GENERATED_BODY()
 
public:
 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=VariableWatcher)
 FString Prefix;

 /** Owner Actor's member variable name. May working only with value that created by blueprint. */
 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=VariableWatcher)
 FName MemberName;

 virtual void PostInitProperties() override;

#if WITH_EDITOR
 virtual void PostLoad();

 virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;

 void Run();
#endif // WITH_EDITOR
 
};


VariableWatcherComponent.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Fill out your copyright notice in the Description page of Project Settings.

#include "VariableWatcherComponent.h"
#include "Engine/BlueprintGeneratedClass.h"


#if WITH_EDITOR

void UVariableWatcherComponent::PostInitProperties()
{
 Super::PostInitProperties();

 bIsEditorOnly = true;
}

void UVariableWatcherComponent::PostLoad()
{
 Super::PostLoad();

 Run();
}

void UVariableWatcherComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
 Run();

 Super::PostEditChangeProperty(PropertyChangedEvent);
}

void UVariableWatcherComponent::Run()
{
 AActor* TargetActor = GetOwner();
 if (TargetActor != NULL && MemberName != NAME_None)
 {
  FString Result = TEXT("");

  UBlueprintGeneratedClass *BPC = Cast<UBlueprintGeneratedClass>(TargetActor->GetClass());
  if (BPC != NULL)
  {
   for (TFieldIterator<UProperty> It(TargetActor->GetClass()); It; ++It)
   {
    UProperty* Property = *It;

    if (Property->GetName().Equals(MemberName.ToString()))
    {
     UNumericProperty *NumProp = Cast<UNumericProperty>(Property);
     if (NumProp)
     {
      Result = Prefix + NumProp->GetNumericPropertyValueToString(Property->ContainerPtrToValuePtr<void>(TargetActor));
     }
     break;
    }
   }
  }

  SetText(Result); // Deprecated?
 }
}
#endif // WITH_EDITOR
Code highlight by http://hilite.me/


Step 3.

Let's look at a usage example.
  1. Create a Actor.
  2. Add a 'Integer' or 'float' variable.
  3. Add 'VariableWatcher' component.
  4. Assign the variable name you just added to 'MemberName'.

Step 4.

The resulting screenshot. If you change the value specified in the editor, it is immediately reflected in the 'viewport'.


More...

You will need to make more modifications for actual use. Perhaps you will need the following:
  • String variable types must also be supported.
  • Depending on your system, you may need a structure data type.
  • Depending on your system, you may need to support table data types.
  • The relevant variables must be well synchronized.

Comments

Popular posts from this blog

Liquid material in a bottle

MatCap material

How to Make Circular Progress Bar(or Rounded Rectangle)