Unityで等速に移動する方法まとめ

基本的に全部右(1, 0, 0)に移動する場合について考えます。
その他の方向についても同様に出来ると思います。

Unityのバージョンは2019.3です。

Transform

Transform.positionの書き換え

単純に座標の足し算です。
これらの処理はfpsの影響を受けるのでUpdateで書く際にはTime.deltaTimeを掛けましょう。(そうしないとfpsによって速度が変わります)

private void Update()
{
    transform.position += Vector3.right * Time.deltaTime;
}

また、FixedUpdateで書く場合はTime.deltaTimeは必要ありません。

private void Update(){
    transform.position += Vector3.right * 0.02f;
}

Transform.Traslate

Transform.positionの書き換えと原理はほぼ同じですが、Unityの関数を利用します。
fpsの影響を受けるという点でも同じです。

private void Update(){
    transform.Translate(Vector3.forward * Time.deltaTime);
}
private void Update(){
    transform.Translate(Vector3.forward * 0.02f);
}

違いとしては、引数に指定する数値がワールド座標ではなく対象のオブジェクトからみた進行方向で指定するという事です。
Vector3.forwardを指定すれば前方(向いてる方向)に進み、Vector3.rightを指定すれば右に進みます。

このようにTransformの利用はシンプルで分かりやすいです。
しかしRigidbodyやColliderとの相性が悪かったりしますよね...。 (例えば、Rigidbody.velocityの値は変わりません)

Rigidbody

ここから先はRigidbody及びColliderを利用する場合の話です。 Rigidbodyを利用した物理演算に関する処理は必ずFixedUpdateで行います。

velocityの値を書き換える

Rigidbodyがもつ速度のパラメータであるvelocityの値を上書きします。

private void FixedUpdate()
{
    GetComponent<Rigidbody>().velocity = Vector3.right;
}

Rigidbodyを使った一番シンプルな方法かと思います。
ただしこのようにvelocityを直接書き換えてしまうと、他の物理演算の影響を受ける時に問題になる事が多いです。

AddForce + velocity を使う

velocityの書き換えは問題になることが多いので、AddForceを利用します。 しかし単純にAddForceを繰り替えすだけでは、ひたすら加速してしまいます。

そこで速度の遅い時には力を強めて速い時には弱める事で、等速を維持します。
自転車を漕ぐときに最初は力を入れて踏み込み、スピードに乗ったら徐々に力を抜くのに似ていますね。

これをUnityで実装してみます。
自身の速度はrb.velocity (rbはRigidbody)で取得できます。
これを減算する事で、遅い時は強く、速い時は弱い力を与える事ができます。
(つまり厳密には最初から等速ではなく、凄い速さで加速するだけで"ほぼ"等速と言えます)

private void FixedUpdate(){
    var rb = GetComponent<Rigidbody>();
    const float targetVelocity = 2;
    const float power = 20;
    rb.AddForce(Vector3.right * ((targetVelocity - rb.velocity.x) * power), ForceMode.Acceleration);
}

f:id:tmls:20200923190634g:plain

これで等速になりました。

しかしtargetVelocity = 2としたのに実際には1.4しか出ていないのは気になります。
これは摩擦が影響していて、↓のように摩擦0のPhysic Materialを作成して、

f:id:tmls:20200923191226p:plain

Cubeのコライダーに設定すれば、

f:id:tmls:20200923191346p:plain

velocityが2になっている事を確認できます。

f:id:tmls:20200923191737g:plain

現状、私はこの方法がベストなのではないかと思っています。

AddForce + 空気抵抗 を使う

Rigidbodyのdragの値は抵抗の値を表しています。
抵抗はF = kvの式で表され、速度に比例して変化します。

なので終端速度というものが存在し、徐々に加速して一定の速度に達するとそこからは等速になります。
雨粒がどれだけ高いところから落ちてきても、全部同じ速度なのと同じ原理です。

この終端速度を使って等速を表現します。
まず下記のようなスクリプトを作成し、

private void FixedUpdate(){
    const int power = 25;
    GetComponent<Rigidbody>().AddForce(Vector3.right * power, ForceMode.Acceleration);
}

続いてRigidbodyのdragの値を大き目に設定します。

f:id:tmls:20200923175835p:plain

これで動き始めは加速、しばらくすると等速になるかと思います。

f:id:tmls:20200923175415g:plain

徐々に加速したい場合には良いかもしれません。

摩擦を0にする

コライダーに設定可能なPhysic MaterialはデフォルトでNoneになっていると思いますが、これは摩擦が0であるわけではありません。
Noneの時には、デフォルト値としてDynamic Friction = 0.6 Static Friction = 0.6が設定されています。

従ってこれを上述の方法でDynamic Friction = 0 Static Friction = 0にして例えば、

private void Start()
{
    GetComponent<Rigidbody>().velocity = Vector3.right;
}

このように初速のみを与えれば、あとは速度が維持され等速で動き続けることになります。 ただしこれは氷の上を滑ってるのと同じなので、障害物に当たれば減速したり止まったりします。

AddForce + 摩擦 で等速にすることは可能か?

AddForceと摩擦を使うと、何となく等速に出来そうな気がしますが基本的には出来ません。

摩擦力はF = μNの式で表され、垂直抗力に比例します。 垂直抗力が重力のみの場合、摩擦力は常に一定の力を加え続けます。 従って、空気抵抗のように終端速度が存在しません。

ただし一応、摩擦力と全く同じだけの力を加え続ければ理論上は等速に移動が可能です。 摩擦分を打ち消すだけの力を加える事で、実質的に摩擦力が0にするという話です。

下記のコードは、その一例です。

        private Rigidbody m_rb;
            
        private void Start()
        {
            m_rb = GetComponent<Rigidbody>();
            m_rb.velocity = Vector3.right;
        }

        private void FixedUpdate()
        {
            var col = GetComponent<Collider>();
            Vector3 g = Physics.gravity;
            float m = m_rb.mass;
            float u = 2 * col.material.dynamicFriction;

            float F = u * m * g.y;
            rb.AddForce(Vector3.right * -F, ForceMode.Acceleration);
        }

今回はuの計算を自身のコライダーに設定されたDynamicFrictionの値であると仮定しています。 実際にはこの条件が成立しないこともあるので、上記のコードは常に動くとは限りません。

このように、摩擦を用いた等速の表現は非常にシビアで汎用性が低い事が分かります。 また今回紹介してきた方法は全て摩擦の影響があっても無くてもpowerの値が十分に大きければ、正しく動作するはずですので、摩擦については自由に設定して良いかと思います。

まとめ

Unityで等速に移動する方法を見てきました。
どの方法を使うかは、ケースバイケースですので合ったものを利用いただければと思います。

私のおすすめとしては、物理演算の影響を受けられ即座に等速にすることができる「AddForce + velocity」が汎用性が高いと思うので困ったら試してみてはどうでしょうか。

bug.nの設定

よく使うもの

キー 動作
win k アクティブウィンドウを一つ上に切り替え
win j アクティブウィンドウを一つ下に切り替え
win h メインウィンドウを左方向にリサイズ
win l メインウィンドウを右方向にリサイズ
win shift h ウィンドウサイズを大きくする
win shift l ウィンドウサイズを小さくする
win shift c 現在のウィンドウを閉じる
win , 左のモニターの切り替え
win . 右のモニターの切り替え
win shift , 現在のウィンドウを左のモニターに移動
win shift . 現在のウィンドウを右のモニターに移動
win ctrl o 元のウィンドウに戻す(最大化の解除など)
win num numの仮想モニターに移動する

たまに使うもの

キー 動作
win ctrl メインウィンドウの数を増やす
win ctrl メインウィンドウの数を減らす
win ctrl i ウィンドウの情報を表示する
win d ウィンドウの入れ替え
win i ウィンドウの入れ替え

iniファイル

↓にiniファイルを置いた。

github.com

主に下記サイトのサンプルで、joten'sの見た目とdwm look-alikeのキーコンフィグを融合させている。 github.com

また、このキーコンフィグの際にWin + lの組み合わせがWindows側で設定されており、さらにAutoHotKeyを使っても上書きできなかった。
なので、↓のサイトを参考にレジストリを直接いじって無効にした...。

okwave.jp

Windowsの見た目を最強にする

f:id:tmls:20200918094136p:plain

f:id:tmls:20201102130935p:plain

f:id:tmls:20200927220326p:plain

タスクバーを真ん中に配置

www.youtube.com

また、同時に入るTaskbarX Configurationで透明度なども設定できる。

タスクバーを透明にする

↑の方法以外でもタスクバーを透明にすることが出来る。こちらの方が色々設定できそう? soundartifacts.com

Windowsのテーマを変更

↓の動画に従って、Windowsのパッチを当てる。

www.youtube.com

↓おすすめのテーマ

Nord Windows 10 Themewww.deviantart.com

邪魔だからWindowsメニューの全部のピン止めを外す. 大きさも一番小さくする.

www.howtogeek.com

Rainmeterをダウンロード

www.rainmeter.net

Rainmeterのスタイルをダウンロード

visualskins.com

Chromeのテーマを変える

↓のサイトからテーマをダウンロードして、 Nord Theme for Chrome V2www.deviantart.com

↓のサイトに従ってChrome拡張を手動で入れる。 www.cnet.com

さらに、Chromeのショートカットの プロパティ >ショートカット > リンク先--disable-windows10-custom-titlebarを後ろに追記する。
同様にタスクバーにあるChromeのショートカットもCtrl + Shift + 右クリックでプロパティを開いて--disable-windows10-custom-titlebarを追記。(Chromeを閉じた状態で行う)

Dockの導入

いくつか種類があるようだけど、私はNuxusを利用した。

www.cnet.com

↓に従ってスタイルを変更できる。

www.youtube.com

でもなんか重すぎるのでやめた。

ウィンドウのタイル表示

Window Manager系のもので、評判が良さそうなbug.nを利用した。

github.com

初心者の私にはあまりにもショートカットが多すぎたので、使いこなせるか微妙。
↓のサイトに日本語での主要ショートカットの解説がされている。

wiki.mma.club.uec.ac.jp

↓私の設定はこちらに

tmls.hatenablog.com

カーソルの変更

↓がおすすめ

Crystal Clear v4.1 | Material Darkwww.deviantart.com

Anathema Pink Cursorwww.deviantart.com

downloadして、中にある.infファイルを右クリック → インストールで大抵はインストールできる。
インストールしたら、Windowsのマウス設定 > その他のマウスオプション > ポインター からデザインを選択できるはず。

ウィンドウの透過

Actual Transparent Windowを利用した。
無料ではないのだが、カスタムも充実していたため満足している。

非アクティブのウィンドウの透明度を下げるのがおすすめ。

www.actualtools.com

NvidiaのOverlayが透過処理に反応してしまって、画面全体が暗くなっていたので、NvidiaのOverlayを透過の対象から除外する設定が必要だった。

タイトルバー、ボーダーの色、大きさを変更

Winaeroを利用した。

winaero.com

ただし、この辺りの変更をするには↓の制約がありそうだった。

  • ウィンドウのサイドのボーダーのサイズを変更するには、テーマをAero lightにする必要がある。
  • InActiveなウィンドウの色を変更するには、テーマをWindows10のデフォルトにする必要がある。

ウィンドウの影の色を変える

ShadowFXを利用した。 Transparency 80% Blur level 20% Factor 4px くらいがすき。

www.stardock.com

好きな色味

おまけだけど、好きな色合いを書いておく。

寒色系

項目 rgb カラーコード
背景 33, 33, 33 #212121
アクセントカラー 64, 217, 255 #40D9FF

暖色系

項目 rgb カラーコード
背景 33, 33, 33 #212121
アクセントカラー 168, 217, 149 #A8D995

コツ

  • 各ウィンドウの背景色をそろえる
  • 壁紙の色とアクセントカラーを近いものにする

Git Bashの見た目を整える

blog.mamansoft.net

基本的に↑の方のものを利用させていただいた。

ただ名前のところが長すぎるので、~/.pureline.confを開きモジュールを一部非表示にする。

# All modules are enabled. Uncomment/comment to enable/disable a module
declare -a PL_MODULES=(
    # Module                Background  Foreground
#    'time_module            MyLightGrey Black'
#    'battery_module         MyBlue      Black'
#    'user_module            MyLime      Black'
    'ssh_module             MyYellow    Black'
    'virtual_env_module     MyBlue      Black'
    'path_module            MyBlue      Black'
    'read_only_module       MyRed       White'
    'background_jobs_module MyPurple    White'
    'git_module             MyGreen     Black'
    'return_code_module     MyRed       White'
    'newline_module'
    'prompt_module          MyDarkGrey  White'
)

# Module Options
PL_PATH_TRIM=1             # 0 Full path, 1, Current, 2+ trim level

github.com

【Unity】Photonで同じ名前のルームがあるのにphoton game does not existエラーが出る場合の対応

問題

Photon Unity Networkingで、同じ名前のルームを作成/参加するときにphoton game does not existのエラーが出たり、Join出来ずに新規にルームが作成されてしまうことがある。
下記の関数で上手くいかない事象を確認している。

JoinOrCreateRoom
JoinRoom

原因

リージョンが違う可能性がある。
デフォルトでは、Photonが自動で最適な接続先サーバーを選択するが、同じ場所で接続しても違ったリージョンに繋がる場合がある。

現在接続中のリージョンは、下記のスクリプトを書けば確認できる。

Debug.Log(PhotonNetwork.CloudRegion);

対策

接続先のリージョンを指定する。
Assets > Photon > PhotonUnityNetworking > ResourcesにあるPhotonServerSettingsを選択し、Settings > Fixed Regionjpと入力する事で日本サーバーに接続する事ができる。

指定可能なリージョンは下記のサイトで確認できる。(Tokenの文字列を入力する)
doc.photonengine.com

海外展開を考えている場合は基本は自動接続設定にしておいて、必要に応じてユーザーにリージョン選択できる機能を作成するのが良いかもしれない。
その際は下記のようにスクリプトからリージョンを指定すると良い。

PhotonNetwork.PhotonServerSettings.AppSettings.FixedRegion = "jp";

CUDA driver version is insufficient for CUDA runtime version への対応

WSL2でCUDAを使おうとして、サンプルを起動したら下記のエラーが発生。

CUDA driver version is insufficient for CUDA runtime version

大抵の場合、ドライバーとのバージョンの違いが原因らしい。

NVIDIAのドライバーを最新のものにして(カスタムインストールで全部入れた)、
PowerShellwsl --updateを実行したらあっさりなおった。

Unityで画面端がちらつく問題への対応

問題

f:id:tmls:20200829014726p:plain めちゃくちゃ分かりにくいが、画面の端に1ピクセル分くらい白い線が出ている。

解決方法

CameraのViewportRectを(X:0, Y:0, W:1, H:1)にする。 何かの拍子にこの値が0.99みたいになっていたのが原因だった。