johnnyGameStudio’s blog

無能なゲームプログラマのぼやき ぎーくになりたい Twitter: https://twitter.com/JGS_Developer

【UE4】スマートフォン(iOS,Android)のスリープ機能を無効にする

はじめに

スマートフォン向けに開発していると少し重めのDLCをDLさせる必要があったり、長めのムービーを見せたいことがよくあと思います
その場合、スリープされてしまうとDLが中断したりムービーが途中で終わってしまったりして意図しない結果になってしまいますよね
なのでスリープ機能をOFFにしてしまえば解決するのですがUE4だとどうやればいいのかまとまっている記事が見当たらなかったので備忘録として残りしておきます

環境

Windows10
UE4.21.2

実装

  1. 〇〇.Build.csのPublicDependencyModuleNamesに「ApplicationCore」モジュールを追加
  2. 任意のcppファイルで「HAL/PlatformApplicationMisc.h」をinclude
  3. ifdefでiOSAndroidで処理を分ける
  4. プラットフォーム別のControlScreensaver関数でONとOFFを切り替える

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyActor.h"
#if PLATFORM_ANDROID || PLATFORM_IOS
#include "HAL/PlatformApplicationMisc.h"
#endif


void AMyActor::SetEnableScreensaver(bool enabled)
{
#if PLATFORM_ANDROID
    FAndroidApplicationMisc::ControlScreensaver(
        enabled ? FAndroidApplicationMisc::EScreenSaverAction::Enable : FAndroidApplicationMisc::EScreenSaverAction::Disable);
#elif PLATFORM_IOS
    FIOSPlatformApplicationMisc::ControlScreensaver(
        enabled ? FIOSPlatformApplicationMisc::EScreenSaverAction::Enable : FIOSPlatformApplicationMisc::EScreenSaverAction::Disable);
#endif
}

備考っぽいもの

今回Includeしている「HAL/PlatformApplicationMisc.h」では単純に必要なヘッダーファイルをプラットフォーム別に読み込めるようにifdefで区切っている
なので、どのプラットフォームだろうがこのヘッダーを読み込んでおけばOK
また、ControlScreensaver関数も共通のクラスから呼び出せば大丈夫になっているかと思いきやVerの問題なのかコンパイルではじかれたので素直にプラットフォーム別に処理をわけたほうが間違いないかなと思いました

あとiOSだけっぽいのですが、無効にする処理をBeginPlayで行っても正常動作しなかったのでTickなどで1秒以上delayさせてから実行するようにすると正常動作しました

Anacondaからjupyterを開いてブラウザが立ちあがったがクリックしても動かない場合

環境

WIndows10
python3.6.9
Anaconda3 5.0.0
jupyter Notebook 6.0.0

現象

新しいPCになったのでopenAIgymの環境をセットアップしており、jupyterNotebookをインストールし起動させるとブラウザが立ち上がった
しかし、フォルダをクリックしても新しいフォルダを作成しようとしてもなにも反応がない
なんだったらURLから直接pathをたたいても開かない
なぜだ?となって軽くggってもブラウザが立ち上がらないケースばかりヒットしてブラウザが立ち上がっても動かないケースは解決法が見当たらなかったので備忘録として書き残す

解決法

jupyterをインストールした環境で以下のコマンドを実行

conda install --force html5lib

【UE4】アウトプットログに出力される文字列を取得する

開発環境

UE4.21.2 VisualStudio 2017

手順

  1. FOutputDeviceを継承するクラスを作成する
  2. Serialize関数を作成
  3. 渡された文字列をGLogからデバイス登録をする
  4. アウトプットログに出力される処理を実行する(ログ、コンソールコマンドなど)
  5. 出力し終わったら再びGLogからデバイス登録を解除

実際のコード

※専用のUMGを用意するのがめんどくさいので出力方法をImGUIライブラリを使っている.実際に使う際は適当なクラスなり変数なり用意してほしい

#include "ConsoleActor.h"
#include <imgui.h>

namespace
{
    TArray<FString> strArray;
}

