Unreal Engine 4.24 でアクターに初速を与えたり、力を加えたりする

ボールをUE4で転がしたり、投げたり、移動方向や速度をコントロールする方法についてのメモです。

単純にアクターをムーバブル(movable)に設定して Simulate Physics にチェックを入れただけでは、速度を与えることはできません（多分）。いくつか実現方法はあるようですが、ここでは Projectile というコンポーネントを使って、初速を与える方法についてメモしておきます。

# やること

- 重力で落下したり、坂を転がったりするボールを作る。
- ボールに初速だけ与えて、あとは自然に（物理シミュレーションで）動かす。
- ボールの速度や向きを、任意のタイミングで変更する。

# 準備

ThirdPerson テンプレートでベースのプロジェクトを作ります。もちろん ThirdPerson でなくても同じことはできますが、お約束なので ThirdPerson を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/85992c70-bb1e-ce3f-1c84-da6a4587ffa0.png)

プロジェクト名は BallSample としておきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/b6fce151-066d-dc3d-f714-4ac72e4ad0e2.png)

Alt+Pでプレイ可能なことを確認しておきます。

# 手順

## 重力で落下したり転がったりできるボール(sphere)を配置する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/efc02281-89ec-eaf5-486a-97e09b7e4670.png)

「基本」の中の「スフィア」をメイン画面内にドラッグドロップで配置します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/e706d764-2b23-b411-ed43-c706454bf49e.png)

最初から配置されている階段の最上段の真上あたりにスフィアを配置します。重力が働いていれば、階段の上に落ちて階段を転がるはずです。プレイヤーの目の前に階段があるので、プレイ開始直後に動作を確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/892cd6f7-c4b0-d77a-828e-28c23a2e0d29.png)

スフィア（Sphere） を選んだ状態で、右下の「詳細」の中を見ていくと Simulate Physics という項目があるので、そこにチェックを入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/28acb240-ef11-ad11-11e4-6747a1767ae2.png)

その下の Enable Gravity にチェックが入ってることも確認します。これで、重力がスフィアにはたらくようになり、空中から落ちて階段を転がり落ちるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/0285796a-9617-a517-fca5-895fe6a538ab.png)

Alt+Pでプレイすると、スフィア（ボール）がちゃんと階段を転がり落ちてきます（よね？）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/03bc15b0-ab86-42c2-60b0-01d37e27e9fc.png)

もし動かなければ、スフィアの「詳細」の「トランスフォーム」の項目にある「可動性」のところが「ムーバブル」になっているかを確認します。

## ボールに初速を与える

スフィアに速度を与えて動かすためには、Movement というコンポーネントをスフィアに追加する必要があります。Movement にはいくつか種類がありますが、ここでは一番汎用性が高い Projectile Movement コンポーネントを使います。

1. スフィアにブループリントを追加する
2. Projectile Movement コンポーネントを追加する
3. 初速を設定するブループリント（グラフ）を追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/f1813ebd-91e3-6fc1-87d6-4e96ecbf42ec.png)

スフィアを選んだ状態で「ブループリント/スクリプトを追加」を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/55e7909b-18bf-c377-4867-d62e90d27d2e.png)

このウィンドウが出たら、そのまま「ブループリントを作成」を押します。この操作で Sphere の名前が Sphere_Blueprint に変更されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/c6f5aa99-f9f6-ff9a-2060-cca1196bf586.png)

こんな画面が出るはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/9ad31e02-554c-c182-fcab-9bc08d4ea512.png)

左側にある「コンポーネントを追加」のボタンを押して、Movement と入力します。すると、いくつか候補がでてくるので、Projectile Movement を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/012490da-e4cd-1fee-8d68-63539055c1e7.png)

こんなふうに、Projectile Movement という項目が追加されるので、作成された項目を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/1bfd7d3e-e8a5-fb74-772e-2af73547d65c.png)

右側の「詳細」の中から Initial Speed を選んで、1000 と入力します。これが初速になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/cdcc3ada-e70a-68a8-d4a1-8bebdc8d0c32.png)

さらに下のほうにある、ベロシティの中の X の項目を -1 にしてみました。初速はこのベロシティの値に Initial Speed を乗じた値になります。X,Y,Zを別々に設定することで、運動する向きの情報を与えることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/f9f73153-0f57-c7b9-47b4-dda3c56bb532.png)

これでコンパイルして実行します。

![ue1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/6781ff9e-a9b0-cedd-23ed-01ca5fa1ca29.gif)

ボールがすっ飛んでくるようになりました。Initial Speed を変えたり、ベロシティのX,Y,Zの値を変えると、好きな方向に飛ばすことができます。

## Enterキーを押したときにボールの移動中に移動方向を変える

Initial Speed を使う方法では、物体の初速を与えることはできますが、動き始めた後の物体の速度を変えたり、移動方向を変更したりすることはできません。SetVelocity とかノード置けたりするので、そこに値を設定したら速度が変えられるのかと思いきや、そういう方法では変更できません。

動き出した後のアクターの速度を変えたい場合は、AddForce または AddImpulse のノードを使う必要があります。使い方自体はほぼ同じですが、結果が若干異なります。

ここでは Enter キーを押したときに、ボールが真上に跳ねるようにしてみます。Enter キーの入力を拾いやすいように、レベルブループリントにプログラムを書くことにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/3d5395bd-b79e-3a1d-a1be-d20bc6a951c2.png)

メインウィンドウの「ブループリント」から「レベルブループリントを開く」を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/82e283c6-b2e9-507a-74b3-da99379688a6.png)

こんな画面が開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/714eacf6-3bf9-803f-b847-3bb0f7178689.png)

**メイン画面側で Sphere_Blueprint を選んだ状態で、レベルブループリントの編集画面で右クリックする**と、メニューに Sphere_Blueprint のリファレンスを作成という項目が出るので、その項目を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/10020007-dbe9-1b95-f66b-6bc664419d48.png)

操作が成功すると、このようなノードができます。この操作で、レベルブループリント内から、Sphere_Blueprint （画面内に置いたボール）を操作できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/807c9fcc-2d1c-f30d-2650-8b586e8b6713.png)

イベントグラフ内で右クリックして Enter と入力します。すると、キーボードイベントの Enter という項目が選べるので、それを選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/42bdb80b-31b5-6887-dd1e-cc31a681ec83.png)

さきほど設置した Sphere_Blueprint のノードから線を伸ばしてマウスのボタンを離し、AddForce と入力すると AddForce の項目が選べるので、それを選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/63dc07f2-bb56-04bf-c1f4-dc39deefb5c8.png)

AddForce ノードが置かれたら、上の図のようにつなぎます。Static Mesh Component ノードは自動的に追加されるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/c22161fb-26a2-faef-35af-7ebb43485878.png)

AddForce の Force の Z の項目に 10000000 と入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/f9f73153-0f57-c7b9-47b4-dda3c56bb532.png)

これでコンパイルして実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/a02d9ecd-9afc-288a-b017-4219974bae70.png)

Enter を押すとボールが 2m くらい跳ねます。

AddForce に入れた数値がやたら大きいですが、スフィアの重量がデフォルトで 100kg 少しあるので、1000000 くらいの数値を入れて、初めて「少し跳ねてるかな？」くらいの感じになります（注；UE4 は長さの単位が cm なので、1N = 1kg m / s^2 = 100 kg cm / s^2 となり、100 と入れて 1N 相当になる）。AddForce してるのに動かないという場合は、アクターがムーバブルになってないか、数字が小さすぎるかのどちらかのことが多いです（多分）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/1c5021a5-130e-c5ab-2b55-85040a0e15c1.png)

質量によらず、同じ動きをさせたい場合は、AccelChange にチェックを入れます。こうすると、どんな物体でも 1kg の物体であるかのように扱われます。約100㎏ のスフィアの場合、上の図のように AccelChange にチェックを入れない場合の 1/100 程度の数値にすると、だいたい同じ動きになります。

## AddImpulse を使ってボールを跳ねさせる

AddForce を AddImpulse に置き換えてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/84097a73-c9bb-2098-724d-bca2dec6015e.png)

AddForce の代わりに、AddImpulse と入力して出てきた項目を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/03d9b5e3-8295-c646-7ac0-caadd9b25b47.png)

Implus の Z の数値を 50000 程度にします。これで、コンパイルしてプレイし、Enter キーを押すと AddForce と同じようにボールが跳ねます。

## AddForce と AddImpulse は何が違うのか

一見同じように見えますが、**AddForce が「力」を加えるのに対して、AddImpluse は「力積」を与える**という点で大きく異なります。

AddImpluse は、最終的に物体に設定したい速度が決まっている場合で、一瞬でその速度までもっていきたい場合に向いています。例えば、バットでボールを撃つとか、弾丸を発射するといった感じです。名前の通り、一瞬だけインパクトがかかるようなシチュエーションです。

一方の AddForce は、加わる力はわかっているけど、最終的に到達する物体の速度はわからないという場合に、継続的に物体に力を与えるような用途に向いています。例えば、重い金属の球をゆっくり押してだんだん加速させるとか、噴射しているロケットエンジンで飛翔体を加速させる、といった感じです。

力を与える系のノードは、これら以外にも AddForceLocation, AddRadialForce, AddAnglarLocation などいろいろあります。それらについては、下記記事が詳しいです。

- [第一次 Add Force / Add Impulse 戦争](http://ikagamedev.hatenablog.com/entry/2017/02/01/204221)

# おまけ

デフォルトではボールがやたら転がりすぎる（摩擦が少ない）ので、少し転がりにくくする方法についてメモしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/104faf94-7d38-d43e-043a-9f7c429f0680.png)

ボール（Sphere_Blueprin）を選んだ状態で「詳細」の中の Anglar Damping の数字を 1 とか 2 とかの数字にします。3くらいにすると、かなり転がりにくくなります。

この数値は、地面に対する摩擦力ではなくて、ボールの回転そのものに対する抵抗力を表しています。そのため、回転した状態で空中を飛んでいても、回転はだんだん遅くなります。