どうも、チャーさんです。
あなたはUnityで動く床、それも滑り落ちず
往復するやつを作りたいと思っていますか?
この記事を読めばそれは実現します。
ですが読まないと結構つまづきます。
動かすのは簡単でも滑り落ちないが難しいでしょう。
ということでゲーム制作したいなら
このまま読んでください。動画はこちら
目次
Unityで動く床(滑らない、往復)を実現する方法
今回は動く床を作り、それを往復させて
かつその動く床に乗った時にオブジェクトも
一緒に動く様にする、
わけですが結論から言うと次のステップで可能です。
1まずは動く床用のオブジェクトを作る。
RigidbodyをつけIs Kinematicにチェック。
2次に床を動かすスクリプトを書く。
スクリプトでは、transform.positionで
動かすのではなく
Rigidbody系のMovePosition()という
メソッドを使って床を動かす。
(なぜならRigidbodyで動かすと動く床の上に
乗ったオブジェクトが滑り落ちなくなるから)
とこの2つのステップをやることで実現できます。
と言うことで早速詳しく説明します。
動く床用のオブジェクトを用意する
まず最初のステップですが、動かす床が
なくては始まりません。と言うことで
何かしら動く床用のオブジェクトを用意しましょう。
これは普通にCubeあたりをつかって
拡大、縮小ツールで横に伸ばしてあげれば
okです。
で、それができたらその動く床オブジェクト
にRigidbodyコンポーネントをつけましょう。
インスペクターのAddCompnentから
rigidと検索窓に打ち込めばでます。
それを追加したらIs Kinematicというのが
あるのでそこにチェックを付けましょう。
後述しますがこれは必須です。
これにてオブジェクトの用意は完成です。
Unityで動く床のスクリプト
それから次に動く床を動かすためのスクリプト
ですが、以下の様なスクリプトを書けばOkです。
と言うことで動く床を実現するのに
大事な部分などを説明をして行きます。
動く床で滑り落ちなくするためのメソッド
最初の結論部分でも書きましたが、
動く床を作る際、上に乗るオブジェクトが
滑り落ちない様にする、
床と一緒についていく様にしたい場合、
Rigidbodyで床を動かす必要があります。
でUnityではRigidbodyでオブジェクトを移動
させる方法が何個かありまして、
その1つがMovePosition()というメソッドです。
このメソッドは()の引数の部分に書いた座標に向かって
オブジェクトを移動させるというメソッドでして、
例えばMovePosition(new Vector3(1,1,1));などとしたら
座標の1,1,1,の部分にオブジェクトが
移動します。まんまですね。
(実際にはRigidbodyを取得する必要があるので、
上記の様に書くと動かないです。あくまで説明用です)
ちなみにこのメソッドの引数の部分にはVector3型で
座標を書く仕様になってます。
詳しい参照は以下のUnity公式のリファレンスにて。
https://docs.unity3d.com/ja/2018.4/ScriptReference/Rigidbody.MovePosition.html
またこのメソッドでオブジェクトを動かすと、
動く床の上に乗せたオブジェクトも
一緒に動いて滑り落ちなくなります。
(物理計算が働きます)
なので動く床を作る際、滑り落ちない様に
させたいならこのMovePosition()
のメソッドを使えばOKです。
動く床を往復させるためには
ですがこれだけだと片道移動になり、
往復運動にはなりません。
なのでここで更に、Mathf.PingPong()という
メソッドも使います。
公式リファレンス
https://docs.unity3d.com/jp/2018.4/ScriptReference/Mathf.PingPong.html
これは平たくいうとピンポン球の様に往復させるメソッド
でして数値を往復させることができます。
例えば0~10までの数値を往復して
出力するみたいな機能でして
例えば、0から数字が増えて10までいったら次は
数字が減って0に戻る、それをリピートみたいな
メソッドです。
なのでこれを使えば、例えばx座標を0~10の間で
往復させるということができますので、
動く床を往復させる場合、これを使うといいでしょう。
でこのメソッドでは1つ目の引数に
Time.timeで2つ目の引数は最大の数値を書きます。
例えば、
Mathf.PingPong(Time.time.10);と書けば、
0~10までの数値で往復しますし、
Mathf.PingPong(Time.time.100);と書けば、
0~100の間で往復します。
ということで今紹介したメソッドを
組み合わせて、言葉でスクリプト組むと
MovePosition(new Vector3(Mathf.PingPong(Time.time,10),y座標,z座標);
などとすれば左右に往復する動く床が
できるわけです。
実際にコード的には、MovePositionを使うには、
Rigidbodyコンポーネントを取得しないと
いけないので、
以下の記述の様にコンポーネントの取得は
必須になります。
private Vector3 startPos;
public Rigidbody rb; //rigidbody取得用
void Start()
{
startPos = transform.position;
rb = GetComponent<Rigidbody>();//これが取得
}
またMovePositionで動かすには
Update関数をFixedUpdateに書き換える
必要があります。(公式がそう言っています)
ということで以下の様になります。
こう書くことで動く床が往復し、かつ
滑り落ちない様になります。
Is Kinematicを忘れずに
またここで大事な点ですが、動く床のRigidbodyで
Is Kinematicという部分にチェックをつける
必要があります。
これを付けないとtransformと同じに
なってしまうので
なので、動く床のオブジェクトのインスペクター
を見て、Rigidbodyコンポーネントの
Is Kinematicにチェックを付け忘れない様にしましょう。
ということでここまできたら一度
動く床の上にオブジェクトを乗せるなり、
キャラを乗せるなりして、
ゲーム再生ボタンを押して動きを見てください。
床が動いていて、滑り落ちなければ成功です。
動く床の速度を上げる方法
でここで気づくかもですが、
動く床の移動速度がめっちゃ遅いでしょう。
ということでこれの速度を上げる方法です。
Mathf.PingPong(Time.time*4,12)
の様に第一引数Time.timeの後ろに
数字をかけましょう。
ここに数字をかけると動きが早くなるので、
public int speed;
と速さ用の変数を用意して、
Mathf.PingPong(Time.time*speed,12);
の様にその変数をかけてやれば
インスペクター上から動く床の速度をいじれます。
現在位置から床を動かすには
であとこのままですと、x座標が常に0
から始まってしまいます。
なので、
void FixedUpdate()
{
float posX = startPos.x + Mathf.PingPong(Time.time*speed,12);
rb.MovePosition(new Vector3(posX,startPos.y,startPos.z));
}
の様にして現在座標に対して、
pingpongで出力させる数値を足して、
現在位置から指定した距離往復する
動きに変えてあげましょう。
またこれで動く床は完成と言いたいですが、
上に乗るオブジェクト次第では、
回転してしまったりするでしょう。
その際はrigidbodyにある、
freeze rotationなどをチェックつければ
転がらなくなるので、
そのへんで調整しましょう。
まとめ
ということでまとめです。
往復する滑り落ちない動く床を作りたいなら
1まずは動く床用のオブジェクトを作る。
2次に床を動かすスクリプトを書く。
スクリプトでは、transform.positionで
動かすのではなく
Rigidbody系のMovePosition()という
メソッドを使って床を動かす。
Is Kinematicにチェックを忘れずに。
です。
ということで本記事はこれで以上です。
それでは読んでもらってありがとうございました。
それでわ。
チャーさん