一日分の備忘録

ゲーム制作におけるいろいろな実装の備忘録。基本的にはゲームエンジン中心。その中でもUE4がメイン。プログラマーなのでプログラム的な記事が多くなるかも

ぷちコンの参加賞が届きました。

しかもラッキー賞当たっちゃいました。

f:id:oneday-memorandum:20171111144049j:plain

UE4で指定フォルダからファイルの読み込み(CSV編)

作っちゃったし備忘録書く必要あるかなとも思ったがとりあえず書いとく。CSV編としているが他のファイル形式を読み込んだものを書くかと言われると多分書かない。

.h

public:	

	UFUNCTION(BlueprintCallable, Category = "CSVReader")
	void LoadCSVData(FString Filename);
	UFUNCTION(BlueprintCallable, Category = "CSVReader")
	TArray<FString> GetRowDataByKey(FString Key);
	UFUNCTION(BlueprintCallable, Category = "CSVReader")
	TArray<FString> GetKey();

public:
	//変数
	TMap<FString, TArray<FString>> RowData;
	TArray<FString> KeyList;

.cpp

void ACSVReader::LoadCSVData(FString Filename)
{
	//CurrentDirectory取得
	FString dir = FPaths::GameDir();
	//ファイル名
	FString filename = dir + Filename + ".csv";
	//ファイル取得
	FString csvFullData;
	FFileHelper::LoadFileToString(csvFullData, *filename);
	//列で分解
	TArray<FString> row;
	csvFullData.ParseIntoArray(row, TEXT("\n"), true);
	//キーを登録
	row[0].ParseIntoArray(KeyList, TEXT(","), true);
	for(int i = 0 ; i != KeyList.Num() ; i++)
	{
		RowData.Add(KeyList[i]);
	}

	//キー以外の各要素をRowDataにキーと関連付けて登録
	TArray<FString> element;
	for (int i = 1; i != row.Num(); i++)
	{
		row[i].ParseIntoArray(element, TEXT(","), true);
		for (int j = 0; j != element.Num(); j++)
		{
			RowData[KeyList[j]].Add(element[j]);
		}
	}
}
TArray<FString> ACSVReader::GetRowDataByKey(FString Key)
{
	return RowData[Key];
}
TArray<FString> ACSVReader::GetKey()
{
	return KeyList;
}

