C++幼女先輩

プログラミング成分多め

アニメーションブループリントで モーション合成

はじめに

ゲームのサンプル書いているけど仕事のほうが忙しく、作業すすまないため Tipsを書くことに

Tipsと言う名の、自分のためのメモでもある

今回の内容

ブループリントに関して何も言及していないのにアレだが アニメーションブループリントは、通常のブループリントと全く違う。別物である アニメーションの合成機能と簡単な計算しかないので この間仕事で使った機能を

アニメーションブループリントを作成する

テンプレートより ブループリントの ThirdPersonを選ぶ

Content/Mannequin/Animations/ThirdPerson_AnimBP があるのでそれを開く このファイルが今回HACKする アニメーションブループリントだ。

同じフォルダに複数ファイルがあるが

ThirdPerson_IdleRun_2D これは、後述するブレンドスペース。名前は2Dになっているが中身は BlendSpace1D なんでだ?? それ以外は JumpやWalk、Run、Idleの モーションファイル

初期状態

テンプレートを実行したら

f:id:murasame-labo:20160926105429p:plain

TPS視点でグレーマンが 移動、カメラ回転、ジャンプ が出来るだけの単純なデモが実行される コントロール部分は ThirdPersonCharacterの EventGraphにルーチンが書いてあるのでそちらを参考に。

今回のアニメーションで注目すべきは まず歩き。 アナログパットを少しだけ傾けると ゆっくり。大きく傾けると 前傾姿勢になり走っていると思う これは Idle、Walk、Runを 速度によりブレンドしているので、なめらかにつながっている

この、アニメーションのブレンドを、ブレンドスペースという

先程のThirdPerson_IdleRun_2Dというファイルで Idle、Walk、Runを合成している

2つ目は ジャンプ。これは ジャンプスタート、ジャンプ中、ジャンプ終了と3つのアニメーションを組み合わせて、ステートマシンを形成している

とりあえず今回注目は この2つ

ブレンドスペース

ThirdPerson_IdleRun_2D Unrealではヘルプを読むかぎり 現状は2軸のアニメーションブレンドしか出来ないが将来的に拡張する予定らしい。 今回は Idle~Runまでの1軸のブレンドなので、 BlendSpace 1Dを使っている

似た機能にAimOffsetがあるが、こっちは加算アニメーション等 BlendSpaceより多少機能が充実しているらしい

ThirdPerson_IdleRun_2Dを開くと 下記の画面がある f:id:murasame-labo:20160926112527p:plain

縦軸がスピードで、今回はレンジが 0-375になっている。 黒い点が Idle、Walk、Runのモーションで、Speedという引数により ブレンド係数が変わるようになっている

今回は1Dなので横軸はないが、例えば 上半身を左右に動かす Directionという引数を横軸にもって 2Dでブレンドすることも出来る

プレビューで簡単にブレンドが確認できるのでとても便利ですね。

f:id:murasame-labo:20160926113152p:plain

AnimGraph(Idle/Run state)で こんな感じに Speedを引数に アニメーションを作ります

ジャンプ ステートマシン

ステートマシンを開く f:id:murasame-labo:20160926113602p:plain

初期状態が Idle/Run(先程のブレンドスペース)で、ジャンプをすると JumpStart->JumpLoop->JumpEnd->Idle/Run  という流れ

それぞれ該当する モーションをFinalPoseにすれば良い。簡単。

ブループリントから変数を受け取る

色々な理由で ブループリントから値を渡したい事があると思う。

今回は ThirdPersonCharacterから TestHogeというBool値を渡す

ThirdPersonCharacterのEventGraphで、 ZでTestHoge設定、Xでクリア する f:id:murasame-labo:20160926120028p:plain

これを ThirdPerson_AnimBPのアニメーションBPで取得するには PawnOwnerからCastしてThirdPersonCharacterを取得する ここで気をつけるのは、アニメーション ブループリントのOwnerはAnimInstanceであって、キャラクターではない キャラクターは PawnOwner

f:id:murasame-labo:20160926121255p:plain

