Calling non-static UFunction from console command

Hello there.

I’m implementing some console commands, using FAutoConsoleCommand. I’ve done some Exec functions before, but, since it’s already deprecated, I started to use the former.

This is the code I’m using to register my command in my UCheatManager, which does work.


FAutoConsoleCommand CSetHeroStamina(
    TEXT("C2.SetHeroStamina"),
    TEXT("Sets hero stamina percentage
")
    TEXT("    0: Deplete")
    TEXT("    1: Refill"),
    FConsoleCommandWithArgsDelegate::CreateStatic(&CSetHeroStaminaExecuted),
    ECVF_Cheat);

The thing is, CSetHeroStaminaExecuted is a static function, but I need to call a non-static Blueprint-implementable function. How can I bind that UFunction to the console command, or retrieve the World to get to my PlayerController’s cheat manager, cast it and call my UFunction? GEngine->GetWorld() seems to be returning nullptr always. I’m aware there’s this FConsoleCommandWithArgsDelegate::BindUFunction(), but I’m not sure how to pass the WorldContext object it needs to do the binding.

Thanks in advance.

GEngine->GetWorld shouldn’t be returning null. That seems off. You could store a static pointer to your Hero (assuming there’s only one) on your game mode and then create a static method to grab it. Basically use a singleton-esque model.




class AMyGameMode : public AGameMode
{
   static void SetActiveHero(AActor* MyHero) { s_MyHeroPtr = MyHero; }
   static AActor* GetActiveHero() { check(s_MyHeroPtr.isValid()); return s_MyHeroPtr.Get(); }

// ...
private:
  static TWeakObjectPtr<AActor> s_MyHeroPtr;
}



Then when your Hero is created, simply call AMyGameMode::SetActiveHero, and in your Console method you can call AMyGameMode::GetActiveHero.

Or figure out why GEngine is returning a null world and go about things that way.

Thanks for your reply, Matt.

Turns out I had an epiphany and decided to store a static pointer to the world itself in the constructor of my CheatManager*.*


UCSCheatManager::UCSCheatManager()
{
    UCSCheatManager::world = GetWorld();

    if (UCSCheatManager::world != nullptr)
    {
        UE_LOG(LogClass, Log, TEXT("Found a valid world"));
    }
}

It does work and I’m able to call non-static functions from my manager, but again, is it there a “proper” way to do it? According to this (unless my english is that bad, as it’s not my native language), it shouldn’t be accessed in a constructor.

https://answers.unrealengine.com/questions/529349/gengine-getworld-return-null.html

OK, going with Matt’s suggestion and my previous workaround, what I did was to create a singleton-esque static reference to my cheat manager. Seems to do what I need, but still, it’d be great to have better documentation on FAutoConsoleCommand, specially on binding events. Console Manager section of the manual only gives details about console vars. Hope the Shooter project has something like this.

You can use FAutoConsoleCommandWithWorldAndArgs to get access to the world.

So, I forgot I put this thread.

In the end, my solution was to create a static instance for my cheat manager, then call the non-static function from that static instance when using FAutoConsoleCommand.

Thanks, everyone.