UdonSharpメモ ~コードの付箋~
記事の内容
結論に至るまで長時間を要したコードとかを載せておくところ。
プレイヤーの移動入力をアバターの移動と言うことがありますがお気になさらず...
ScrollできるUI
標準のScrollViewを使えばすご~~~くお手軽だが、レティクルやレイキャストがあたった状態でアバターを移動するとスクロールまで移動しやがるので微妙に良くない。
同じような動作をするスクリプトを書いてみた
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using UnityEngine.UI;
public class ScrollView : UdonSharpBehaviour
{
public RectTransform viewport,content;
public Scrollbar scrollbar;
void LateUpdate(){
// content: 中身
// viewport: 表示領域
Vector2 viewport_vec2 = viewport.rect.size, content_vec2 = content.rect.size;
scrollbar.size = Mathf.Min(viewport_vec2.y / content_vec2.y, 1);
scrollbar.gameObject.SetActive(scrollbar.size < 1);
if(content_vec2.y >= viewport_vec2.y){
Vector2 pos = content.anchoredPosition;
pos.y = (content_vec2.y - viewport_vec2.y)*scrollbar.value;
content.anchoredPosition = pos;
}
}
}
<RectTransform>.rect.size
でUIの大きさを取得できる。
スクロールバーの大きさを高さ同士で割って求める。
1を超えないようにMathf.Minで抑制してる。
位置の計算は、表示領域の超過分をどれだけy軸に加算するかをスクロールバーのvalueで求める。valueは0~1で取得できるので都合が良い。
...とか思ってたけどScroll ViewのMovement Type
をClamped
にして、
Scroll Sensitivity
を0にすればいいっぽい。どこに書いてあるんだそんなの
トラッキングをトラッキング(?)
HMDやコントローラの位置を取得できる。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class TrackingTrace : UdonSharpBehaviour
{
private VRCPlayerApi targetPlayer;
public GameObject playModeObject;
public VRCPlayerApi.TrackingDataType type;
void Start()
{
#if !UNITY_EDITOR
targetPlayer = Networking.LocalPlayer;
#endif
}
void Update(){
Vector3 pos = targetPlayer != null ? targetPlayer.GetTrackingData(type).position : playModeObject.transform.position;
Quaternion rotate = targetPlayer != null ? targetPlayer.GetTrackingData(type).rotation : playModeObject.transform.rotation;
transform.position = pos;
transform.rotation = rotate;
}
}
playModeObjectはプレイヤーが存在しないUnityEditor上でのPlayMode時に代わりに追従するオブジェクト。
#if
系は、エディタ上で動かした時にエラーが出ないようにするプリプロセッサ ディレクティブって言われてるやつ。
プレイヤーのトラッキングデータは<VRCPlayerApi>.GetTrackingData(<TrackingDataType>)
で取得できる。
こいつはpositionとrotationの両方を持ってるので、必要に応じて取り出す必要がある。
VRChat上でのキーボード入力
通常のUnityと同様にInput.GetKey(<KeyCode>)
から取得できる。
正直にUpdate系に書くとボタンを押している間毎フレーム処理される。
そのため、次離すまで処理させないようにする(OneShotにする)には、
自前でboolで既に押されているかを保持しておく必要がある。
void LateUpdate()
{
if (Input.GetKey(KeyCode.I))
{
if (!isPushed)
{
isPushed = true;
// 処理...
}
} else {
isPushed = false;
}
}
Discussion