VRChat 非公式日本語ドキュメント

VRCTween

VRCTweenを使用すると、強力なDOTweenライブラリを活用して、VRChatワールド内に滑らかなアニメーションを作成できます。わずか数行のコードで、位置、回転、スケールなどをアニメーション化することが可能です。

概要

VRCTweenは、時間経過とともに値をスムーズに補間(トゥイーン)する組み込みのトゥイーンシステムです。フレームごとに位置や回転を逐一更新する代わりに、VRCTweenが計算やタイミングを自動的に処理します。

一般的な使用例:

VRCTweenはUnityで広く利用されているトゥイーンライブラリであるDOTweenを使用しており、UdonSharpおよびUdon Graphの両方で動作します。

基本的な使用方法

Tweenの作成

ターゲット型に対する拡張メソッド、または VRCTween の静的メソッドを使用してTweenを作成します。各メソッドは、Tweenの制御や設定に使用できる VRCTweenHandle を返します。

using VRC.SDK3.Components;


public class MyScript : UdonSharpBehaviour
{
    public GameObject cube;

    void Start()
    {
        // Move the cube up over 2 seconds.
        VRCTweenHandle tweenHandle = cube.TweenPosition(new Vector3(0, 5, 0), 2f, VRCTweenEase.OutQuad);
    }
}

コールバックの受け取り

Tweenの完了時に通知を受け取るには、ハンドルに対して .OnComplete() をチェーンします。

public class MyScript : UdonSharpBehaviour
{
    void Start()
    {
        gameObject.TweenScale(Vector3.one * 2f, 1f, VRCTweenEase.OutBounce)
            .OnComplete(this, nameof(OnScaleComplete));
    }

    public void OnScaleComplete()
    {
        Debug.Log("Scale animation complete!");
    }
}

Tweenの種類

Tweenの作成メソッドは、対象の型(例: gameObject.TweenPosition(...))の拡張メソッドとして、あるいは VRCTween の静的メソッドとして利用可能です。いずれも VRCTweenHandle を返します。

詳細なコード例については、Built-in Tween Types を参照してください。

Virtual Tween

Virtual Tweenは、毎フレーム UdonBehaviour 上の変数に書き込むことで、任意の数値(float、int、Color、Vector3)をアニメーションさせます。組み込みのTweenタイプで目的の動作が実現できない場合に使用してください。詳細や例については Virtual Tweens を参照してください。

トゥイーンの制御と設定

VRCTweenHandle のインスタンスメソッドを使用して、トゥイーンの制御や設定を行います。設定メソッドはメソッドチェーンのためにハンドルを返します。

cube.TweenPosition(new Vector3(0, 5, 0), 2f, VRCTweenEase.OutQuad)
    .From()
    .SetDelay(0.5f)
    .SetLoops(2, VRCTweenLoopType.Yoyo)
    .OnComplete(this, nameof(OnDone));

APIの完全なリファレンスとイージングタイプ(ease type)の表については、Settings and Control を参照してください。

この例では、ハンドルの保存、コールバック、およびクリーンアップの方法を説明します。

using UdonSharp;
using UnityEngine;
using VRC.SDK3.Components;


public class TweenExample : UdonSharpBehaviour
{
    public GameObject button;
    private VRCTweenHandle scaleTween;

    public override void Interact()
    {
        // Scale up and down when clicked.
        scaleTween = button.TweenScale(Vector3.one * 1.2f, 0.15f, VRCTweenEase.OutQuad)
            .OnComplete(this, nameof(OnTweenComplete));
    }

    public void OnTweenComplete()
    {
        // Scale back down.
        button.TweenScale(Vector3.one, 0.15f, VRCTweenEase.OutQuad);
    }

    void OnDestroy()
    {
        // Clean up tweens when object is destroyed.
        button.KillAllTweens();
    }
}

ベストプラクティス

Tweenハンドルを保存する

後からTweenを制御する必要がある場合は、Tweenハンドルを保存しておきます。

private VRCTweenHandle myTween;

void Start()
{
    myTween = gameObject.TweenPosition(Vector3.up, 2f, VRCTweenEase.OutQuad);
}

public void StopTween()
{
    myTween.Kill();
}

Tweenをクリーンアップする

Tweenは完了すると自動的にクリーンアップされます。ただし、実行中のTween(無限ループや長時間実行されるTweenなど)は、オブジェクトが破棄される際に強制終了させるべきです。

void OnDestroy()
{
    gameObject.KillAllTweens();
}

コールバックを使用してTweenを連結する

コールバックとカスタムイベント名を使用して、Tweenのシーケンスを作成します。

void Start()
{
    cube.TweenPosition(Vector3.up * 5, 1f, VRCTweenEase.OutQuad)
        .OnComplete(this, nameof(OnFirstTweenComplete));
}