TryGetPawnOwnerを ThirdPersonCharacterにキャストし、そこから TestHogeを取得。 Blend Poses by bool にて、TestHogeがtrue時は 今まで通りのブレンドスペース歩き falseの時は Idleを設定してみた

実行結果は、Zキーを押すと ブレンドされた歩きに、Xキーを押すと Idleのまま地面を滑る ようになり、正常に ブループリントから値を渡せた事が確認できる

各種ブレンド

上記に Blend Poses by bool が出たので、各種ブレンドを簡単におさらい 基本的にはアニメーションブループリントは アニメーションのブレンドと、そのための簡単な計算しかできませんので ブレンドを覚えたらほぼ終わりです

f:id:murasame-labo:20160926123244p:plain

左から

Blend

一番単純なブレンド。 AとBの2個のアニメーションをブレンドするのみ。 Alphaでブレンド係数を変更できます

Blend Poses by bool

ActiveValue 引数のbool値により、TruePoseとFalsePoseに分岐します。ブレンド無し。 各モーションの補完時間も指定可能

Blend Poses by int

ActiveChildIndex 引数のint値により 複数のモーションに分岐。ブレンドなし AddPinでポーズは複数追加できる 各モーションの補完時間も指定可能

Layered blend per bone

影響ボーンを指定し、ボーンごとにブレンドすることが可能 指定ボーン以下の子ボーンが合成される。ボーンも複数指定可能 例えば 右腕だけ合成、上半身だけ合成、右腕と左腕のみ合成 等を行うことが出来る Add pinで ブレンドを増やせるので、ウエイト違いで複数合成可能

Blend Poses (Enum)

基本的に ステートマシンを使うが、Enumを使ってアニメーション制御も可能 ActiveEnumValueにEnum変数を指定し、そのEnum値により ポーズを分岐させる事が可能

以上!

明日はTGS

明日は東京ゲームショウ ビジネスデイ

友達の会社はブース作って新しいビジネスを発表するらしい

私のところは・・・と比較したって始まらない

まずは友達に挨拶し、ビジネス内容を詳細聞き、手伝えるなら手伝う事。

地道にビジネスを育てようと思う とりあえず今の案件をおちつかせるど!!

教育  まとめ

まとめ。

今まで 教育係になることが多かった。なぜか年上相手ばかりだけど。 今まで ほとんどの案件でリーダー的立場なので、教育しつつスタッフを使っていた

教育は慣れているはずだが、改めて 教育について考えると 私は あまり教育ができていなかったのではないかと 思う

「教育」というのは 教える+育てる である 今まで私は、教えるというのは 出来ていたと思うが 育てるに関しては どうだったのか?

私の今までの指針は 教える。出来るヤツは 勝手に育つ。 自分で育たないヤツは 出来ないヤツだから 切ればいい

そういう考えであったし、ある意味正しいのだけど

勝手に育たないヤツも居る。むしろ最近は そちらの方が多く 教えて 育てないと ダメ

その 育てるというのが 具体的に何が必要なのか・・・ 試行錯誤をしている。 学校を考えると、教えるというのは授業だ 育てるというのは?  遠足や放課後、ホームルーム、教育指導 などなど 直接勉強と関係ないタスクも多い

しばらく 人を育てることに重きを置いてみようと思った

教育 概要

チラシの裏

私は、プロの現場で戦う プログラマーであり、謙遜をせずにいうと Sクラスのプログラマだと思う

プログラマのクラスってのは、自己判断で、報酬額で選ぶのか、技術なのか、プロダクトなのか よくわからないけど とりあえず どこかの世界の第一線で働いていると言える

まー 上には上がいるけどね。。。

そんなわけで、まだ現役!

だけど 教育というのも重要な仕事である

教育というと学生の頃からよく、教えるのがうまいと言われ、色々な人に勉強教えたり 家庭教師を闇でやってたりしてたけど

ことプログラムに関しても、常に教育係に任命されていたり、リーダーとして常に働いていたので 作業員を教育して 使える人材に育て上げてから 仕事を始めてきた