class CONSOLETEST_API FConsoleDevice : public FOutputDevice//手順1
{
public:
    FConsoleDevice()
    {
    }
    //手順2(consoleに吐き出されるlog情報が1行ごとに渡される)
    virtual void Serialize(const TCHAR* Data, ELogVerbosity::Type Verbosity, const class FName& Category, const double Time) override
    {
        strArray.Insert(Data, 0);
    }
    //手順2
    virtual void Serialize(const TCHAR* Data, ELogVerbosity::Type Verbosity, const class FName& Category) override
    {
        strArray.Insert(Data, 0);
    }
};

void AConsoleActor::OutputStr(const FString& str)
{
    FConsoleDevice device;
    GLog->AddOutputDevice(&device);//手順3
    UE_LOG(LogClass, Log, TEXT("output -> %s"), *str);//手順4
    GLog->RemoveOutputDevice(&device);//手順5
}
// Called when the game starts or when spawned
void AConsoleActor::BeginPlay()
{
    Super::BeginPlay();
    OutputStr("AAAAAAAAAAAAAAAAAA");
    OutputStr("BBBBBBBBBBBBBBBBBB");
    OutputStr("CCCCCCCCCCCCCCCCCC");
}

// Called every frame
void AConsoleActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    //取得したログのゲーム内への出力方法は各々で考えてください

    ImGui::NewFrame();
    Super::Tick(DeltaTime);
    //setting
    ImGui::SetNextWindowPos(ImVec2(50, 20), ImGuiCond_Always);
    ImGui::SetNextWindowSize(ImVec2(550, 300), ImGuiCond_Always);
    ImGui::SetNextWindowBgAlpha(0.5f);
    bool isVisiableCloseBtn = true;
    //Draw
    if (ImGui::Begin("Console"), isVisiableCloseBtn)
    {
        for (int i = 0; i < strArray.Num(); i++)
        {
            ImGui::Text("%s", TCHAR_TO_ANSI(*mBuffer[i]));
        }
    }
    ImGui::End();
}

結果

image.png

認定スクラムマスターを取得

認定スクラムマスターを取得

題名の通り
認定スクラムマスターになるには研修に参加する必要がある
研修費用は個人だとかなり高額なので受講する際は会社と交渉するべき f:id:johnnygamestudio:20190613220013p:plain

スクラムマスター研修

会場は神谷町のオフィスビルだった
参加した人数は全部で60人ほどで6人で1チームになり、基本的にワークショップを行ったりスクラムの詳細な事例などを説明されたりする形で進行し計2日間にわたって行われる
個人的に印象に残ったのは「コンテキストスイッチ」という概念の体感ワークショップ
コンテキストスイッチとは簡単に説明すると、異なるタスクを同時進行した場合タスクの切り替え時に総労力の20%がロスとして発生するというもの
実際に行ったワークショップの例を下記に説明するので是非やってみてほしい

アラビア数字と漢数字とアルファベットを書く

用意するのは1枚のA4用紙とストップウォッチ
そこにアラビア数字、漢数字、アルファベットを書くためのスペースを作るために区切りを書く

その① それぞれ交互に書いていく

アラビア数字、漢数字、アルファベットを画像のように書いていき、10まで書き終わるまでのタイムを計る
f:id:johnnygamestudio:20190613230451p:plain

その② 10まで書ききったら次へ移る

アラビア数字、漢数字、アルファベットを画像のように10まで書き終わったら次の文字へ移るように書いていってそのタイムを計る
f:id:johnnygamestudio:20190613230501p:plain

結果

やってみればわかるが①でやったやり方だと時間がかなりかかるが②のやり方だとかなり速くなる
個人差はあるが、私の場合はその①は1分かかり、その②だと30秒ほどだった
こんな簡単なタスクでもコンテキストスイッチが発生するということは実際の業務ではさもありなんというである

認定スクラムマスター試験

認定スクラムマスターの試験はWEBブラウザ上で行う
私の場合は研修終了の翌日にメールアドレスへ試験へのリンクが届き、試験を受けることができるようになる
問題は全部で30問あり23問正解すると合格となる
特に会場に出向くなどはないので自宅や職場で受験が可能
難易度はそこまで高くないが研修でのスクラムへの理解度が試されるような問題となっており、研修で行った内容がそのままテストに出るようなことはない
制限時間などはなく、ggり放題なのだがggっても特に正解が出てくるような問題でもなかったりするので注意が必要
研修だけでなく、自分で本を読んだりしてある程度勉強していればたぶん落ちることはないと思われる
(と言っているが私の点数は24点だった。ギリギリ)

