VideoPlayerをフレーム送りで再生する
動作環境
Unity2020.3.21f1
概要
VideoPlayerによるmp4動画のフレーム再生を行います。
再生方法はURLを指定するものとします。
コードについて
基本的なフレーム送りはVideoPlayer.StepForward()で行えます。これは1フレーム進めて描画するための関数です。指定したフレームへの移動は行えません。
注意・補足
再生するための準備としてVideoPlayer.Prepare()を呼んでおいて、VideoPlayer.isPreparedがtrueになるのを待ちます。これをしないとVideoPlayer.frameRateが0で呼び出されることがあります。
mp4ファイルの長さを取得したいとき、VideoPlayer.clip.lengthはURLでは取得できません。VideoPlayer.lengthを使用しましょう。
動画フォーマットについて
今回実装に使ったmp4フォーマットはH264 baseprofileです。
仮にmainprofileで再生を行うと以下のWarningが出力されます。フレームが飛ぶ等の原因になりそうなので回避しておくことを勧めます。
Unexpected timestamp values detected. This can occur in H.264 videos not encoded with the baseline profile. Timestamps will be skewed to correct the playback
エンコーディングについては以下のサイトを参考にしました。
ログをちょっと多く表示するConsoleビューハック
Unityを使う上で欠かせないConsoleビューはデフォルトで2行ずつ表示になっています。これを1行にする方法を紹介します。
しかし、このログをよく見るとUnityEngine.Debug.Log(object)が表示されていることがほとんどで正直要らない気がする。スペースは有効に使いたい。
右上の三点リーダーをクリックすると設定項目が隠れている。
1行に設定すると多くのログが見れるようになりました。ログ探しが少し楽になります。ぜひ使ってみてください。
NavMeshの分かりにくいトコ
NavMesh height slope radius、そんなワードで検索をかけているあなたに伝えたいNavMeshの分かりにくい特徴について少しだけ触れます。
こんなところで時間を費やしたのは僕だけでしょうか、いやそんなはずはない。
僅かな気になりポイントを書きます。
まずはこちらをご覧ください。NavMeshの一部分が消えてしまっているように見えると思います。
このマップの元の状態は以下の通り。凹凸のある地面なので、高さHeihgtや坂Slopeの設定に問題があり、うまくBakeされていないのではないかと思いました。
しかし、それは誤りです。凹凸のあるメッシュオブジェクトを試しに消してみると以下のようになります。つまりは正しくNavMeshは生成されていたのです!
NavMeshのBakeが上手くいかないと思っていたら実はそんなことはなくて、NavMeshの下にあるメッシュが見えていただけだったというお話でした。
この徒労感よ!!
Generic Interfaceとかいうやつ
Genericなインターフェースって実装しようとするとどうなるんだろうと思ってやってみました。JetBrains Riderによる補完された答えは以下の通りです。
そんな定義の仕方があるんだなーって参考になったのでご紹介です。
public interface ITestInterface<T>
{
T GetData();
}
public class TestData{}
public class SamleData{}
public class TestScript : monobehaviour, ITestInterface<TestData>, ITestInterface<SamleData>
{
TestData ITestInterface<TestData>.GetData()
{
throw new System.NotImplementedException();
}
SamleData ITestInterface<SamleData>.GetData()
{
throw new System.NotImplementedException();
}
}
静的ゲームオブジェクトでおかしいと思ったら
Unityには静的ゲームオブジェクトという機能が備わっています。
調べればすぐに出てくるし、staticにチェックを入れるだけでライティング等の負荷を削減できます。
しかし、私の知識は古かった。
staticのチェックを入れてるのにパフォーマンス変わらないな。
影動くけどおかしいな。
そう思ってLightingSettingsを見てみると・・
AutoGeneratingのチェックがデフォルトでオフになってる!!
ので、しっかりと自身でGenerateLightingしましょうという話。
JellyPutiプライバシーポリシー
Unityにおける座標移動の実装方法まとめ
座標移動の実装を考える時、度々「もっと良い方法があるんじゃないか」となることが多いため、まとめていこうと思う。
考慮すべき事柄
実装内容によってベストな実装は異なると考える。よって、考慮すべき事柄もまとめておく。
1. Y軸移動が存在するか
2. 障害物が存在するか
3. 坂は存在するか
TimeScaleによる挙動の差異に関しては考慮しないこととする。
処理負荷について考慮しないこととする。
ネットワーク通信等の外的要因も同様に考慮しない。
実装方法(利用クラス)
1. Transformクラスを経由する
メリット
最も手軽で直感的に座標移動ができる。
デメリット
その他のオブジェクトの影響が考慮しづらい。障害物があった際にはすり抜けてしまう。衝突判定だけRigidBodyを駆使したとしても、物理挙動と併用すると干渉してバグとなることが多い。坂も同様で、面に沿う動きを実現するには計算が必要。
2. RigidBodyクラスを経由する
メリット
手軽に障害物を考慮できる。重力も手軽に実装でき、PhisicsMaterialを実装すれば摩擦も制御できる。
デメリット
非現実的な動きに向いていない。RigidBodyは物理挙動を実装するためのものなので当然ではあるが、そのため速度の調整が難しいことがある。
坂を上るときにX方向にのみ力を加えた場合には力のベクトルが変化するため与えたパラメータとは異なる量の移動になったりする。
3. NavMeshAgentクラスを経由する
メリット
ルート探索などAIの実装に向いている。障害物も考慮できる。
デメリット
実装手順が多い。障害物が移動する場合等では更に手順が増えていく。
また冗長にも感じられる。当たり判定にはどのみちCollider・RigidBodyを使うことになるので移動以外の実装を考慮してしまうと無駄が多く感じる。
実装方法(計算手法)
計算方法は制作するゲームによって確実に最適解が変わると思う。各種クラスにはそれぞれ異なる計算手法が取れるように機能が実装されていることが多いので、あまり強く意識する必要はないと思う。