19歳でプロの現場に立ち、フリーランス集団の一員に入り 半年間は 受付システムの開発リーダーの座を先輩から奪い取り、先輩をこき使っていた 半年後に 女性技術者を教育することになった

KさんとIさん。Kさんは6歳上で、Iさんは10歳ほど歳上

Kさんは正直、全くプログラマに向かない人間で、数学が全くできない普通の女の子だが、社長と肉体関係があり 面倒みてくれとの依頼 でもKさんにはC言語をポインタからメモリアロケートまで つまづくことなく教えきった ただし、腕に根性焼きが残っているように、昔から 肉体関係で自分の立場を保つ事しか出来ないらしく 自分の技術力のなさに気がつき、立場を守るために 開発男性を片っ端に誘って 肉体関係を構築していった そのため メンバーの女性たちから不満が高まっていた 私にとって始めての教育だったが、私が引導を下した。 最終出社日に 彼女と公園でみんなで遊んだ。そして私は一人 大泣きをした。 表向きには 彼女に引導を下し、彼女へのごめん だけど、実際は 自分がうまく教育できなかったことへの不満だろう

Iさんは コードはそこそこ書けるが、やはり数学的思考が弱く、適正としては ギリギリ。 ただし、仕様書を作る能力は そこそこだったので、最終的には メンバーでは仕様書ナンバー2の立場になった コードも まーまー でも地頭はそこまで良くないので その辺が限界

その後、これまた5歳上の N君の教育。 N君は繊細かつ頑固で、自分の世界を持っており決して曲がらないタイプで 能力は高いし、プロは世界観を持つべきだが、他人の世界観に入ることができないし そのために 伸びる限界があった 彼は結構いい仕事をしてくれたが結論から言えば 切った。 なぜなら、ホステスに恋に落ちて、仕事が残っているのに 夕方数時間 スーツ着て居なくなる その事を注意しても 食事に行っていた(嘘ではないが・・)と 改善されないからである 今の私なら、それでも作業がちゃんと済んでいれば何も言わないけど、当時は 規律を乱すことを嫌がっていた

そして ゲーム会社に行きA君 A君はネットゲーム中毒で、朝こないが、私は我慢をしていた。 彼は一応 前回はメインでゲームを作ったらしく、今度はメイン以外がいい ってことで私の下に入った コードの技術は弱いが、仕様をよく覚えているので、役に立ってはいた だが いつも昼遅くに来て、会社で寝ていて、作業も中途半端なものを出し、コードも品質が悪い ので 少し私もイライラしていた 決定的だったのは、私が自作エンジンのパフォーマンス改善のために 4関数に関してインタフェースを変更した それから1週間後に 彼が最新をとってビルドして コンパイルが通らなかったので 「エンジンのインタフェースは変更するな!前の関数は残して 新たな関数を追加しろ! 今までのコードがコンパイル通らない!」 と怒ってきた まー 一理あることはあるが、開発初期段階だし、パフォーマンスが大きく変わり 古い呼び出し方では読んでほしくないので 変更が必要な旨を説明したが、結論言うと 今までの相手の仕事態度への不満と 不真面目なヤツに言われる筋合いがない ということで 切った

お次は A君の代わりに入ったK君。彼は良い。教えるだけで勝手に育ってくれて、そのまま社員になった

その後色々と教育したが

T君 これまた年上だが、あいつは ダメ人間だった。コードは普通。だが仕事中にキャッシュから2ちゃん見たり、串さして2ちゃん見たり ブラック企業情報調べてたり 仕事内容も あまり良くないし コードの品質は ギリギリ合格レベル だけど 屑なりにも 上手く使えたと思う。 なんだろう この辺から、他人は他人。自分の希望する人間にはならない と理解し、屑なりに使う方法をあみ出してきた

その後は S君に3Dの基礎から全部教えたり、そこそこ出来ているが

本当に教育できていたのか??? と疑問に思った

続く

Unreal4 簡単なゲームを想定して調査する

TL;DR

Unreal習得に最も近道は 大雑把なエンジンの思想を覚えて、1本簡単なゲームを作り そこに肉付けすることだと思う