総評

研修自体はかなり楽しかった
ほかの業界の開発者と色々話せたのも良い経験になった
スクラム開発に興味がある人は受講をお勧めする
現在、新しいチームでスクラム開発を初めていこうとしているところなので組織全体へ波及できるようにしっかり成果を出していかなくてはならない

f:id:johnnygamestudio:20190613220028j:plain
緑のトレーナー着ているのが私

【今更】Twitch本社に行ってきました【GDC2019】

3月にGDC2019に行ってました

本当に今更ですが、GDC2019に参加してきました
その際にAWSさんのご招待でTwitch本社に行ってきたのでレポートしておきます

超綺麗なロビー

Twtich本社はサンフランシスコの街中にひっそりとTwitchの看板が見えるビルに入っています
中に入るとロビーがあってID照会をしないと入れない仕組みになっていました
f:id:johnnygamestudio:20190531023504j:plain f:id:johnnygamestudio:20190531023445j:plain

無料で利用できる綺麗な食堂

Twitchでは従業員なら無料でランチをすることができます
さらに飲み物やアイスも無料で食べることができてまさに至れり尽くせり
ですが、ここサンフランシスコで優秀な人材を獲得しようとするならこれらは至って普通だそうです
おそろしやサンフランシスコ

f:id:johnnygamestudio:20190531023813j:plain f:id:johnnygamestudio:20190531023810j:plain

豊富なメニュー

メニューは日によって違っていてハンバーガーやピザ、サラダチキンなどもありました
それだけでなく、ランチでもお酒を無料で飲めてしまいですが、パッと見た限りさすがに昼間から酒を飲んでいる人は見当たりませんでした

f:id:johnnygamestudio:20190531024145j:plainf:id:johnnygamestudio:20190531024149j:plainf:id:johnnygamestudio:20190531024152j:plain f:id:johnnygamestudio:20190531024843j:plain

実況設備も完備

Twitchなのでもちろん実況設備も充実しており、僕が見た限り大小さまざまな実況室が5つくらいはあったと思います
f:id:johnnygamestudio:20190531025031j:plain

個人的に一番良かった点

サンフランシスコのオフィスの多くはオープンテラスがあり、そこで談笑したり仕事したりしている従業員の方がいたのが印象的でした
すごいサンフランシスコっぽい
f:id:johnnygamestudio:20190531025208j:plain

【UE4】最小構成でC++クラスの自動テストを試してみた

はじめに

第3回UE4何でも勉強会 in 東京に参加したが、その中で自動テストについて触れられており、興味があったのでUE4の自動テストについて触ってみた
しかし、Blueprintでのテスト手順はいくつかヒットしたが、ほとんど説明しているブログが見当たらず、あってもあまり詳細には書かれてなかったりしていたので最小構成でのC++クラスのテストをまとめておく

実行環境

UE4.21.2
VisualStudio2017

実行手順

1. プラグインを有効にしてエディタを再起動

まず最初にプラグインを有効にする。メインメニューから
編集>Plugin
を開いて、その中の「Testing」という項目を選択
その中にあるPluginはすべて有効にして、その後再起動
(これらを有効にすると、エディタの再起動を求められる。[Restart Now] ボタンをクリック)
image.png

2. セッションフロンドエンドを開く

ウィンドウ>デベロッパーツール>セッションフロントエンド
を開く
sessionFront.png

開くと「このアプリケーション」の今開いている項目を選択(緑色のアイコンになっていればOKなはず)
その後オートメーションタブを選択
sessionFront2.png

※すでにこのままでもC++以外の既存の機能はテスト可能

3.テストしたいクラスを用意する

今回は最小構成でやっているため、適当にActorを継承したAMyActorクラスを用意した
実装したcppファイルは以下のようになっている(ヘッダーは特に何もしていないので省略)
解説はソース内にコメント

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyActor.h"
#include "AutomationTest.h"//マクロをつかうため

