UnityのIKでモーション作成②

tongarik.hatenablog.jp
続きです。

IKの位置を決めるオブジェクトを指定するまでしたので
次はIKの位置をマウス操作で動かせるようにします。

ここではOnMouseDrag関数を使います。
マウスをドラッグしている間呼ばれる関数です。

void OnMouseDrag()
    {
        //対象オブジェクトのワールド座標をスクリーン座標に
        var _objPos = Camera.main.WorldToScreenPoint(transform.position);
        //マウスの位置をスクリーン座標で取得
        var _mousePos = Input.mousePosition;
        //z軸を対象オブジェクトにあわせる
        _mousePos.z = _objPos.z;
        //スクリーン座標をワールド座標に変換
        var _worldPos = Camera.main.ScreenToWorldPoint(_mousePos);
       
        //対象オブジェクトをマウス位置にあわせる
        transform.position = _worldPos;
    }

これをIKの位置を決めるオブジェクトにアタッチすればマウスドラッグで移動できます。

IKの角度はLookAt関数を使います。
角度を決めるターゲットを用意して

transform.LookAt(_target.transform.position,transform.up);

これで位置と角度が決めれるようになったので
IK位置と角度をアニメーションカーブに保存してモーションを作れるようにします。
techblog.forgevision.com
を参考にしています。
保存方法が録画ではなくフレーム指定で1ポーズづつ保存出来るようにしただけですのでスクリプトは省きます。

これでIK位置角度をアニメーション出来るようになりました。
ここまでがUnityroomに公開している内容です。

このままだとモデルのアニメーションではないので
モデルのアニメーションとして保存したい場合は
バーチャルYouTuber事務所ENTUM(エンタム)さんが公開している
EasyMotionRecorderを使うのが手っ取り早いです。
github.com

UnityのIKでモーション作成①

はじめに

pixivが無料で提供しているVRoid Studioで3Dモデルが簡単に作れるようになったので
次は動きもつくってみようとUnityでこんなのを作りました。
f:id:kanabun500kanabun:20190121204345p:plain
unityroom.com
UnityのIKを使ってモーションを作成します。
Unityroomで公開しているのはモーションは保存出来ません。


作成過程で調べたことを忘れないように残しておきます。

3Dモデル

VRoidで作成したモデルを使用しています。
UnityにインポートするにはVRM - dwango on GitHubからUniVRMをインストールしてから
3Dモデルのvrmをインポートします。

IKについて

docs.unity3d.com
IKについては公式を見てもらうとして実際にしたIKの設定は
IKで動かしたい3DモデルにAnimatorをアタッチしてAnimatorタブから
画像の右の赤〇のIKPassにチェックを入れるとIKが有効になります。
このウインドウは左の赤〇のIKの右横にある歯車を左クリックすると出てきます。
f:id:kanabun500kanabun:20190121205411p:plain

VRoid以外のモデルでIKを使う場合リグがHumanoid以外になってると使えないので
そのときはHumanoidにする必要があります。

次にスクリプトです。
IKはOnAnimatorIK関数を使います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Animator))]
public class IKVRoid : MonoBehaviour
{
    [SerializeField]
    Transform _bodyObj = null;

    [SerializeField]
    Transform _rightHand = null;
    [SerializeField]
    Transform _rightElbow = null;

    [SerializeField, Range(0.0f, 1.0f)]
    float _rightHandWeight = 1.0f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _rightElbowWeight = 1.0f;

    [SerializeField]
    Transform _lookTarget=null;

    [SerializeField, Range(0.0f, 1.0f)]
    float _lookWeight = 0.5f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _bodyWeight = 0.4f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _headWeight = 0.4f;
    [SerializeField, Range(0.0f, 1.0f)]
    float _eyeWeight = 0.4f;

    Animator _animator;

    void Start()
    {
        _animator = GetComponent<Animator>();
    }