エンジンの思想

この間調査した内容では、BluePrintというビジュアル言語とC++があり、どちらでもゲームコードをかけるし お互いにCall出来る

ビジュアル言語では、デザイナーや企画がコードを書いたり、微調整したり、意思を伝えたり 普段 Excelやメールでくる仕様書が、実際に動くイメージとして作ってもらえる事が多い

ただし BluePrintでは、複数人で同時でファイルさわれなかったり、コードの再利用性等 プログラマにとってはC++にメリットがある場合も多いので BluePrintとC++をうまく併用するのが良さそう

また、ネットワークでのマルチプレイヤーゲームを想定して作られているため サーバとクライアントでの値のレプリケートや、RPCもある

そして、ネットワークの遅延に対しても、非常によく出来たアルゴリズムを使い 違和感が極力出ないように補完される

そして、レンダリングにはデファードレンダリングを使い、今流行の綺麗なライトマップが表現可能

その他、20年間のノウハウを含んでいるだけあり、とても素晴らしい出来である

実践しようぜ!

ってことで、あまり先を考えずにゲームを作ってみようと思う

プロジェクト作成

プロジェクト新規作成で BluePrintを選び SideScrollerを選ぶ 名前は GlayRunにした。理由はよくわからない

f:id:murasame-labo:20160908034914p:plain

実行すると サイドビューで ジャンプと横移動が可能

しかしジャンプは高くゆるやかで、移動速度も遅いので変更しよう f:id:murasame-labo:20160908035658p:plain

Content/SideScrollerBP/Blueprints/SideScrollerCharacter  を開く 左上のメニューから CharacterMovement というコンポーネントを選ぶ

コンポーネントとは、Actorに対して昨日を追加するモジュールで、この場合はジャンプや移動等の機能を提供する

そこで CharacterMovementの MaxWalkSpeedや、Jumping/Fallingの Jump Z Velocity 等を調整する

これで 思った動作になった

敵を作る

敵は 新規BluePrintで Characterから派生しよう 今のところは C++コード書かないので Character から直接派生させる C++でコード拡張するのは前回やった リフレクションのアレをすればいい

名前は BP_CharaEnemy にした。ダサいのでネーミング規則はそのうち考えたい ついでに SidescloeerCharacterを BP_Charaにした

f:id:murasame-labo:20160908035708p:plain

BluePrintを作った段階では メッシュが設定されていないため、敵は表示されないので とりあえず BluePrintと同じメッシュをつける 左上メニューより Meshを選択し DetailsのSkeltalMeshに SK_Mannequin を設定 このままだと プレイヤーと紛らわしいので Materialsを適当なものにする 私は 水にした。意味不明

f:id:murasame-labo:20160908040154p:plain

その後 敵キャラを小さくしたかったので、メッシュやカプセルのスケールやトランスフォームを調整 f:id:murasame-labo:20160908040335p:plain 

とりあえず 敵キャラっぽいのが出来た

敵と当たり判定をつける

Characterにはカプセルがあるので、とりあえずは それを使ってコリジョン判定を行う事ができる 攻撃コリジョンと 食らいは別にするのが常識だ

今回は プレイヤーが敵に当たった処理を書きたいので BP_Charaの CupsuleComponentを右クリックし AddEventメニューから、OnComponentHitを選ぶ コリジョンでは BeginOverlapやEndOverlapも使えるが、今は敵との判定が Overlap不可能なためHitを選ぶ

f:id:murasame-labo:20160908040513p:plain

すると EventGraphに OnComponentHitイベントノードが出現するので OtherActorから Cast to BP_CharaEnemyを生やす。 確認のためにPrintStringをつなげる

f:id:murasame-labo:20160908041248p:plain

論よりRUNだ

敵をレベル(マップ)に配置する。 とりあえずは BP_CharaEnemyをD&Dでレベルに置けばいい

Playし敵に当たると  PrintStringのメッセージが出る

当たり判定は成功

上記サンプルで適当に流しすぎ機能

