Help us understand the problem. What is going on with this article?

VR内でOutputLogを見よう

More than 3 years have passed since last update.

Unreal Engine 4 アドベントカレンダー2016の14日目の記事です。

VR内でOutputLogを見る

VRアプリ開発で不便に思うことがあるので作ってみました。
OutputLogに出ている情報を、Blueprintから利用できるようにします。
ログをゲーム内の壁に表示してみたのがこちら↓(スクショはVRモードではないですが・・・)

console2.png

これでHMDをかぶって、モーションコントローラで操作をしながらOutputLogを確認できます。

中身の解説

C++でログにアクセスする機能を追加します。
ちょっと煩雑になるので、先にこの機能を使って組んだBPを示します。
GameSingletonにログのバッファを持たせて、通知を受け取れるようにしています。

totalBP.png

ログを取得、通知する

ログを拾うには FOutputDevice を継承したクラスを作成し、AddOutputDeviceで登録すれば完了です。
お手本としては OutputLogModule にある FOutputLogHistory を見るのが良いと思います。
今回は とりあえずGameSingletonにログバッファと通知機能を追加します。

うっかりすると、通知先でもOutputLog出力処理がある場合に無限ループになってエディタが停止してしまいます。
適当にフラグを追加して回避しています。(全体的にも適当ですが・・・)

MySingleton.h
#pragma once
#include "UObject/NoExportTypes.h"
#include "MySingleton.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMySingletonOutputDeviceUpdate);

UCLASS(Blueprintable, BlueprintType)
class MYCONSOLETEST_API UMySingleton : public UObject
{
  GENERATED_UCLASS_BODY()

  // ログ保持のバッファ
  UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = MyConsole)
  TArray<FString> Buffer;

  // 登録解除用
  virtual void BeginDestroy() override;

  // バッファへログを追加する
  void addConsoleText(const TCHAR* Data);

  // ログ追加時の通知
  UPROPERTY(BlueprintAssignable)
  FMySingletonOutputDeviceUpdate OnOutputUpdate;

};
MySingleton.cpp
// Fill out your copyright notice in the Description page of Project Settings.

#include "MyConsoleTest.h"
#include "MySingleton.h"

class MYCONSOLETEST_API FMyOutputDevice : public FOutputDevice
{
public:
  UMySingleton *mySingleton;
  FMyOutputDevice::FMyOutputDevice()
  {
    mySingleton = nullptr;
  }

  virtual void Serialize(const TCHAR* Data, ELogVerbosity::Type Verbosity, const class FName& Category, const double Time) override
  {
    if (!mySingleton) return;
    if (!mySingleton->IsValidLowLevel()) return;
    mySingleton->addConsoleText(Data);
  }

  virtual void Serialize(const TCHAR* Data, ELogVerbosity::Type Verbosity, const class FName& Category) override {
    if (!mySingleton) return;
    if (!mySingleton->IsValidLowLevel()) return;
      mySingleton->addConsoleText(Data);
  }

  virtual bool CanBeUsedOnAnyThread() const override { return false; }
};

// OutputDeviceは1つ
static FMyOutputDevice *d = nullptr;

UMySingleton::UMySingleton(const FObjectInitializer& ObjectInitializer)
  : Super(ObjectInitializer)
{
  // 登録
  if (d == nullptr) {
    d = new FMyOutputDevice;
    check(GLog);
    GLog->AddOutputDevice(d);
  }
  if (d) {
    d->mySingleton = this;
  }
}

void UMySingleton::BeginDestroy() {
  // 登録解除
  if (d) {
    d->mySingleton = nullptr;
  }
  Super::BeginDestroy();
}

void UMySingleton::addConsoleText(const TCHAR* Data) {
  Buffer.Insert(Data, 0);
  Buffer.SetNum(30);

  // 再起呼び出しを防ぐ
  static bool bFirst = false;
  if (bFirst == false) {
    bFirst = true;
    OnOutputUpdate.Broadcast();
    bFirst = false;
  }
}

作成したMySingletonを登録します。
エディタを起動して、↓のように設定します。
singleton.png

BPからアクセスできるようにする

このGameSingletonをBlueprintからアクセスできるようにします。
↓このノードです。
GetSingleton.png

MyFunctionLibrary.h
#pragma once
#include "MyFunctionLibrary.generated.h"


UCLASS()
class MYCONSOLETEST_API UMyFunctionLibrary : public UBlueprintFunctionLibrary
{
  GENERATED_BODY()
public:
  UFUNCTION(BlueprintPure, Category = "MyConsole")
  static UObject* GetSingleton(bool& IsValid);
};
MyFunctionLibrary.cpp
#include "MyConsoleTest.h"
#include "Core.h"
#include "Engine.h"
#include "MyFunctionLibrary.h"

UObject* UMyFunctionLibrary::GetSingleton(bool& IsValid)
{
  IsValid = false;
  UObject *o = (GEngine->GameSingleton);

  if (!o) return NULL;
  if (!o->IsValidLowLevel()) return NULL;

  IsValid = true;
  return o;
}

最後に

地味なVRネタになってしまいました。
VRアプリ開発者の方は普段どんな環境でデバッグしてるんでしょうかね?
良い機能や情報があったら知りたいです。

明日は、monsho1977さんの「エンジン拡張的な何かをやりたい」です。

ruyo
bandainamcostudios
バンダイナムコスタジオは、家庭用ゲームソフト、モバイルコンテンツ、の企画・開発・運営、ゲームに関する技術研究・開発を行っている会社です。
https://www.bandainamcostudios.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした