なにこれ
自分がワールド製作でよく使うメモです。
スクリプトの記載などもありますが、基本適当な記載です。
要望があれば追記していきます。
非スクリプト系
移動速度・ジャンプ力変更
- jumpImpulse
- ジャンプ力
- warkspeed
- 歩く速度
- runSpeed
- 走る速度
- strafeSpeed
- 走る速度
移動速度を上げると酔いやすくなるので注意してください。
※[JP]Tutorial Worldの設定は以下の通り。
ジャンプ力がデフォルトよりも強く設定されている。
物を複製したい
Ctrl+D
ピックアップ出来る物を作りたい(非同期・ローカル)
・持ち上げたいオブジェクトに「VRC Pickup」を設定する。(Add Component)
→「Rigidbody」が自動的に追加される。
・コライダーを設定する。
- Use Gravity
- チェックを入れると重力落下します。
- Is Kinematic
- 物理演算を受け付けなくなります。
- (離しても飛んでいかなくなる)
「Use Gravity」「Is Kinematic」両方チェック外すと永遠に飛んでいきます。
ピックアップ出来る物を作りたい(同期・グローバル)
基本はローカルと同じ
・「VRC Object Sync」を設定する。(Add Component)
・「Allow Collision...」はチェックを外しておく。
スクリプト系
表示・非表示のスイッチ(インタラクト)
鏡とかのスイッチ。
よく消し忘れたままアップロードしてしまうので、開始時に強制オフにしてる。
// 対象のオブジェクト
[SerializeField] private GameObject TargetObj;
void Start()
{
// 開始時、強制オフ
TargetObj.SetActive(false);
}
// 触ったとき(インタラクトした時)
public override void Interact()
{
// 表示非表示を切り替え
TargetObj.SetActive(!TargetObj.activeSelf);
}
ソースを修正すると、「Udon Behaviour」の中に枠が出てくるのでオブジェクトを設定する。
表示・非表示のスイッチ(エリア)
特定エリアに入ったら自動でOnになりますよ的なやつ
「自分だった場合」をつけ忘れて暴走したり、出た時にOffにするのを忘れやすいので注意。
// 対象のオブジェクト
[SerializeField] private GameObject TargetObj;
void Start()
{
// 開始時、強制オフ
TargetObj.SetActive(false);
}
// エリアに入ったとき
public override void OnPlayerTriggerEnter(VRCPlayerApi player)
{
// 入ったプレイヤーが自分だった場合
if (player == Networking.LocalPlayer)
{
TargetObj.SetActive(true);
}
}
// エリアから出たとき
public override void OnPlayerTriggerExit(VRCPlayerApi player)
{
// 出たプレイヤーが自分だった場合
if (player == Networking.LocalPlayer)
{
TargetObj.SetActive(false);
}
}
・同じオブジェクト内にコライダーを設定する。
・設定したコライダーの「Is Trigger」にチェックを入れる。
テレポートさせたい
// テレポート先(オブジェクト)
[SerializeField] private GameObject teleportPointTo;
// 触ったとき(インタラクトしたとき)
public override void Interact()
{
// プレイヤーをテレポートさせる
Networking.LocalPlayer.TeleportTo(teleportPointTo.transform.position, teleportPointTo.transform.rotation);
}
テレポート先に設定したい場所にオブジェクトを配置し、設定する。
音を流す
audio.Play();
改造クライアント対策
あいつら勝手に他人のメソッドを叩いたりします。正直迷惑。
勝手に鏡を付けられたりテレポートさせられたりの対策
ワールドのインタラクト出来るもの等に距離制限を設ける。
「指定された距離よりも遠くにいる為、何もしない」を実現する。
[SerializeField] private GameObject TargetObj;
public bool IsTinyDistance(Vector3 objPlace)
{
// プレイヤーの座標を取得
var player = Networking.LocalPlayer;
var playerPosition = player.GetPosition();
// 各座標の差異を取得
var differenceX = playerPosition.x - objPlace.x;
var differenceZ = playerPosition.z - objPlace.z;
// 指定距離にいる場合、true
if((distance * -1) < differenceX && differenceX < distance && (distance * -1) < differenceZ && differenceZ < distance)
{
return true;
}
return false;
}
public override void Interact()
{
// 距離チェック
if (IsTinyDistance(this.gameObject.transform.position))
{
// 表示非表示を切り替え
TargetObj.SetActive(!TargetObj.activeSelf);
}
}
[SerializeField] private GameObject TargetObj;
public bool IsTinyDistance(Vector3 objPlace)
{
// プレイヤーの座標を取得
var player = Networking.LocalPlayer;
var playerPosition = player.GetPosition();
// 各座標の差異を取得
var differenceX = playerPosition.x - objPlace.x;
var differenceZ = playerPosition.z - objPlace.z;
// 指定距離にいる場合、true
if((distance * -1) < differenceX && differenceX < distance && (distance * -1) < differenceZ && differenceZ < distance)
{
return true;
}
return false;
}
public override void Interact()
{
// 距離チェック
if (IsTinyDistance(this.gameObject.transform.position))
{
// プレイヤーをテレポートさせる
Networking.LocalPlayer.TeleportTo(teleportPointTo.transform.position, teleportPointTo.transform.rotation);
}
}
Publicメソッドを呼ばせない
正確には、「呼ばれても何もしなくする」
バカみたいなやり方ですが、なんと効果があります。
public void runSeq(int checkNum)
{
if (checkNum == 9999)
{
/*
各種処理
*/
// 改造クライアントは最後に呼ばれた時のパラメータ値を使用している様なので、
// 正常動作時の最後に正常に動作しない形で一度呼び出す。
runSeq(0);
}
}
public override void Interact()
{
// checkNumが9999の時のみ正常に動作する
hogehoge.runSeq(9999)
}