Live2D Cubismでパーツのフェード方法
結論:『Live2Dパーツ表示項目内のパーツのアルファ値をフェードアウトしたい場合は100から0に、フェードインしたい場合は0から100にし、グラフエディタを開き、リニアでフェードの線形補間をかける』
東北イタコのLive2Dモデルを弄っていたが、複数の腕の種類があり、アニメーションの途中でうまく切り替えたいと思った。
が、なかなかフェードイン・アウトを利用した切り替え方法がわからなかったので、ここに備忘録的に記載する。
最初はフェードイン・アウトなど考えずに普通に切り替えようと思い、アルファ値を普通に表示したいパーツを0から100に、非表示にしたいパーツを100から0に変更するという手をとった。
その結果が下図。見ての通り、ぶつ切りになり、違和感がある。
この状況を改善するためにフェードイン・アウトを導入していく。
先ず、パーツをフェード開始のタイミングで、
- 既存で表示しているパーツにアルファ値100を振る
- これから表示するパーツにアルファ値0を振る。
そして、フェード終了のタイミングで、
- 既存で表示しているパーツにアルファ値0を振る。
- これから表示するパーツにアルファ値100を振る。
そのあとにグラフエディタを開く
上図のように各アルファ値を振り終えたら、フェードアウトするパーツを選択した状態でグラフエディタを押下する。
グラフ上に0と添字についたポイントを押下し、リニアボタンを押下する。
すると、グラフが下図のように変更される。この斜めになったグラフが徐々にアルファ値が変更されることを示している。
フェードインするパーツにも同様の操作を行う。
下図のようになる。
以上の設定が全て完了すれば、フェードを利用したパーツの切り替えが完了となる。
DOTweenの導入方法と使用例
DOTweenはUnityのAssetのひとつで、Objectの動きを制御するAsset。
無料版と有料版があるが、今回は無料版を利用した。
先ず、上記のAssetをDownloadし、Importする。
その次に下記のようなウィンドウが表示されるので、「Setup DOTween」を押下。
そうするとAdd/Remove Modulesに遷移するので、「Apply」を押下。
これで準備完了。
あとは、Objectにアタッチされているスクリプトに動きをコーディングすると完了となる。
動きのコーディングの前にやることは、スクリプト冒頭に、
using DG.Tweening;
を記載。これでDOTweemingをこのスクリプト内で使用可能となる。
では、実際に動きのコーディングをしていく。
今回は2種類の動きを作ろうと思う。
どのような動きか、画像をあげるので灰色の円盤状の機体に注目してほしい。
まず1つ目。
下記のような簡単な直線的な動き。
この動きを実現させるためには、下記のコーディングをする。
void Start() { transform.DOMove(new Vector3(0, -750, 0), 4.0f) .SetEase(Ease.Linear); }
簡単に説明すると、
- 第1引数は到着点
- 第2引数は到着点に行くまでにかかる時間
- チェーンメソッドSetEase()は加速減速の方法
今回のケースだと、
(0, -750, 0)に4秒かけて加速減速なしで向かう
となる。
これだけで完成となる。
ちなみにObject出現位置が動きの開始位置となるのでそこは記述の必要はない。
2つ目。
Pathを指定してその経路を通る動き。下記のような動き。
この動きを実現させるためには、下記のコーディングをする。
void Start() { Vector3[] paths = new[] { new Vector3(0, 0, 0), new Vector3(-450, 300, 0) }; transform.DOPath(paths, 2.0f, PathType.CatmullRom) .SetEase(Ease.Linear); }
簡単に説明すると、
先ず、Vector3でPathの配列を作る。
そのあとに動きの制御のDOPathを利用する。
- 第1引数はPathの配列
- 第2引数は到着点に行くまでにかかる時間
- チェーンメソッドSetEase()は加速減速の方法
今回のケースだと、
(0, -750, 0)、(-450, 300, 0)を経由してに2秒かけて加速減速なしで向かう
となる。
これだけで完成となる。
OnTrigger系関数の利用に関わるCollider Component内のIsTrigger
結論:『OnTrigger系関数を利用するときは、少なくとも片方の衝突ObjectのColliderのIsTriggerがTureであれば良い』
Unityでシューティングゲームを作っているときに、
- 操作機の弾と敵機が衝突したら爆発
- 敵機の弾と操作機が衝突したら爆発
- 操作機と敵機が衝突したら爆発
- 弾同士が接触しても物理的挙動が起こらない
という制御をしたいと思った。
で、今回は上記制御するにあたり、物理的挙動は全て不要だったので、結論的には、
- 操作機のIsTriggerをTrue
- 敵機のIsTriggerをTrue
- 弾のIsTriggerをTrue
でOKであった。
Collider ComponentにあるIs Triggerは何かと言うと、
そのObjectがOnTrigger系関数を稼働させるトリガーになるかどうかというもの。
True: トリガーになる
False: トリガーにならない
そして、OnTriggerを発生させるための必要条件は他にも2つあり、 Rigidbody(2d) Componentを少なくとも片方の衝突Objectが有している必要がある。 RigidBodyというのは、物理的挙動を制御するComponent。
もう一つの必要条件は、 Collider Componentを両方の衝突Objectが有している必要があるということである。
OnTrigger系関数の利用条件をまとめると、
- 少なくとも片方のObjectのIsTriggerをTrueにする
- 少なくとも片方のObjectにRigidbody(2d) Componentをアタッチ
- 両方のObjectにCollider Componentをアタッチ
となる。
Float型数値の等価比較
Unityでシューティングゲームを作成している時、敵機の位置を読み取り、その位置がある値と等しいかを確認する必要が出てきた。
何をしたかったかというと、敵機の位置により、その動きのパターンを決めたかったということ。
そこで先ず、どのように敵機の位置を把握しようとしたかというと以下の通り。 (x座標が0という条件が当てまるかの確認)
if (transform.position.x == 0.0f)
しかしこの方法だと以下のような警告が出てしまった。
「Fix floating point number comparing. compare a difference with epsilon.」 「Comparison of floating point numbers can be unequal due to the differing precision of the two values.」
警告分は異なるが、記載してある内容としては、
「Floating型数値を等価比較する際はその精度の違いを考慮して、EPSILONを利用した比較をすべき」
というようなことを言っていると思う。
どうも一見同じに見える数値でも、Float型であると丸め誤差などで微妙に差が生じてしまい、全く同じにならないケースがあるようだ。
なので、Epsilonというとても小さい数値の定数を使用し、2つのFloat型数値が「おおよそ」同じが確認するということをするようだ。
そして、ググった結果、以下のようにコードを書き換えた。
if (Mathf.Approximately(transform.position.x, 0.0f))
このMathf.Approximatelyの詳しい内容は後述のリンクを参照して欲しいが、 簡単に内容を説明すると 「第一引数と第二引数の差がEPSILON(というすごい小さな値)いないかどうか」 を調べるというもの。 これを使えば同じだと想定されるFloat型数値の等価比較が誤差を気にせずできるようになる (と思う) docs.unity3d.com
ブログの記事がGoogleで検索されるようにすべきこと
先ほど自分の書き上げたブログの記事がGoogleで検索されない。
このような場合は、まだその記事がGoogleに登録されていないということが原因のようだ。
これを解決するためにはまず、Googleにこの記事を見つけてもらう必要がある。
そこで利用するものが「Google Search Console」である。
まずはブログをそのもの「Google Search Console」にて登録。
このブログそのものの登録自体は最初の一回きりなので、ここでは方法の記載は割愛。
次に問題の検索されないブログの記事をGoogleに登録依頼をする。
まず、下図のように「Google Search Console」の「URL検査」を押下し、上の検索バーでその記事のURLを検索する。
そうすると、GoogleがまだそのURLの記事を登録していない場合には、下図のような画面が表示される。
このようにGoogleがその記事を登録していないと、記事のURLやその記事の文章でGoogle検索しても表示されない状態ということになる。
なので、Googleにその記事を見つけて登録してください、というリクエストを送り、Google検索で引っかかるようにする必要がある。
そのリクエスト方法が、「インデックス登録をリクエスト」を押下。これだけである。
すると下図のようなポップアップが出現する
しばらくしてから、記事のURLや記事中の文章でGoogle検索をしてみると、下図のようにちゃんと引っかかることが確認できる。
ちなみに今回の場合は「インデックス登録をリクエスト」してからだいたい30分後には登録が完了していたようだ。
Screen Space-Camera時のJoystick Packの設定
Unityにてシューティンゲームを作成している際、Joystick PackのFloating Joystickを利用した。
今回、自分が作っているこのゲームではCanvasのRender ModeをScreen Space-Cameraと設定していた。
このScreen Space-Cameraだと、Floating Joystickの挙動が少し変だった。
具体的には下記のようになってしまった。
画面タッチした位置とFlaoting Joystickの出現位置がずれてしまっている。
しかもこれは一番最初のタッチだけで発生し、それ以降はタッチとlaoting Joystickの出現位置は同位置となり、正常となる。
この現象を解消するために、スクリプトを書き換えた。
具体的には、Joystick.jsのStart()部分とOnDrag(PointerEventData eventData)部分である。
おそらく、原因はFloatingJoystickのbackground.anchoredPositionが決まる前にcam = canvas.worldCameraの設定が効いていない事かと思う。
なので、background.anchoredPositionが決定される前にcanvas.worldCameraの設定を下記のように行った。
加えて、
こうする事で、タッチイベントが発生する前にcanvas.worldCameraの設定ができ、そのあとの余計な処理(OnDrag(PointerEventData eventData)内のコメントアウトしたところ)を省くことができる。
以上の書き換えを行ったところ、
最初のタッチ位置とFloating Joysickの位置が同位置にあるようになった。
UIがカメラ範囲外にレンダリングされてしまう場合の対処法
カメラの範囲外の領域にUI(今回はフロート型のジョイスティック)がレンダリングされてしまい、それが残り続けてしまう現象に遭遇した。
このような感じ。左下にジョイスティックの残骸があるのがわかると思う。
これがずっと残ってしまう為下記のように対応した。
「CanvasのRender ModeをScreen Space - Cameraに変更」
UIがレンダリングされ、残骸が残ってしまう場合の設定は、
Screen Space - Over layで設定されていた。
Render Cameraには画角設定しているCameraを設定。
このようにすると、下図のようにカメラ範囲外にUIがレンダリングされず残らない。