namespace
{
    AMyActor* actor = nullptr;//テストクラスからアクセスできるように無名名前空間でインスタンスのを確保(これで正しい方法かは疑問だが楽)
}
// Sets default values
AMyActor::AMyActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
    actor = this;//コンストラクタで自身のポインタを渡しておく
}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
    Super::BeginPlay();
    
}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

}
//テストクラスから呼び出される関数
void AMyActor::ExecuteAutomationFunc()
{
    UE_LOG(LogTemp, Log, TEXT("Autonmation TEST"));
}

/*以下テストクラスの生成
AutomationTest.h内に書かれているマクロ「IMPLEMENT_SIMPLE_AUTOMATION_TEST」を使う
マクロの中身を見る限り、コンパイル時?にこのcppファイル内に第一引数で指定した名前のクラスを自動生成
RunTest関数を自動テスト側が実行するという仕組みだと思われる
第2引数はセッションフロントエンド内でのカテゴリ分け
ほかにもマクロが色々あるがそれは最後のリンクを貼っている参考にした記事で確認してみてほしい
*/
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMySimpleTest, "MyTest.MySimpleTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
bool FMySimpleTest::RunTest(const FString& Parameters)
{
    actor->ExecuteAutomationFunc();
    return true;
}

4. テスト実行

マクロの第2引数で渡したカテゴリの設定が反映されているはずなのでそれを有効にする
(今回の場合だと「MyTest.MySimpleTest」)
テストしたい項目を有効にしたら「テストを開始する」ボタンを押す
image.png

5. 結果

以下のように
- [x] MyTestが実行されている
- [x] AMyActorのメンバ関数内のLogが正常に吐かれている
- [x] すべてのテストが正常に成功して終了している
これらが確認できるのでテスト完了。

image.png

参考

公式:自動化システムの概要
自動テストの追加方法

【UE4】Unityで慣れたゲームPGがUE4に乗り換える際のTips

はじめに

最近Unityから離れてUE4触ってみようとするゲーム系エンジニア増えましたね
そんな人たちに向けて、実際にUnityに慣れたプログラマUE4に移行してみたときに困ったポイント・知っておいたほうがいいポイントをまとめてみました
正直、始めたばっかりなので間違っている箇所もあるかもしれませんがその際はコメントしていただけると助かります

本記事の対象となる人

  • C++なんもわからんという人
  • Unityなら一通り触っていたという人

参照渡しとポインタ渡しと値渡し

なにをいってもこれ
もちろん、C#にもこれらはあるわけですがC++ではより厳格な制御が求められます
例えば、C#でこんな感じで書いた場合だとString型のtmpはhoge関数の引数として渡されてもC#のString型は参照型なのでコピーはされません
(もちらんintなどの値型が引数ならコピーされます)

void hoge(string str)
{
...
}

void foo()
{
    string tmp = "hello";
    hoge(tmp);//参照型なのでコピーは発生しない
}

また、C#で参照渡しを行いたい場合はrefを使います
現場によりけりだと思いますが、refを使うことはUnityだとあまり使用するタイミングは少ない気がします
(使うケースだと関数内で引数の中身をいじることを明示的に示したい時などでしょうか)
何が言いたいかというと、C#の場合は割と雑に書いてもコンパイル通るし問題ないように動きます
しかし、C++はそうはいきません
先ほどのように書くと値渡しとなりコピーが発生します

void FooClass::Hoge(FString str)
{
...
}
void FooClass::hogehoge()
{
    FString tmp = TEXT("Hello");
    Hoge(tmp);//値渡しなのでコピーが発生する
}

これを防ぐにはポインタ渡しが参照渡しを行ってあげる必要がありますので以下のようにする必要があります
また、値渡しでない場合はconstを積極的に使ったほうがよいでしょう
※ポインタ渡しと参照渡しがなにかという説明はほかに色々記事があるのでここでは説明しません

void FooClass::Hoge_pointer(const FString* str)
{
...
}
void FooClass::Hoge_ref(const FString& str)
{
...
}
void FooClass::hogehoge()
{
    FString tmp = TEXT("Hello");
    Hoge_pointer(&tmp);
    Hoge_ref(tmp);
}

列挙型の文字列化