攻撃コリジョンを使っていない コリジョンのOverlapも欲しい コリジョンHIT相手が複数種類いる場合 敵のスポーンを動的にしたい *BP_CharaのデフォルトのBluePrintの説明(横移動とジャンプ)

また、非常に足りてないと思う機能 UI GameStart,GameOver そして ゲームの遷移 キャラの死亡演出 得点 ライフ 敵キャラの動き(大げさにいえばAI)

今日はスケジュール管理が忙しく時間取れず 簡単なサンプルしか作れなかったけど ここから少しずつ膨らませて行こうとおもう

次に調査する内容を何にするか

今のところ、BluePrintとのリフレクションまわりの調査が終わった 正直いうとゲームを作る上で表向きには何も必要なさそうな部分だけど

Unrealの性質を知る上では、良い題材と思う いきなりリフレクションから始めるあたりが、私流というか、自分にとって最も効率の良い勉強法なんだろう

その延長でいけば、変数のレプリケーションやRPCまわりだが そこに行く前に、サーバーとクライアントの処理、Unrealの基本的なクラス についてが必要になる Unrealは元々 サーバに複数のプレイヤーが集まり ネットワーク対戦するゲームなので サーバにしかない変数、サーバにありクライアントと同期するもの、各プレイヤーにしかないもの、各プレイヤーとサーバにしかないもの などがある

ゲームを作るうえでは、当たり判定等の処理も必要だし UIも必要 敵AIも必要 そもそもキャラクターのセットアップやアニメーション機能必要じゃね? デザイナー向けのBluePrintも・・・

非常にやること多いんですけど・・・

ってことで、ミニゲーム作りながら地道にやるのがいいのかな

UnrealEngine4 最初にBluePrintとのリフレクション部分を調べる part4 BluePrintに渡せる型

BluePrintに渡せる型

BluePrintになんでも渡せると思うな!

C++コード

UENUM(BlueprintType)
enum class EHogeEnum : uint8 {
    HOGE,
    HOGE2,
    HOGE3
};

USTRUCT(BlueprintType)
struct BPSAMPLE_API FHoge {
    GENERATED_USTRUCT_BODY()
        float x;
};

USTRUCT(BlueprintType)
struct BPSAMPLE_API FHogeStruct {
    GENERATED_USTRUCT_BODY()

public:
    UPROPERTY(BlueprintReadWrite)   FHoge hoge_;
    UPROPERTY(BlueprintReadWrite)   EHogeEnum enum_;

    UPROPERTY(BlueprintReadWrite)   uint8   uint8_;
// UPROPERTY(BlueprintReadWrite)   uint16  uint16_;
// UPROPERTY(BlueprintReadWrite)   uint32  uint32_;
// UPROPERTY(BlueprintReadWrite)   uint64  uint64_;
// UPROPERTY(BlueprintReadWrite)   int8    int8_;
// UPROPERTY(BlueprintReadWrite)   int16   int16_;
    UPROPERTY(BlueprintReadWrite)   int32   int32_;
// UPROPERTY(BlueprintReadWrite)   int64   int64_;

    UPROPERTY(BlueprintReadWrite)   float  float_;
// UPROPERTY(BlueprintReadWrite)   double  double_;

    UPROPERTY(BlueprintReadWrite)   bool   bool_;

    UPROPERTY(BlueprintReadWrite)   FString FString_;
    UPROPERTY(BlueprintReadWrite)   FName   FName_;
    UPROPERTY(BlueprintReadWrite)   AActor  *AActor_;

    UPROPERTY(BlueprintReadWrite)   TArray<int32> TArray_;
// UPROPERTY(BlueprintReadWrite)   TMap<int32, int32>    TMap_;
// UPROPERTY(BlueprintReadWrite)   TSet<int32>   TSet_;

};

コメントになっているのは、基本的に渡せないもの。 意外と渡せるの少ないですね

構造体、Enumは USTRUCT,UENUM 付きのものは渡せる プリミティブ型では uint8、int32、float、bool のみ

コンテは TArrayのみ

UObjectを継承しているクラスは渡せる f:id:murasame-labo:20160908113351p:plain