質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Unity

    4019questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

transform.positionとtransform.Translateだとどちらが適切か。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 524

tkmnusr

score 162

 前提・実現したいこと

ゲームオブジェクトの位置移動では、
transform.positionを変える方法とtransform.Translateによる方法があると思いますが、
この2つの違いや、どちらが適切かをご教示いただけませんか?
一定の速度で自然に移動させたいと考えています。
また、今回、一定の速度で移動させることを考えているので、Rigidbodyを使った移動は考えていません
(Rigidbodyは一定の速度で移動しないはず)。

 試したこと

こちらのサイトによると、
transform.Translateよりもtransform.positionの方が処理速度が速いと書かれていました。
単純にこれだけの情報で考えると、transform.Translateよりもtransform.positionを変えたほうがいいように思えますが、
transform.Translateを使う利点はないのでしょうか?

何かのサイトで、transform.Translateはtransform.positionを変えるよりも動きが滑らかになると書かれていたのを見た気がするんですが、(それがうろ覚えでそのサイトのURLも忘れてしまい、本当にそう書かれていたかどうかも自信がないのですが)、
本当でしょうか?

動きが滑らかになるのが本当であれば、多少処理速度が遅くてもtransform.Translateを使いたいと考えています。

また一定の速度で移動させたいので、transform.Translateでもtransform.positionでも、どちらの場合でも、
Time.deltaTimeは掛けるべきでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

移動に関する処理については、こちらの記事内の比較が面白いと思います。

「僕Unityできますよ」Tシャツのコードレビュー - Qiita
https://qiita.com/YamadaGames/items/cde2162b52ba80bc0beb

他のオブジェクトとの衝突などを考慮する場合には、transform.position の変更よりも transform.Translate や  Rigidbody の各種メソッドを使うほうが確実、ということのようです。
(※ sakura_hana さんの指摘を受けて一部訂正しました)

上記の記事内で、Time.deltaTime を掛けることについてもコメント含めて記述があります。Update() メソッドはプログラムを動作させる環境によって1秒間あたりに呼び出される回数が異なるため、その差異を吸収するためには Time.deltaTime を掛けるのが有効なようです。

どういうものなのかを理解した上で使い分ける、というのがよいのだと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 20:27

    横から失礼します。
    transform.Translateも物理演算を引き起こさないので衝突するオブジェクトに使うのは危険です。
    リンク先の画像で跳ね返っているのは、移動速度が遅い為に「衝突を無視して壁に埋まる→移動が終了した瞬間に物理演算発動→壁からはじき出される」という動きです。

    キャンセル

  • 2018/06/08 20:28

    なるほど、正確な解説ありがとうございます。

    キャンセル

  • 2018/06/08 20:39 編集

    ご回答ありがとうございます。また、sakura_hana様もご指摘とご解説ありがとうございます。
    衝突を考慮するならば、そもそもtransform系の移動が非推奨ということなんですね。
    Rigidbodyでの移動は一定の速度でないと思い込んでいましたが、velocityで設定するのであれば、
    一定速度で移動できるみたいですね。

    キャンセル

  • 2018/06/08 20:51

    > Rigidbodyでの移動は一定の速度でない
    velocityで設定する他、(こちらも厳密に試していませんが)摩擦・重力ゼロにしてAddForceした場合も慣性の法則で一定速度で動き続けるんじゃないかなーと思います。
    第二引数の指定によって普通の加速(徐々に力が込められる)か瞬時に最高速に達するか変えられたりもします。
    http://d.hatena.ne.jp/nakamura001/20120320/1332224186

    キャンセル

  • 2018/06/08 21:04

    > tkmnusr さん
    物理演算をUnityに頼るなら、移動にもRigidbodyを使うのが便利だよという話だと思います。私の回答が原因で話が発散してしまったかも。

    なおRigidbodyのvelocityの値を直接いじるのも若干注意が必要なようで、理解した上で使い分けるのがよさそうです。
    https://docs.unity3d.com/ja/current/ScriptReference/Rigidbody-velocity.html

    (Unity公式の Space Shooter tutorial などでも velocity を直接変更しているので、絶対ダメというわけではないのでしょう)

    移動処理は突き詰めるとなかなか難しいですね。。。
    個人的にはカメラやUI要素の移動などで物理演算を必要としないものにはTransform.position の値変更や Transform.Translate を使っていますが(そのときの用途で使いやすいほうを選択)、アクションゲームのプレイヤーキャラクターなどはRigidbodyを使って動かすことが多いです。

    キャンセル

  • 2018/06/08 22:10

    ご回答ありがとうございます。
    ご提示のページ拝見しました。
    なるほど、非現実的という意味では、直接いじるべきではないということですね。
    今回自分は、入力してから瞬時に一定の速度で移動させることが目的だったので(transform系のような動きの移動)、直接velocityをいじる方法が、物理演算による衝突も加味された上で一定速度で移動できるので、ベストな方法だと理解できました。
    ありがとうございます。

    キャンセル