C++では列挙型を文字列化させるように気の利いた機能はない
C#のようにToString()で簡単に文字列化させてくれるなんて素晴らしい機能はない
だが安心してほしい、UnrealC++ではそこらへんはカバーされている。ありがとうUE4

UEnumをStringに変換する方法はこちら
もしくはこっち

ただし、これはUEnumの列挙型だけであり、なんらかの理由によりUEnumが使えず、普通に宣言されているenumは泥臭く実装するしか方法はないです(あったら是非教えてほしい)
つまり、いい感じのマクロを組んだり、Map(C#でいうところのDictionary)を使用して文字列を列挙型の各値と連結させるしかない
ここらへんは下記リンクで世界中のエンジニアが試行錯誤しているのでぜひ参考にしてください
世界一悲しい話をしている場所はこちら

関数の呼び出し履歴

Unityの場合、Debug.Logを使えばその関数でLogが吐き出されるまでの経路をConsoleウィンドウで確認できますよね
僕の場合はよくこれを使ってデバッグとかしていたんですが、UE4ではそれはできません

呼び出し履歴を知りたい場合はブレイクポイントを使うしか方法はありません
UE4のブレイクポイントを使うための方法などはこちらの方がまとめてくださってます

改造UE4使ったときのインテリセンスがやばい

小さいProjectデータや改造UE4を使っていない場合などは言うほど、重くならないのですが、僕の場合改造されたUE4を用いて作業をしているのでVisualStudioが参照しようとするファイル数が尋常ではなく、インテリセンスがほとんど機能しません
ですが、こちらの記事を参考にしてもうらうとかなり軽減されます

For those who suffer from Visual Studio IntelliSense slowness

簡単に解説すると、ソースファイルを変更した際にインテリセンスはすべてのパスを検索して参照を見つけており、UE4のエンジンデータは特に量が多いです。なので、エンジン側を毎回検索せずにすることで高速化しているようです。

余談ですが、個人的に予測IntelliSenseを使いたいので
オプション > テキストエディター > 試験的 > 予測IntelliSenseの有効化をTrueにしてます

image.png

includeとはなにかということ

Includeとは何をしているか知っていますか?
includeを行うとコンパイル時にその宣言された部分に指定されたヘッダープログラムを差し込み、そのプログラムファイル内で外部のクラスなどを扱えるようにしています
なぜこれをちゃんと知っておくことが大事かというとコンパイル時間に差が出てくるからです
UE4C++クラスを作成するとヘッダーファイルにこんな宣言がされているのを確認できると思います

#pragma once//これ

#include "CoreMinimal.h"
...

これは何を意味するかというと、このヘッダーファイルを読み込んだ時に二重に読み込まれることを防ぐ効果があります
たとえば以下のように二度同じヘッダーをincludeしてしまうとコンパイル時に二つ同じ関数や変数が存在することになっていまい、予期せぬエラーの原因になったり、コンパイル時間が増加したりするなど悪影響を及ぼします

#include "Sample.h"
#include "Sample.h"

ですが、このSample.h内で「#pragma once」が宣言されていればそのようなことは防ぐことができるというわけです
なので、新しくクラスを作成した際は必ず#pragma onceを宣言することを忘れないようにしましょう
詳しく知りたいかたはこちら

無名名前空間

↑のコンパイル時間を長くしない、ということに関連して無名名前空間は使ってほうがいいかなと思います
無名名前空間はCPPファイル内で宣言できるためコンパイル時間を長くしなくて済むほか、外部から見えるヘッダーファイルでは見てほしくない関数名や変数名などを隠蔽するための機能です
ヘッダーに宣言しているとアクセスできなくても関数などは見えてしまうため、設計的にそれは好ましくない場合などで使います
無名名前空間を使うときは「そのファイル内で完結する関数・変数」に限ります
具体的には以下のように使います

#include "Test.h"

namespace
{
    void Hoge()
    {

    }
    int foo;
}


// Called when the game starts or when spawned
void ATest::BeginPlay()
{
    Super::BeginPlay();
    Hoge();
    int a = foo;
}

まとめ

以上C++なんもわからんゲームプログラマがUnityから移住してきた際に知っておいたほうがいいTipsでした
ほかにも色々ありますが、長くなるのでいったんこれで締めます
参考になれば幸いです
間違いなどありましたらコメントください