    void OnAnimatorIK()
    {
        if (_bodyObj != null)
        {
            _animator.bodyPosition = _bodyObj.position;
            _animator.bodyRotation = _bodyObj.rotation;
        }

        if (_rightHand != null)
        {
            _animator.SetIKPositionWeight(AvatarIKGoal.RightHand, _rightHandWeight);
            _animator.SetIKRotationWeight(AvatarIKGoal.RightHand, _rightHandWeight);
            _animator.SetIKPosition(AvatarIKGoal.RightHand, _rightHand.position);
            _animator.SetIKRotation(AvatarIKGoal.RightHand, _rightHand.rotation);
        }

        if (_rightElbow != null)
        {
            _animator.SetIKHintPositionWeight(AvatarIKHint.RightElbow, _rightElbowWeight);
            _animator.SetIKHintPosition(AvatarIKHint.RightElbow, _rightElbow.position);

        }

        if (_lookTarget != null)
        {
            _animator.SetLookAtWeight(_lookWeight, _bodyWeight, _headWeight, _eyeWeight);
            _animator.SetLookAtPosition(_lookTarget.position);
        }
    }
}

左手、右足、左足は省略してます。
SetIKはAvatarIKGoal.名前で右手や左足を指定します。
SetIKHintはAvatarIKHint.名前で右肘や左膝を指定します。
このスクリプトを3Dモデルにアタッチしてモデルとは別にIKの位置を決めるオブジェクトを登録します。
アニメーション中IKを有効にしてオブジェクトを動かすと対応した位置にモデルが動くようになります。


ここでは使ってませんが

_animator.SetBoneLocalRotation(HumanBodyBones.RightHand,Quaternion rotation);

を使えばHumanBodyBones.名前でボーンを指定してボーンの角度を決められます。


続きます。

Unity 1週間ゲームジャム (テーマ『10』)に参加

Unity 1週間ゲームジャム に参加しました。
今回で3回目の参加です。

お題は『10』

ここまで書いて書くことなくて放置していたけど
反省やらなんやらを書いておくこともありよりのありかと思い書いてみる。


3日目くらいにボウリングでいこうかなとなんとなく決定。
この時点ではボウリングのスコアやらを忠実に作ってからアレンジしようなどと考えていた気がします。

実際はステージ作成とスコア表に時間をとられてなんとか間に合わせた結果ただのボウリングとあいなりました。

今回の自己評価というか良かった点は
期限内に自分のやろうとしていた最低限のことを終わらせて間に合わせたこと。

反省点は
レイヤーズストーリーズゼロのキャラ使ったけど全くいかせてなかった。
他にもいっぱいあるけど次頑張ることにしよう

その他

Unity 2018.2.6f1を使用したけど
アセットのRecorderをビルドに含めるとWebGL出力でエラーが発生する。

今回使用したレイヤーズストーリーズゼロのキャラはオープンソースで公開されてます
projectlayered.com

VRChatのEmote(エモート)作成

VRChatをデスクトップモードでプレイしているとエモートを変更したくなったので方法をメモしておきます。

エモートの変更自体は変更したいアニメーションを用意してアニメーションを変更するだけです。
アニメーションの用意はAssetを購入するのが早いですが欲しいモーションがあるとは限らないのでここでは自作していきます。

自作する場合、検索してでてくるのはBlenderで作る。Unityだと有料アセットを使う。がよくでてきますが
ここではIKを使用してUnityでアニメーションを作成していきます。

AssetのMecanim Example ScenesにあるIK.csを使用します。
assetstore.unity.com

ヒューマノイドのキャラクターにIK.csをアタッチし
Ik Actineにチェックを入れ、Body,Left Foot,Right Foot,Left Hand,Right Hand,Look Atの6つのオブジェクトを設定します。
f:id:kanabun500kanabun:20181022215204p:plain

AnimatorでBase Layerの右にある歯車をクリックしてIK Passにチェックを入れます。
f:id:kanabun500kanabun:20181022214729p:plain

後はAnimationでBody,Left Foot,Right Foot,Left Hand,Right Hand,Look Atの6つのオブジェクトのPositionとRotationを変化させてアニメーションを作成します。
作ったアニメーションはそのままだとVRChatにはもっていけないのでEasyMotionRecoderを使用します。
github.com

EasyMotionRecoderをインポートしたらシーンにEasyMotionRecorder.prefabセットし
MotionDataPlayerコンポーネントおよびMotionDataRecoderコンポーネントのAnimatorにモーションキャプチャ対象のキャラクターをアタッチする。

シーンを再生しRキーを押して録画開始しXキーで録画終了。
開始と終了が成功したかわかりづらいのでDbug.Logで録画開始と終了を表示させてました。
f:id:kanabun500kanabun:20181022225039p:plain

使い方に書いてある通りに
モーション記録して生成されたRecordMotion_2018~~~ ファイルを選択、インスペクタ上で右クリックして「Export as Humanoid animation clips」を選択するとAnimationClipに変換されます。

Y軸がずれるのでオフセットで調整。

これでアニメーションが作成できました。

Unity 1週間ゲームジャム (テーマ『あつい』)に参加

参加2回目、今回のテーマは『あつい』

自分のテーマは前回出来なかったネットランキング、ツイート、BGMを含めて完成させること。
これからも共通で使える部分なので今回はチュートリアルを意識して作成することにしました。
今回はUnity2018.1.9f1を使用しています。

タイトル

f:id:kanabun500kanabun:20180913154202p:plain
タイトル画面です。
あついの文字はBlenderで作成しています。
すたーとはボタンをクリックするとシーンを移動させてます。

ゲーム部分

f:id:kanabun500kanabun:20180913154903p:plain
ゲームは文字にボールを当てるとあついとさむいが入れ替わるようになっています。
赤文字のあついを揃えると得点が増え、お邪魔ボールを出す炎のオブジェクトが増えます。
青文字のさむいを揃えると得点が減り、炎のオブジェクトを減らします。

文字の入れ替わりはOnCollisionEnterとSetActiveを使用しています。
あついとさむいが揃ったかどうかはタグ検索で判定しています。

ボールは発射されるまでは土台と一体となって動くようにしています。
土台の子オブジェクトにColiderをつけてボールと接触している間はボールが土台に追従するようにしています。
発射する時は子オブジェクトを非アクティブにして発射可能にしています。

タイムアップ

制限時間は60秒に設定してあります。
タイムアップでリトライ、ランキング、ツイートがアクティブになります。
リトライはシーンを再読み込み
ランキングは
blog.naichilab.com
ツイートは
github.com

反省点

ランダム要素がいらいらさせる。
攻略要素が少ない。
等、ゲームとしての爽快感がまったく足りなかった。

今回の目的は達成できたので次回はもう少しゲーム性を頑張りたい。

ニフクラ mobile backend のクイックスタートでつまづいた話

Unityで利用するためニフクラを始めたらクイックスタートでエラー

原因は打ち間違えそして確認時も見落とすという単純ミス
忘れないために書き残しておきます。


以下エラーをだしてミスを見つけるまで

イントロダクション (Unity) : クイックスタート | ニフクラ mobile backend
リンクの通りに
APIキーを作成し
Unityで新規プロジェクトを作成し
SDK(ver.3.2.3)をDLし
Unityにインポートし
空のGameObjecを作成し
GameObjecGの名前をNCBMSettingsと手打ちし
NCMBSettings.csをアタッチして
APIキーを設定。


そしてサンプルコードを実行したら
f:id:kanabun500kanabun:20180731202542p:plain
画像のようにエラーが発生。
そして上記の手順をもう一度確認し
もう一度サンプルコードを実行して
同じエラー

google先生に聞いても同じ症状は出てこなかったので
Unityのバージョンを変え実行して
同じエラー

SDKのバージョンを
https://github.com/NIFTYCloud-mbaas/UnityFirstApp/archive/AnswerProject.zip
このプロジェクトに使用していたものに変更
エラーなしで正常に動作。

ですがこのバージョンだとWebGLに対応していないため
今回はWebGLで出力したいので使えず。

そこでバージョン違いを比較したところ
エラーの該当箇所はGameObjectのNCMBSettingsを参照して
旧バージョンだと参照していない。

よくよく見てみるとNCBMSettingsとMとBを入れ替えて入力…
打ち間違えを訂正したら正常に動作。



あとこのクイックスタートが過去バージョンで作ってあるためかこのNCMBSettingsと入力する記述で
"わかりやすいように、作成したGame Objectをここでは「NCMBSettings」という名前に変更します。"
と書かれており、現バージョンでは「NCMBSettings」と入力しないとエラーが発生することを想起しづらい文面だったのも罠でした。

Unityでゲーム画面をGIF形式で保存

assetstore.unity.com
ツイッターでGIFで簡単な動画をあげたかったので探しました。
使ったアセットは上記のRecorder。

GIFでの保存は
Tools>Recorder>Video
f:id:kanabun500kanabun:20180703231714p:plain
Selected recorder:>UTJ>GIF
f:id:kanabun500kanabun:20180703232315p:plain
後はStart Recordingを押せばゲームが再生されGIFで保存されます。
保存先はプロジェクトフォルダのRecordingsフォルダです。