UdonSharpの書き方 その1
概要
この記事はUdonSharp含め、プログラミングを何も知らない方を対象としています。
なので正確な用語を使わず、不正確な物言いを多分に含みます。
つまり、「簡単な命令文くらいなら10分あればかけるよ」を目指す上で
問題がない範囲で意図的に語弊があるように書いています。
後々さらに力を伸ばすにあたり、おそらくここに書いてある内容とは矛盾する記事を多数見かける事となるでしょうが
知識をアップデート・修正していく前提の心持ちで読み進めていく物として他の記事を参考していってください。
目次
そもそもどんな概念があるのか
英文字や数字、色んな記号を使ってコードは書かれていますが、
その意味は大きく3つに分けることが出来ます。
データ、箱、機能。
それとこの3概念に密接に関係する「型」という概念
上記4概念を何となくでも理解できたら大丈夫です。
どんだけ難しいコード文であろうとも
それがデータなのか、箱なのか、機能なのか、そしてどんな型なのか
これらを意識するだけで理解に掛かる負荷はグッと減ります。
データとは
三大区分のうちの1つめ、データです。
データとは数値に限らず色々な情報のことを指します。
人で例えるなら年齢、氏名、生年月日、住所、性別、職歴等
単純な数字で表せるものからそうでないものまで、全て情報でありデータです。
そして全てのデータには型というものがあります。
年齢ならば数値という型であり
氏名であれば文字列という型であり
生年月日なら日付という型であるように。
プログラミング言語ではそれらを英文字で表現します、数が多いので部分的な紹介にはなりますが
int型 : 整数型とも呼び、その名の通り0や12、-38といった整数値である事を表す型です
string型 : 文字列型とも呼び、1文字1文字ではなく、1つの文章ひと塊を1データとして扱える型です
「こんにちは、〇〇さん。おはようございます。」も1つのstring型のデータです
詳しい説明はいずれしますが、他にもUnityやUdonsharpならではの型で
Vector3型、VRCPlayerApi型等、沢山の型があります。
箱とは
三大区分のうちの2つめ、箱です。
「箱」はその名の通り、何かを入れるものを指し示しています。
プログラミングにおいては、データを入れる為の箱です。
実際にプログラミングをする時には、むき出しのデータの形では扱いにくい場面がどうしても出てきます。
そんな時にデータを箱に格納し、箱を操作する事によって自分の願う処理を実現していきます。
箱にもデータと同じく型があります。
上記データの欄で説明したように、int型の箱、string型の箱等、データと同じだけ箱にも型が存在します。
そして1番重要なのが箱には自分の型と同じ型のデータしか格納できないという性質があることです。
型という概念が三大区分それぞれに密接に関係してくるのはこれが理由です。
データや箱を操作する時は、それら1個1個が何の型なのかを意識する事が
プログラミングを理解する上で非常に重要なコツとなっていきます。
変数宣言とちょっとした足し算を実際に書いてみよう
前回記事「UdonSharpの始め方」で既にUdonSharpファイルの作り方、開き方は習得できたと思うので
実際にコードを書く事で実感を得ていきましょう。
「HogeHoge」と名前を付けたUdonSharpファイルを開けた場合、既にここまでのコードは書かれていると思います。
今回は「void Start()」と書かれている下の領域の、{}で囲まれている部分に書いていきます。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class HogeHoge : UdonSharpBehaviour
{
void Start()
{
}
}
まずは、「箱を用意しそこにデータを格納する」 をコードではどう表現するのかですが、
int型(整数型)を用意し、そこに5を格納する
string型(文字列型)を用意し、そこに「Hello!」を格納する
を表現する場合は
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class HogeHoge : UdonSharpBehaviour
{
void Start()
{
int aaa;
aaa = 5;
string bbb;
bbb = "Hello!";
}
}
と書きます。
コード内の「aaa」、「bbb」はそれぞれ用意する箱の名前であり
この名前はほとんど自由に自身で名付けることができます。
{}の中では段落が{}の外より一段深くなりますが、これはコードエディターが自動で段落付けを行っており
見やすさを保つための親切機能の中の1つです。
{}の中では2行毎に改行が行われていますが、これは単に自分にとって見やすくするために改行をしていて
コードの内容には関係しない部分ですので、各々の感覚で見やすくなるようキレイに書いていけば問題ありません。
箱を用意するための書き方は意外と簡単で、用意したい型の名前とその箱の名前をスペースを空けて連続で記述するだけです。
そして箱にデータを格納する書き方では「=」の記号が使われているので少し混乱するかもしれませんが、
約束事として「=」の右側を左側に格納する、と覚えていきましょう。
注意すべき点は2点あり、string型のデータを書くには「"(ダブルクォーテーション)」の記号で挟むことと
コード1文の終わりには「;(セミコロン)」を付けることです。
では次に足し算処理を書いてみましょう。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class HogeHoge : UdonSharpBehaviour
{
void Start()
{
int aaa;
aaa = 5;
int aaa2;
aaa2 = 10;
Debug.Log(aaa2);
aaa2 = aaa;
Debug.Log(aaa2);
}
}
箱を用意する部分では、aaaに5を、aaa2に10を代入しています。
Debug.Logについては前回記事で少し説明しましたが、()内の箱の中身をUnityEditor下部のコンソール画面に表示してくれる命令文です。
このUdonSharpが実行されたときに下のコンソール画面を開いてみると、「10」の次に「5」を表示されていると思います。
この結果からわかるように、「aaa2 = 10;」が実行された時にはaaa2の中身は10となっていますが
「aaa2 = aaa;」がaaa2の中身は5となっていることです。
この例で伝えたいことは2点あり、
箱に箱を格納するように記述しても、実際に格納されるのはデータであることと
既に箱にデータが格納されていても、新しく格納すると上書きされてしまうことです。
一度実際にいろいろな数字をあてはめて試してみるのも面白いかもしれません。
機能とは
三大区分のうちの3つめ、機能です。
機能とは、次の3ステップを行う枠組みです。
1.機能にデータを渡す
2.機能が何かの処理を行う
3.機能がデータを返す
ただし必ずしもこの3ステップが行われる訳ではなく
1.がない機能、3.がない機能、2のみの機能、と多種多様です。
そして機能にも型という概念は密接に関わります。
1.と3.での渡すデータと返されるデータには、機能毎に必ず指定があります。
渡すデータと返すデータの型は違っていても構いません。
実際の機能の1つを見てみましょう。
Networking.LocalPlayer.displayName;
Networking.LocalPlayer.GetPosition();
「.(ドット)」で繋がれていて何が何を示しているか分かりにくいと思います。
これを理解する為にはデータと機能の階層構造について理解する必要があります。
データと機能の階層構造
データも機能も階層構造になっていて、階層を繋ぐ記号が「.(ドット)」です。
これはPCでいうフォルダの階層構造に非常に似ています。
Networking.LocalPlayer.displayName
このコードでは
「Networking」フォルダの中の「LocalPlayer」フォルダの中の「displayName」
という階層構造になっています。
そして階層構造において気を配らなくてはいけないのが、データも機能も区別なくフォルダの中に詰め込まれていることです。
機能とはの欄ではLocalPlayerの中にdisplayNameとGetPosition()がありましたが
displayNameはstring型のデータであり
GetPosition()はVector3型のデータを返す機能だということです。
実際に簡単な機能を使って遊んでみよう
今回使うのはLocalPlayer内の機能を使うことにします。
LocalPlayer自体は、VRCPlayerApi型のデータであり
これは自分自身のプレイヤーの事を指します。
その中の機能のGetPosition()とSetVelocity()を使います。
GetPosition()は
1.の渡すデータはなしで
3.の返されるデータはVector3型のデータで、そのプレイヤーが現在いる位置を返します。
SetVelocity()は
1.の渡すデータがVector3型で
3.の返されるデータはなしで、1.で渡したVector3分の速度を与える処理をします。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class HogeHoge : UdonSharpBehaviour
{
void Start()
{
}
private void Update()
{
Debug.Log(Networking.LocalPlayer.GetPosition());
}
public override void Interact()
{
Networking.LocalPlayer.SetVelocity(new Vector3(0, 5, 0));
}
}
Update()の中に書かれたコードは毎フレーム実行されます。
Interact()の中に書かれたコードはインタラクトした時に実行されます。
UdonSharpの始め方ではCubeにUdonSharpをアタッチしたと思います。
もし別ファイルを作って試している場合は、そのファイルも適当にCubeにアタッチしましょう。
Playボタンを押したら下のようにデバッグログに連続で出力されると思います。
自分のいる座標が出力されるので、キャラを動かしてみると刻一刻と値が変わっているのが確認できると思います。
Cubeをインタラクトした時にはジャンプのような挙動をするのが確認できます。
Vector3のデータをどう扱うかの説明はしていませんでしたが
今回は省略し、このサンプルコードのように書き、中の数字を変更して遊んでみるのもいいでしょう。
おわりに
今回では、プログラミングの基本概念を説明してきました。
次回は説明を省いてきた、Vector3などの型によってデータの書き方がまちまちになる部分を解説していきます。
Update()やInteract()等の実行されるタイミングが異なる色んな枠組みも紹介していきます。