public void OnFirstTweenComplete()
{
    cube.TweenRotation(new Vector3(0, 180, 0), 1f, VRCTweenEase.InOutQuad)
        .OnComplete(this, nameof(OnSecondTweenComplete));
}

public void OnSecondTweenComplete()
{
    Debug.Log("Sequence complete!");
}

キャンセル可能なタイマーには DelayedCall を使用する

VRCTween.DelayedCall は、SendCustomEventDelayedSeconds の代わりに使用できるキャンセル可能なタイマーです。

private VRCTweenHandle timerHandle;

void Start()
{
    // Schedule a delayed callback.
    timerHandle = VRCTween.DelayedCall(this, nameof(OnTimerFinished), 3.0f);
}

public void CancelTimer()
{
    // Cancel the timer at any time.
    timerHandle.Kill();
}

public void OnTimerFinished()
{
    Debug.Log("3 seconds have passed!");
}

Udon Graph

VRCTweenはUdon Graphで利用可能です。ノード検索で VRCTween および VRCTweenHandle ノードを探してください。

  1. "VRCTween TweenPosition"(またはその他の作成メソッド)を検索して、Tweenを作成します。
  2. GameObjectとパラメータを接続します。
  3. ノードから VRCTweenHandle が出力されます。
  4. VRCTweenHandle ノード(Kill、Pause、SetDelay、OnCompleteなど)を使用して、制御や設定を行います。

コールバックについては、 VRCTweenHandle OnComplete ノードを使用します。

制限事項

入力値の検証

VRCTweenは、DOTweenの状態やUnityのTransformを破損させるような値を拒否します。この拒否によってUdonBehavior自体がクラッシュしないよう、例外は発生させません。そのため、「何も起きなかった」というトゥイーンは、通常、以下の入力値のいずれかが無効であったことを意味します。

生成メソッドにおいて、以下の場合は無効なハンドルを返し(トゥイーンの生成をスキップし)ます:

設定や制御を行うメソッドにおいて、無効な引数が渡された場合は何も実行(no-op)されません:

トゥイーンが実際に開始されたかどうかで処理を分岐させる必要がある場合は、生成後に handle.IsValid を確認してください。

パフォーマンスのヒント

一般的なヒント

多数のトゥイーンをずらして実行する

タイル状に並んだオブジェクトなど、多数のオブジェクトをアニメーションさせる必要がある場合は、すべてのトゥイーンを同じフレーム内で作成しないようにしてください。その代わり、それぞれの間に小さな遅延を設けて時間をかけて実行するようにします。

[SerializeField] private GameObject[] tiles;
[SerializeField] private float delayBetween = 0.05f;

private int _nextIndex;

public void AnimateAll()
{
    _nextIndex = 0;
    _AnimateNext();
}

public void _AnimateNext()
{
    if (_nextIndex >= tiles.Length) return;

    tiles[_nextIndex].TweenScale(Vector3.one, 0.3f, VRCTweenEase.OutBack);
    _nextIndex++;

    SendCustomEventDelayedSeconds(nameof(_AnimateNext), delayBetween);
}

こうすることで呼び出しごとに1つのトゥイーンが作成され、処理が多くのフレームに分散されます。視覚的には、すべてが同時に変化するよりも、カスケード状にずれて変化する魅力的な演出になります。

頻繁に実行される処理(ホットパス)でのトゥイーンの再利用

移動するターゲットを追従するUI要素や、毎フレームプレイヤーの入力に応答するオブジェクトなど、頻繁にトゥイーンを再設定する場合は、ChangeEndValueSetDurationSetEase を使用してハンドルを再利用することで、フレームごとのメモリ割り当てを回避できます。500個のトゥイーンを300フレームにわたって更新する内部ベンチマークでは、再利用パターンは破棄して再作成する方法と比較して メモリ割り当てが46分の1 になり、実行速度は 10倍 速くなりました。

この最適化は、トゥイーンが高頻度で作成・破棄される場合に重要となります。単発のアニメーション(ドアの開閉、ボタン、スケールのポップアップなど)では、単純に破棄して再作成するコードの方が読みやすく、十分に機能します。

VRCTweenHandle _moveHandle;

void Start()
{
    // Create once with infinite loops so it stays alive after completing.
    _moveHandle = gameObject.TweenPosition(Vector3.zero, 1f, VRCTweenEase.OutQuad)
        .SetLoops(-1, VRCTweenLoopType.Restart)
        .Pause();
}

public void MoveTo(Vector3 target, float duration)
{
    // Reconfigure and restart without allocating.
    _moveHandle.ChangeEndValue(target, true)
        .SetDuration(duration)
        .SetEase(VRCTweenEase.OutCubic);
    _moveHandle.Restart();
}

詳細については、「設定と制御」内の Tween reuse を参照してください。

リソース

最終更新: