#やったこと
前回プレイヤーの座標を取得しました。
UdonSharp日記~ローカルプレイヤーの座標の取得~
今回はPlaneにオリジナルの当たり判定を作成し、
VRCInstantiateを使用して、道の動的生成を行います。
んでもってそれの発展形でPlaneの動的生成を実験。
— はんちょ (@sadimensions) April 27, 2020
UdonSharpをアタッチしたGameObjectをVRCInstantiateで生成した場合、再帰的にUdonSharpが機能するか不安でしたが、機能しました。
ただしこの方法は非同期なのが問題。 pic.twitter.com/7DqeYgJlBU
#参考文献
やぎりさんのUdonSharpコード走り書きメモ・・・VRCInstantiate
#やり方
最初にスポーンするPlaneの横に、これからどんどんコピーしていく予定のPlaneを置きます。
ここにUdonBehaviourをつけて、UdonSharpを適用します。
そして次のコードを作成します。
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using UnityEngine.UI;
public class Floor : UdonSharpBehaviour
{
public GameObject prefab;
public Text debugText;
bool is_stillGiveBirth = false;
void Update()
{
var player = Networking.LocalPlayer;
if (player != null)//Unityの再生ボタンで実行すると変数がnullになるらしいよ
{
//playerの位置を取得(位置は頭の位置を使用)
var headData = player.GetTrackingData(VRCPlayerApi.TrackingDataType.Head);
debugText.text = string.Format("Head-Pos: {0}\r\n", headData.position.ToString());
if (is_In(headData.position) && is_stillGiveBirth == false)
{
//当たり判定があり、まだPlaneを生成していない場合、Planeを生成する。
var go = VRCInstantiate(prefab);
go.GetComponent<Transform>().position = new Vector3(0.0f, 0.0f, prefab.transform.position.z + 2.0f);
is_stillGiveBirth = true;
}
}
}
//入力されたVector3(座標)が自身の中にあるかどうかを判定する
//使用するのはx,zの2次元座標のみ
private bool is_In(Vector3 pos)
{
float myX = this.transform.position.x;
float myZ = this.transform.position.z;
float scaleX = 5.0f*this.transform.localScale.x;
float scaleZ = 5.0f*this.transform.localScale.z;
//x chexk
if(myX - scaleX < pos.x && pos.x < myX + scaleX)
{
//z check
if (myZ - scaleZ < pos.z && pos.z < myZ + scaleZ)
{
debugText.text = string.Format("ON: x{0}, z{1}, sx{2}, sz{3}\r\n", myX, myZ, scaleX, scaleZ);
return true;
}
}
return false;
}
}
設計方針としては以下の通り。
1.プレイヤーの座標を得る
2.自身(Plane)の座標と幅・高さを考慮したものと比較して当たり判定をとる
3.当たる場合、自身をクローンして先の座標に生成する。
4.何度も生成しないようにフラグを立てる
難しくないのだけど、当たり判定を使わずにコライダーを使ったらどうか?とか
クローンに使用する関数は何を使うべきか?とか
幅と高さはscaleを使ってるけど、絶対座標系との対応が取れなくてどうしようとか
(今回は実験なのでマジックナンバーとしました)
そんなこんな考えていたら、5時間くらいかかっています。
知識がないところからスタートすると時間かかりますね。
#課題
今回使用したVRCInstantiateは動機が取れないとのこと
(本当に非同期化は調べていない)
解決策を考えなくては・・・
一つ気になることといえば
黒鳥さんのUDONメモによると・・・
VRCInstantiateのあれこれ(2020/04/11現在)
現在同期的にインスタンス化を行う方法がない?
インスタンス化したオブジェクトではUdonBehaviourが死ぬ。
SendCustomNetworkEventで同期的にインスタンス化出来ているようにみえるが、PickupとUdonBehaviourが死ぬ。
プレハブの座標とは違う場所からインスタンス化される。
とあり、インスタンス化したPlaneでUdonBehaviourが動かないことが報告されており、
今回の実験とは結果が違うので、慎重に調査をしないといけません。
今回の実験はローカル上でのテストなのでVRChatにアップすると挙動が違うかもしれない。
###後日談
Udonが抱えているバグとして、インスタンス化したオブジェクトでは”時々”UdonBehaviorを失ったり、トリガーが機能しなくなるとのこと。
今回の記事で作成したものは、インスタンスがどんどん次のインスタンスを作成していくコードとなっていたので現時点(2020/4/27)では良くない設計例ですね。
ローカルではなくVRChat上へアップロードしてテストしたら挙動が違いました。
— はんちょ (@sadimensions) April 27, 2020
難しいね pic.twitter.com/FGx92jFotl