見出し画像

【Udon#】VRChatで画面に遅れて追従するUIを実装する

Unity 2019.4.31f1
VRChat Worlds SDK3 2021.11.08.14.28
UdonSharp 0.20.3

こんなやつ


参考

手順

  • Create Emptyで空のGameObjectを作成する

  • 空のGameObjectに『Udon Behaviour』を追加して下記のスクリプト(Udon#)を設定する。

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;

public class UdonFollowUI : UdonSharpBehaviour {
    [SerializeField] private float followMoveSpeed = 0.1f;
    [SerializeField] private float followRotateSpeed = 0.02f;
    [SerializeField] private bool lockHorizon;
    
    private Quaternion rot;
    private Quaternion rotDiff;
    private Vector3 playerPosition;
    private Quaternion playerRotation;

    void Start() {
        //初期位置の設定
        var player = Networking.LocalPlayer;
        if(player != null) {
            var headData = player.GetTrackingData(VRCPlayerApi.TrackingDataType.Head);
            transform.position = headData.position;
            transform.rotation = headData.rotation;
        }
    }

    void Update() {
        //プレイヤーの位置・回転をリアルタイムに取得
        var player = Networking.LocalPlayer;
        if(player != null) {
            var headData = player.GetTrackingData(VRCPlayerApi.TrackingDataType.Head);
            playerPosition = headData.position;
            playerRotation = headData.rotation;
        }
    }

    private void LateUpdate() {
        //UI位置とプレイヤー位置の差分をLerp関数で滑らか補完
        transform.position = Vector3.Lerp(transform.position, playerPosition, followMoveSpeed);

        //上と同じく回転をLerp関数で滑らかに補完
        //lockHorizonがtrueの場合はxzの角度を0にすることで水平に固定
        rot = playerRotation;
        if(lockHorizon) {
            rot.x = 0;
            rot.z = 0;
        }
        transform.rotation = Quaternion.Lerp(transform.rotation, rot, followRotateSpeed);
    }
}
  • 空のGameObjectの下にCanvasを置く。このCanvasにUIなどを設置する。

  • 上記のスクリプトはGameObjectとプレイヤーの頭位置を一致させるものなのでプレイヤーと被ってしまう。CanvasのZ位置等をズラして頭(視線)の延長線上に配置する。

  • Canvasの位置や上記スクリプトのfollowMoveSpeed等を調整して完成

感想

  • Udon#のGetTrackingDataでプレイヤーの頭の位置情報が取れることがわかったのでイケるかなと思ったら意外とすんなり動いてくれた。

  • 頭位置の他に右手と左手も数値が取れるので、手に追従するUIも同じ感じで実装できそう

  • とりあえず上記のスクリプトで動いたけど、Udon#というかC#の書き方に慣れていないので正しいのかわかっていない、誰か教えて(LateUpdateあたりもまだ理解しきれていない)。

  • 本当はフェードイン・アウトまで実装したかったけどUdon#からだとCanvasGroupをGetComponentできなくてAlphaがいじれなかった、なんで?(書き方を間違っているだけかもしれない)

  • この辺はシェーダーで処理させる必要がある?

この記事が気に入ったらサポートをしてみませんか?