checkベストアンサー

0

transform.positionは「指定の場所に移動」、
transform.Translateは「現在地から指定の値だけ移動」です。

例えばUpdate内で
transform.position = Vector3.right;とすれば「(1,0,0)に居続ける」ことになりますし、
transform.Translate(Vector3.right);とすれば「ワールド空間(1,0,0)方向に移動し続ける」ことになります。

逆に言えば
transform.position = transform.position + Vector3.right;
transform.Translate(Vector3.right);は同じです。

で、リンク先のサイトですが、これ怪しい気がします。
「一定距離を一定回数移動した時間」を測っているとすれば、フレームレートに応じて変わります。
わかりやすいように1フレームあたりの移動量を「1m」、1回分の目標距離を「60m」とした場合、
60fpsの時は「1秒」で移動が完了しますが、30fpsの時は「2秒」かかります。
(1秒間に30回移動する=1秒間で30mしか進めない=60m進むには2秒かかる)

フレームレートは何もしなくても微妙にブレるものなので、例示されている誤差はすぐ出るのではないでしょうか。
また、数回実行した平均を取るべきでもあります。
(※実際に試してはいないので本当にtransform.Translateの方が早い可能性はあります)

この為、普通は係数に0.1fではなくTime.deltaTimeを使います。
これは「前回のフレームからの経過時間」なので係数として使うと、上記の例で言うと1フレームあたりの移動距離を60fpsの時は「1m」、30fpsの時は「2m」にしてくれるイメージです。

また上記の通り、positionもTranslateも移動するだけの処理なので、これを使ったからって動きが滑らかになる訳では無いです。
(もちろん移動量を小さくすれば滑らかに見えますがその分移動速度が遅くなります。早ければ途切れ途切れに見えます。現実世界と一緒です)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 20:49 編集

    ご回答ありがとうございます。
    positionとTranslateの違いがわかりました。
    一応、確認させていただきたいのですが、下記2点は合っていますか?
    ・衝突を考慮するならば、そもそもtransform系の移動が非推奨。
    ・velocityで設定するのであれば、Rigidbodyでも一定速度で移動できる(Rigidbodyでの移動はAddForceのように全て一定の速度でないと思い込んでいました)。

    キャンセル

  • 2018/06/08 20:56

    1つ目は、衝突=物理演算とするならばYes。(座標の比較等によって衝突判定を自力実装してやんよ!というケースならtransform系でもOK)
    2つ目はnegitamaさんのコメントで回答してしまいましたが、velocity以外でも一定速度での移動は一応可能です。(条件が限られるのでvelocity使った方が早いケースがほとんどですが)

    キャンセル

  • 2018/06/08 22:15 編集

    ご回答ありがとうございます。
    velocity以外の方法を下記のように検証してみましたが(第2引数はVelocityChangeが最適と思いました)、
    //右キーを押したときの処理。
    rb.AddForce(Vector3.right, ForceMode.VelocityChange);
    これでも確かに一定速度で動くのですが、
    左キーを押したときにも、
    //左キーを押したときの処理。
    rb.AddForce(Vector3.left, ForceMode.VelocityChange);
    とすると、右キーで右移動していた状態から、左キーで左移動に切り替えようとすると、
    velocityのときの実装とは違い、右から左への切り替え時に(おそらく)慣性の法則が働いてしまい、
    スムーズな切り替えにはならなかったです(左移動開始時に、加速してから一定速度に達しました。
    velocityで実装した場合は、切り替え時も瞬時に一定速度で左移動しました)。
    移動の切り替えも考慮すると、velocityを設定する方法しかないということでしょうか?

    キャンセル

  • 2018/06/09 13:31

    右への力を打ち消す為に一時的に左への力が多めに掛かってる感じなのかなーと思います。
    結局どれがいいかは「どう見せたいか」によるので、完全にキビキビ動かしたいならvelocity直接指定になるのではないかと思います。

    キャンセル

  • 2018/06/09 14:24

    ご回答ありがとうございます。
    大変勉強になりました。
    ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Unity

    4019questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。