どうやらFPaths::GameDir();でCurrentDirectoryが取得できるらしい。(ここだけ伝えたかった)
パッケージ化前は[各種ドライブ://~~~/MyProject/]
パッケージ化後は[各種ドライブ://~~~/exeファイルのある階層/MyProject/]
を取得する。
ちなみにブログ用に若干プログラムコードはサボってるので実装するときは各自ちゃんと作ってください。
使いみちあるかと言われると微妙になさそう。ユーザーに配布したゲームでCSV作ったらステージ自分で作れます!的な感じにしたらもしかするともしかするかもしれない。

UnityのProjectでDLLを使う備忘録

VisualStudio2015を開く
VisualC++ -> Win32コンソールアプリケーションを作成
Win32アプリケーションウィザードが開いたら次へ
アプリケーションの種類:DLL
追加のオプション:空のプロジェクトをonにして完了
.cppと.hを作る。

source.h

#pragma once

#define CPULUSSOURCE_API __declspec(dllimport) 

extern "C"//Unityで使うため
{
	CPULUSSOURCE_API float DllMultiPly(float a, float b, int loopNum = 100000000);
}

source.cpp

#include "CPlusSource.h"

float DllMultiPly(float a, float b, int loopNum)
{
	for (int i = 0; i < loopNum; i++)
	{
		float p = a * b;
	}
	return a * b;
}

ものすごい重い計算処理(仮)
ビルド前にソリューションプラットフォームをx64に変更。
ビルドしたらプロジェクトフォルダ内のx64内にDLLができている。
できたDLLをUnityProject/Assets/Plugins内に入れてUnity起動。
Scriptを作成しこんな感じで書く

script.cs

public class DllTestScript : MonoBehaviour {


    [DllImport("DLLTest", EntryPoint = "DllMultiply")]//今回作ったdll
    public static extern float CPlusOnlyDllMultiplyt( float a, float b, int loopNum = 100000000);
    void Start () {
        float tempFloatData = 0;

        //C++
        ProcessLoadTimeStart();

        tempFloatData = CPlusOnlyDllMultiplyt(8, 8);

        ProcessLoadTimeEnd();
        Debug.Log(tempFloatData);


        //C#
        ProcessLoadTimeStart();

        tempFloatData = TestCSharpLibrary.TestCSharpLibrary.SharpMultiply(100000000, 3, 5);//別で用意していたC#dllを使用
	//for(int i = 0 ; i < 100000000 ; i++)
	//{
	//	float p = 3 * 5;
	//}
	//ない場合はこれを関数化して使用

        ProcessLoadTimeEnd();
        Debug.Log(tempFloatData);

    }


    private float CheckTimer = 0;
    void ProcessLoadTimeStart()
    {
        // 現在の経過時間を取得
        CheckTimer = Time.realtimeSinceStartup;
    }

    void ProcessLoadTimeEnd()
    {
        // 処理完了後の経過時間から、保存していた経過時間を引く=処理時間
        CheckTimer = Time.realtimeSinceStartup - CheckTimer;

        Debug.Log("ProcessLoadTime : " + CheckTimer.ToString("0.00000"));
    }
    // Update is called once per frame
    void Update () 
    {
	
    }
}

Emptyを作ってScriptをアタッチして実行。
割りと苦戦したが1回できてしまえば後はあっさりできた。

プロパティ指定子の備忘録

プロパティ指定子使いそうなものについてまとめ

UPROPERTY()で設定できるもののこと


AdvancedDisplay
Detalis(詳細)パネルの拡張ドロップダウンリストに表示される。

AssetRegistrySearchable
メンバー変数として格納するアセットクラスインスタンスからこのプロパティと値が自動でアセットレジストリに追加される。
構造体やパラメータの使用は厳禁
難しく言ってるけど要するに検索できるようにする。

BlueprintAssignable
マルチキャストデリゲートのみ使用可能。ブループリントへ割り当てるためにプロパティを公開する。

BlueprintCallable
マルチキャストデリゲートのみ使用可能。ブループリントのグラフでの呼び出しのために公開するプロパティです。

BlueprintReadOnly
プループリントでの読み取りのみ可能。

BlueprintReadWrite
ブループリントでの読み書き可能

Category
プロパティのカテゴリを指定をする。"|"を使ってネスト(入れ子)設定もできる。

UPROPERTY(Category="CategoryName|SubCategoryName")
Type VariableName;

Config
iniファイルで値を保存することができ、作成時にロードされる。編集はできない。

EditAnywhere
プロパティエディタに公開されて編集可能になる。
前記事参照oneday-memorandum.hateblo.jp


EditDefaultsOnly
プロパティウィンドウでのみ編集可能。Visible* とは互換性がない。

EditFixedSize
配列の長さの変更を制限する。

EditInline
アンリアルエディタのプロパティインスペクタ内で編集できるようになる。

EditInstanceOnly
詳細タブのみ編集可能になる。

NoClear
オブジェクト参照がNoneにならないようにする。

VisibleAnywhere
エディターでプロパティで表示する。編集は不可。

VisibleInstanceOnly
詳細タブでプロパティで表示する。編集は不可。

多分こんなもん

TGSに参加してきました。

1日目

グランツーリスモSPORTS
初心者用のブレーキ、ステアリングが自動
中級者向けのブレーキ自動が嬉しかった。

 

真・女神転生VR
コントローラーでタブレットを持って命令を送ると行った手法。タブレットに情報を入れるとなかなか良いのではないかとおもった。
途中地震の演出があり建物が崩れるのだが、その時に画面が揺れて気持ち悪くなったが、よく観察してみると、カメラは揺れておらず、周りの建物のみ上下に揺れていると行った演出をしていた。せめてもの酔い対策ということか。確かにカメラは揺らしてない。でも吐いた。ゲロゲロ

 

シリコンスタジオ
運転シュミレーター
酔い対策などは見受けられなかった。開発者と話をしたところ、シュミレーターだから酔い対策はしなかったとのこと。この話を聞いて、VRのコンテンツで何から何まで酔い対策を考える必要はないのだなと思った。新たな発見

 

インディーズ
自分にお金があればぜひ支援したいと思うようなゲームが非常に多かった。お金欲しい。あとはスイッチが結構あった。PSVRもそこそこ展示が増えた印象。もう少し英語話せるようになりたい。今後はスイッチに流れがそこそこきそうでした。

 

tobii
VR視線追従周りの技術でもがあった。
制度は良いが遅延がかなり気になった。お話を聞かせていただいたが、今後の酔い対策や処理不可の面で必ず必要になるだろうとtobii開発者と共通の認識だったので安心?した(なお話ししていただいたのはtobiiマーケティング部の方)。今後の対応が待たれるが、次のVRはスタンドアロン型のHMDが来ると予想されているので先はまだ長いか・・・待ち遠しい。

 

学生
ある程度のスペースがある学校には大体VR作品があり。どれも学生ながら非常によくできていた。

人気コンテンツ
MHWとCODWWⅡはすごく人気。会場15分ほどで受付終了すると言ったレベル。

またVRも、HMDかぶるだけのVRと言うのは受付中止になるほどではなかったが、専用筐体や最新のVRウェアなどを着て参加するものはすぐに受付中止になっていた。

 

2日目
匂いVR
VRサクラ
チョコの匂いやスイカの匂い、香水の匂いが体験できる。中々たまらない感じがでてて非常によかった。今後この技術も発展していってほしいと思います。いけないことをしている気分になりました。これ以上は言葉で表すのは非常に難しい。そのような体験でした。

 

ペットと遊ぶやつ
不快な匂いは割りとそれだけで気分が悪くなった。やはり五感すべてが快適な体験が行えないとVR酔いと言うものが発生するのかと思う。このコンテンツに関しては自らはその場を動かず犬とたわむれるだけといったものなのだが、本当に匂いだけで気分が悪くなった。また新しいことを感じれたので、気分は悪くなったが満足した。

 

seiya
VR音ゲー。ノートが音になり、ノートを拾えなかったら音はならない。パンチするときの力が得点に加算される。結構疲れるもののVRの体験としては良いものではないかなと思われる。

 

ボトムズ
対戦系コンテンツ。専用コントローラーで移動などを行う。ゲームが始まると対戦相手と戦うのだが、相手が誰かわからない。2戦目にしてようやくルールが理解できた。
内容自体は非常に楽しく、コックピット系VRに専用コントローラーはかなり良い体験になることを再確認。Gyroと合わせられるような技術になると良さそう。やはりVRはアトラクション系との親和性はかなり高い。


Gyro
360度超回転するVR
VR酔いよりもアトラクション酔いが強いと感じる。映像と体にかかるGが少しだけタイミングがずれている部分があり、そこで一瞬胃液がこみ上げた。映像と体にかかるGを更に正確にすることが直近の課題だろう。しかしながら映像に合わせると没入感は群を抜くものになるだろう。アトラクションとしてぜひともはやってほしい。

 

閃の軌跡

完全に趣味。特に語ることはなく、ただただ楽しみ。

 

------------------------------------------------------------------------------------------------------------------------------------

全体

やはりと言うかなんというか注目はMHWだろう。これに関してはビジネスデーにも関わらずどこもかしこも人で溢れていた。全体的にスマートフォンゲームブースの人はそこまで多くなく、コンシューマ系に人がかなり多く流れていっていた。これはゲームの周期が一周したと言うのはまだ早いかもしれないが、ごくごく近い未来そうなるのではないかなと思う。

とは言うもののスマホの出店数は前年とほぼ同じくらいと言った印象。
去年に比べ、アーケードゲームは前年に比べ少ない?(というか全く見なかった)

コンシューマは各ハード少し減ってスイッチが参入してきたと言った感じ。

VRに関してはPSVRがかなり減ってviveがかなり増えた。というのも、上記で上げた専用筐体などを使ったものの影響がかなり大きいのかなと思う。VRは家庭で楽しむものというよりもアトラクション的な要素として楽しませていく方向にシフトしつつあるのか、果たしてと言った感じだった。もちろん前年に比べ、家庭で遊べるゲームも増えている。

また、PCゲームが去年に比べ、少し増えていたかなという印象、中でもPUBG(PLAYER UNKNOWN BUTTLE GROUND)はいたるところで見かけた。

こういった部分を見るとesportsやSteam配信(PCゲー)の時代にも流れになりつつあるのかもしれない。

処理時間計測の備忘録

BPのある部分のみ処理時間を計測したくなったのを気になったので作成。
この処理自体の処理時間はわかりません。

C++クラスを作成。
.h

UFUNCTION(BlueprintCallable, Category = "Clock")
static void StartClock();

UFUNCTION(BlueprintCallable, Category = "Clock")
static float EndClock();

.cpp

#include <windows.h>

static LARGE_INTEGER freq;

static LARGE_INTEGER start_time, end_time;

void UClock::StartClock()
{
	QueryPerformanceFrequency(&freq);
	QueryPerformanceCounter(&start_time);
}


float UClock::EndClock()
{
	QueryPerformanceCounter(&end_time);
		
	return 1000 * (float)(end_time.QuadPart - start_time.QuadPart) / freq.QuadPart;
}

適当に重い処理を書いて計測。
f:id:oneday-memorandum:20170816160207p:plain

こんな感じで使う
f:id:oneday-memorandum:20170816160212p:plain

レベルに配置したActorのインスタンス変数の編集可否をフラグで管理する方法についての備忘録

BPではmetadataにアクセスできなさそうなのでC++クラスを作成。
下記コードを追加
Trueのときに編集可

UPROPERTY(Category = "test", EditAnywhere, BluePrintReadWrite, meta = (EditCondition = "EditTest"))
int hoge;
UPROPERTY(Category = "test", EditAnywhere, BluePrintReadWrite)
bool EditTest;

これだけ。後は作ったC++クラスを継承したアクターをレベルに配置するとこういう感じで表示されるので、チェックONOFFで編集状態が切り替わる。
f:id:oneday-memorandum:20170809165851p:plain

Falseのときに編集可にする場合は下記の通り

UPROPERTY(Category = "test", EditAnywhere, BluePrintReadWrite, meta = (EditCondition = "!EditTest"))
int hoge;
UPROPERTY(Category = "test", EditAnywhere, BluePrintReadWrite)
bool EditTest;


enumで編集可、不可の設定

UPROPERTY(Category = "enumtest", EditAnywhere, BluePrintReadWrite, meta = (EditCondition = "EnumValue==enable"))
int enableEdit;
UPROPERTY(Category = "enumtest", EditAnywhere, BluePrintReadWrite, meta = (EditCondition = "EnumValue==disenable"))
int disenableEdit;
UPROPERTY(Category = "enumtest", EditAnywhere, BlueprintReadWrite)
enumtest EnumValue;

としたいところだが、どうやらEditConditionは式を判別できない模様。
ということでこんな感じでまずはコードを書く。(今回はチェックのためにあえてbool型をEditAnywhereにしている。)

/*クラスの外にenumを宣言*/
UENUM()
enum class enumtest : uint8
{
	enable UMETA(DisplayName = "enable"),
	disenable UMETA(DisplayName = "disenable")
};

/*クラス内に変数を宣言*/
UPROPERTY(Category = "enumtest", EditAnywhere, BlueprintReadWrite)
bool enumBool;
UPROPERTY(Category = "enumtest", EditAnywhere, BluePrintReadWrite, meta = (EditCondition = "enumBool"))
int enableEdit;
UPROPERTY(Category = "enumtest", EditAnywhere, BluePrintReadWrite, meta = (EditCondition = "!enumBool"))
int disenableEdit;
UPROPERTY(Category = "enumtest", EditAnywhere, BlueprintReadWrite)
enumtest EnumValue;

書いたらこんな感じで公開される
f:id:oneday-memorandum:20170809165926p:plain
この段階であえて表示しているチェックをONOFFで編集可、不可が切り替わるが、enumを変更しても変わらない。
ここまでできたらコンストラクションスクリプト内でこのようにノードを組む。
f:id:oneday-memorandum:20170809170822p:plain
あとはコンパイルしてenumを切り替えると編集可、不可が切り替わる。できたら使わないbool変数は表示しないようにしておく。

forums.unrealengine.com
ここによるとCanEditChangeをオーバーライドすると式の評価ができるみたいだが、よくわからなかった。
誰か教えてください。