【Unity】オブジェクトの位置と回転を低負荷に指定する

オブジェクトの位置と回転をスクリプトから変更したい場合、次のようなコードを書くことが多いかもしれません。

transform.position = new Vector3(1, 2, 3);
transform.rotation = Quaternion.Euler(0, 30, 60);

このような処理は、次のようにTransform.SetPositionAndRotationメソッドを使って書くことも可能です。

transform.SetPositionAndRotation(
    new Vector3(1, 2, 3),
    Quaternion.Euler(0, 30, 60)
);

後者の書き方にすることで、次のメリットが得られます。

メリット
  • 位置と回転を一度に指定できる
  • positionとrotationを別々に指定するより処理負荷が小さい

処理負荷が小さくなる理由は、Transformに送るメッセージが1回で済むようになるためです。このことは、以下スライドの13ページ目で言及されています。

こじゃらこじゃら

では具体的にどれくらい負荷が小さくなるの~?

このはこのは

実際に処理負荷を計測して確かめていくね。

Transform.SetPositionAndRotationメソッドにより位置と回転を指定すると、実際にどれくらい負荷が小さくなるか気になる方がいるかもしれません。

本記事では、Unity2021で実際に処理負荷を計測した結果をまとめました。

動作環境
  • Unity2021.1.25f1

スポンサーリンク

Transform.SetPositionAndRotationメソッド

メソッドの形式は次の通りです。

public void SetPositionAndRotation(Vector3 position, Quaternion rotation);

第1引数位置第2引数回転のクォータニオンを指定します。

両者ともワールド空間での指定となります。

参考:Transform-SetPositionAndRotation – Unity スクリプトリファレンス

処理負荷の検証

次の2パターンのスクリプトで処理負荷を検証していきます。

10万オブジェクトの位置と回転を毎フレーム更新し、更新にかかった時間をプロファイラより計測するようにします。

positionとrotationを個別指定

TestPattern1.cs
using UnityEngine;
using UnityEngine.Profiling;

public class TestPattern1 : MonoBehaviour
{
    private Transform[] _targets;
    private CustomSampler _sampler;

    private void Start()
    {
        _targets = new Transform[100000];

        for (var i = 0; i < _targets.Length; ++i)
        {
            var target = new GameObject("Target_" + i).transform;
            _targets[i] = target;
        }
        
        _sampler = CustomSampler.Create("Pattern1");
    }

    private void Update()
    {
        for (var i = 0; i < _targets.Length; ++i)
        {
            var position = new Vector3(
                Random.value,
                Random.value,
                Random.value
            );
            var rotation = Quaternion.Euler(Random.value, Random.value, Random.value);

            var target = _targets[i];
            
            _sampler.Begin();
            
            // パターン1 計測部分
            target.position = position;
            target.rotation = rotation;
            
            _sampler.End();
        }
    }
}

SetPositionAndRotationメソッドで指定

TestPattern2.cs
using UnityEngine;
using UnityEngine.Profiling;

public class TestPattern2 : MonoBehaviour
{
    private Transform[] _targets;
    private CustomSampler _sampler;

    private void Start()
    {
        _targets = new Transform[100000];

        for (var i = 0; i < _targets.Length; ++i)
        {
            var target = new GameObject("Target_" + i).transform;
            _targets[i] = target;
        }
        
        _sampler = CustomSampler.Create("Pattern2");
    }

    private void Update()
    {
        for (var i = 0; i < _targets.Length; ++i)
        {
            var position = new Vector3(
                Random.value,
                Random.value,
                Random.value
            );
            var rotation = Quaternion.Euler(Random.value, Random.value, Random.value);

            var target = _targets[i];
            
            _sampler.Begin();
            
            // パターン2 計測部分
            target.SetPositionAndRotation(position, rotation);
            
            _sampler.End();
        }
    }
}

実行結果

1フレームあたりのTransform更新にかかった時間の計測結果です。

パターン処理時間[ms]
positionとrotationを個別指定54.5
SetPositionAndRotationメソッドで指定49.0
計測結果

プロファイラでの計測結果も載せておきます。

positionとrotationを個別指定
SetPositionAndRotationメソッドで指定

概ね1割強のパフォーマンスの差で、SetPositionAndRotationメソッドのほうが低負荷であるという結果となりました。

この差を大きいと見るか小さいと見るかは状況次第かもしれませんが、特に理由がない限りはSetPositionAndRotationメソッドを使ったほうが良いと言えるでしょう。

SetLocalPositionAndRotationメソッド(2021.3.11f1以降)

Unity 2021.3.11f1以降では、ローカル空間における位置と回転を指定するSetLocalPositionAndRotationメソッドが追加されました。

public void SetLocalPositionAndRotation(Vector3 localPosition, Quaternion localRotation);

第1引数にはローカル空間の位置第2引数にはローカル空間の回転(クォータニオン)を指定します。

TransformのlocalPositionとlocalRotationプロパティを同時に設定したいとき、このメソッドを用いると僅かに効率的です。ただし、Unity 2021.3.10以前では使用できないメソッドであることにご注意ください。

参考:Unity – Scripting API: Transform.SetLocalPositionAndRotation

メソッドが追加されたことは、以下変更履歴より確認できます。

参考:2021.3.11f1

さいごに

オブジェクトの位置と回転を指定する場合、SetPositionAndRotationメソッドを使用すると低負荷に指定出来ます。

Unity公式のスライドでもこの方式で指定することを推奨しています。

また、ローカル空間の位置と回転を指定する場合、新しいUnityバージョンではSetLocalPositionAndRotationメソッドが使用できますが、それより前のバージョンでは従来通りlocalPosition、localRotationプロパティから指定する形になる点にはご注意ください。

参考サイト

スポンサーリンク