はじめに
VRChat で OSC 触ってみるー
VRCOscLib は続々と新しい機能に対応しています。最新版を用いて開発することをおすすめします。
VRCOscLib の GitHub リポジトリにもいくつかサンプルがあります。
環境
- Visual Studio 2022
- .NET 6
- C# 10
- VRCOscLib v1.1.3 (バージョンは逐次更新)
VRCOscLib を入れてみる
とりあえずコンソールアプリ作成
ソリューション右クリック→「NuGetパッケージの管理」みたいなやつ
「VRCOscLib」で検索→こいつをインストールする
とりあえずいろいろいじる
アバターのIDと名前を取得
using BuildSoft.VRChat.Osc.Avatar;
var avatarConfigs = OscAvatarConfig.CreateAll();
foreach (var config in avatarConfigs)
{
Console.WriteLine($"config: ");
Console.WriteLine($" id: {config.Id}");
Console.WriteLine($" name: {config.Name}");
}
実行結果
config:
id: avtr_8b024156-1ee4-467a-XXXX-f7b11297550b
name: Bell_v5?0?0
config:
id: avtr_bf4a3985-d29d-45c2-XXXX-681620fe4d9b
name: My CustaChan v1?0
お、文字化けした。コンソールの文字コード変えよう。
アバターのIDと名前を取得 (UTF-8で出力)
using BuildSoft.VRChat.Osc.Avatar;
using System.Text;
var avatarConfigs = OscAvatarConfig.CreateAll();
Console.OutputEncoding = Encoding.UTF8;
foreach (var config in avatarConfigs)
{
Console.WriteLine($"config: ");
Console.WriteLine($" id: {config.Id}");
Console.WriteLine($" name: {config.Name}");
}
実行結果
config:
id: avtr_8b024156-1ee4-467a-XXXX-f7b11297550b
name: Bell_v5․0․0
config:
id: avtr_bf4a3985-d29d-45c2-XXXX-681620fe4d9b
name: My CustaChan v1․0
いい感じ、いい感じ。
かすたちゃん(My CustaChan v1․0)の方だけ欲しいので、かすたちゃんのIDで引っ張ってくる。
かすたちゃんのパラメータを列挙
using BuildSoft.VRChat.Osc.Avatar;
using System.Text;
Console.OutputEncoding = Encoding.UTF8;
var avatarConfig = OscAvatarConfig.CreateAll()
.First(config => config.Id == "avtr_bf4a3985-d29d-45c2-XXXX-681620fe4d9b");
foreach (var param in avatarConfig.Parameters.Items)
{
Console.WriteLine($"{param.Name}: " +
$"input {(param.Input != null ? "○" : "×")}, " +
$"output {(param.Output != null ? "○" : "×")}"
);
}
実行結果
Bottoms: input ○, output ○
Wear: input ○, output ○
VRCFaceBlendV: input ○, output ○
VRCFaceBlendH: input ○, output ○
VRCEmote: input ○, output ○
VelocityZ: input ×, output ○
VelocityY: input ×, output ○
VelocityX: input ×, output ○
InStation: input ×, output ○
Seated: input ×, output ○
AFK: input ×, output ○
Upright: input ×, output ○
AngularY: input ×, output ○
Grounded: input ×, output ○
MuteSelf: input ×, output ○
VRMode: input ×, output ○
TrackingType: input ×, output ○
GestureRightWeight: input ×, output ○
GestureRight: input ×, output ○
GestureLeftWeight: input ×, output ○
GestureLeft: input ×, output ○
Voice: input ×, output ○
Viseme: input ×, output ○
いっぱいありゅ!
値の読み取り
using BuildSoft.VRChat.Osc.Avatar;
using System.Text;
Console.OutputEncoding = Encoding.UTF8;
var avatarConfig = OscAvatarConfig.CreateAll()
.First(config => config.Id == "avtr_bf4a3985-d29d-45c2-XXXX-681620fe4d9b");
avatarConfig.Parameters.ParameterChanged += (parameter, e) =>
{
DateTime now = DateTime.Now;
Console.WriteLine($"[{now.ToShortDateString()} {now.ToShortTimeString()}] " +
$"{parameter.Name}: {e.OldValue} => {e.NewValue}");
};
await Task.Delay(-1);
実行結果(一部抜粋)
VRChat を動かしながら確認
[2022/02/22 23:04] VelocityY: 0.16600055 => 0.05700054
[2022/02/22 23:04] VelocityY: 0.05700054 => -0.051999465
[2022/02/22 23:04] VelocityY: -0.051999465 => -0.16099948
[2022/02/22 23:04] VelocityY: -0.16099948 => -0.26999947
[2022/02/22 23:04] VelocityY: -0.26999947 => -0.37899947
[2022/02/22 23:04] VelocityY: -0.37899947 => -0.48799947
[2022/02/22 23:04] VelocityY: -0.48799947 => -0.59699947
[2022/02/22 23:04] VelocityY: -0.59699947 => -0.7059995
[2022/02/22 23:04] VelocityY: -0.7059995 => -0.8149995
[2022/02/22 23:04] VelocityY: -0.8149995 => -0.92399955
[2022/02/22 23:04] VelocityY: -0.92399955 => -1.0329995
[2022/02/22 23:04] VelocityY: -1.0329995 => -1.1419995
[2022/02/22 23:04] VelocityY: -1.1419995 => -1.2509995
[2022/02/22 23:04] VelocityY: -1.2509995 => -1.3599994
[2022/02/22 23:04] VelocityY: -1.3599994 => -1.4689994
[2022/02/22 23:04] MuteSelf: True => False
[2022/02/22 23:04] VelocityY: -1.4689994 => -1.5779994
[2022/02/22 23:04] VelocityY: -1.5779994 => -1.6869993
[2022/02/22 23:04] VelocityY: -1.6869993 => -1.7959993
[2022/02/22 23:04] VelocityY: -1.7959993 => -1.9049993
[2022/02/22 23:04] VelocityY: -1.9049993 => -2.0139992
[2022/02/22 23:04] VelocityY: -2.0139992 => -2.1229992
[2022/02/22 23:04] VelocityY: -2.1229992 => -2.2319992
[2022/02/22 23:04] VelocityY: -2.2319992 => -2.3409991
[2022/02/22 23:04] VelocityY: -2.3409991 => -2.449999
[2022/02/22 23:04] VelocityY: -2.449999 => -2.558999
[2022/02/22 23:04] VelocityY: -2.558999 => -2.667999
[2022/02/22 23:04] VelocityY: -2.667999 => 0
[2022/02/22 23:04] Grounded: False => True
[2022/02/22 23:05] AngularY: 0 => -8
[2022/02/22 23:05] AngularY: -8 => -0
[2022/02/22 23:05] AngularY: -0 => -8
[2022/02/22 23:05] AngularY: -8 => -0
[2022/02/22 23:05] AngularY: -0 => 8
[2022/02/22 23:05] AngularY: 8 => 0
[2022/02/22 23:05] MuteSelf: False => True
[2022/02/22 23:05] MuteSelf: True => False
[2022/02/22 23:05] AngularY: 0 => -8
[2022/02/22 23:05] AngularY: -8 => -0
[2022/02/22 23:05] AngularY: -0 => -8
[2022/02/22 23:05] AngularY: -8 => -0
[2022/02/22 23:05] AngularY: -0 => -8
[2022/02/22 23:05] AngularY: -8 => -16
[2022/02/22 23:05] AngularY: -16 => -8
[2022/02/22 23:05] AngularY: -8 => 0
[2022/02/22 23:05] AngularY: 0 => -8
[2022/02/22 23:05] AngularY: -8 => -16
[2022/02/22 23:05] AngularY: -16 => 0
[2022/02/22 23:05] AngularY: 0 => -24
[2022/02/22 23:05] AngularY: -24 => -16
[2022/02/22 23:05] AngularY: -16 => -8
[2022/02/22 23:05] AngularY: -8 => 0
うごいてるー!!!やったー
OscAvatarConfig.WaitAndCreateAtCurrentAsync()
使ってみる
OscAvatarConfig.WaitAndCreateAtCurrentAsync()
は現在のアバターのコンフィグを取得できる。
取得できるまで待機する。 (Reset Avatar すれば取得できるようになる)
using BuildSoft.VRChat.Osc.Avatar;
using System.Text;
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("取得中...");
var avatarConfig = await OscAvatarConfig.WaitAndCreateAtCurrentAsync();
Console.WriteLine($"取得完了: {avatarConfig.Name}");
avatarConfig.Parameters.ParameterChanged += (parameter, e) =>
{
DateTime now = DateTime.Now;
Console.WriteLine($"[{now.ToShortDateString()} {now.ToShortTimeString()}] " +
$"{parameter.Name}: {e.OldValue} => {e.NewValue}");
};
await Task.Delay(-1);
実行結果(一部抜粋)
VRChat を動かしながら確認
取得中...
取得完了: Koyuki
[2022/02/23 18:59] AngularY: => -8
[2022/02/23 18:59] AngularY: -8 => -16
[2022/02/23 18:59] AngularY: -16 => -8
[2022/02/23 18:59] AngularY: -8 => 0
[2022/02/23 18:59] AngularY: 0 => -16
[2022/02/23 18:59] AngularY: -16 => -8
[2022/02/23 18:59] AngularY: -8 => -16
[2022/02/23 18:59] AngularY: -16 => -8
[2022/02/23 18:59] AngularY: -8 => -16
[2022/02/23 18:59] AngularY: -16 => -48
[2022/02/23 18:59] AngularY: -48 => 0
[2022/02/23 18:59] AngularY: 0 => -24
[2022/02/23 18:59] AngularY: -24 => -32
[2022/02/23 18:59] AngularY: -32 => -56
[2022/02/23 18:59] AngularY: -56 => -24
[2022/02/23 18:59] AngularY: -24 => -16
[2022/02/23 18:59] AngularY: -16 => -0
[2022/02/23 18:59] AngularY: -0 => 8
[2022/02/23 18:59] AngularY: 8 => 16
[2022/02/23 18:59] VelocityX: => -0.0034728758
[2022/02/23 18:59] VelocityZ: => 0.111127004
[2022/02/23 18:59] VelocityX: -0.0034728758 => -0.009260967
[2022/02/23 18:59] VelocityZ: 0.111127004 => 0.22448
[2022/02/23 18:59] AngularY: 16 => 8
送信をやってみる
using BuildSoft.VRChat.Osc.Input;
using System.Text;
Console.OutputEncoding = Encoding.UTF8;
while (true)
{
Console.WriteLine("ジャンプ!");
OscButtonInput.Jump.Press(); // ジャンプボタンを押す
await Task.Delay(500);
OscButtonInput.Jump.Release(); // ジャンプボタンを離す
await Task.Delay(500);
}
実行結果(VRChat)
10秒間ぐるぐるする
using BuildSoft.VRChat.Osc.Input;
OscAxisInput.LookHorizontal.Send(0.5f);
OscButtonInput.MoveForward.Press(); // 前に行く
Console.WriteLine("ぐるぐる");
await Task.Delay(10000);
Console.WriteLine("ぐるぐるおわりー");
OscAxisInput.LookHorizontal.Send(0);
OscButtonInput.MoveForward.Release(); // 前に行くのやめる
実行結果(VRChat)
アバターが変わったことを検知
アバターが変わったら使用可能なパラメータを列挙するようにする。
using BuildSoft.VRChat.Osc.Avatar;
using System.Text;
Console.OutputEncoding = Encoding.UTF8;
OscAvatarUtility.AvatarChanged += (sender, e) =>
{
var config = OscAvatarConfig.CreateAtCurrent()!;
Console.WriteLine($"{config.Name}:");
foreach (var param in config.Parameters.Items)
{
Console.WriteLine($" {param.Name}: " +
$"input {(param.Input != null ? "○" : "×")}, " +
$"output {(param.Output != null ? "○" : "×")}"
);
}
Console.WriteLine();
};
await Task.Delay(-1);
実行結果(一部抜粋)
VRChat を動かしながら確認
My CustaChan v1․0:
Bottoms: input ○, output ○
Wear: input ○, output ○
VRCFaceBlendV: input ○, output ○
VRCFaceBlendH: input ○, output ○
VRCEmote: input ○, output ○
VelocityZ: input ×, output ○
VelocityY: input ×, output ○
VelocityX: input ×, output ○
InStation: input ×, output ○
Seated: input ×, output ○
AFK: input ×, output ○
Upright: input ×, output ○
AngularY: input ×, output ○
Grounded: input ×, output ○
MuteSelf: input ×, output ○
VRMode: input ×, output ○
TrackingType: input ×, output ○
GestureRightWeight: input ×, output ○
GestureRight: input ×, output ○
GestureLeftWeight: input ×, output ○
GestureLeft: input ×, output ○
Voice: input ×, output ○
Viseme: input ×, output ○
Bell_v5․0․0:
Adder: input ○, output ○
Menu: input ○, output ○
BlendMode: input ○, output ○
UseBlend: input ○, output ○
IsEnteredBlend: input ○, output ○
TailIsActive: input ○, output ○
DressIsActive: input ○, output ○
Shoes: input ○, output ○
Socks: input ○, output ○
Headgear: input ○, output ○
Bottoms: input ○, output ○
Under: input ○, output ○
Wear: input ○, output ○
VRCFaceBlendV: input ○, output ○
VRCFaceBlendH: input ○, output ○
VelocityZ: input ×, output ○
VelocityY: input ×, output ○
VelocityX: input ×, output ○
InStation: input ×, output ○
Seated: input ×, output ○
AFK: input ×, output ○
Upright: input ×, output ○
AngularY: input ×, output ○
Grounded: input ×, output ○
MuteSelf: input ×, output ○
VRMode: input ×, output ○
TrackingType: input ×, output ○
GestureRightWeight: input ×, output ○
GestureRight: input ×, output ○
GestureLeftWeight: input ×, output ○
GestureLeft: input ×, output ○
Voice: input ×, output ○
Viseme: input ×, output ○