|
@@ -1,6 +1,5 @@
|
|
|
using UdonSharp;
|
|
using UdonSharp;
|
|
|
using UnityEngine;
|
|
using UnityEngine;
|
|
|
-using VRC.SDK3.Components;
|
|
|
|
|
using VRC.SDKBase;
|
|
using VRC.SDKBase;
|
|
|
using VRC.Udon;
|
|
using VRC.Udon;
|
|
|
using VRC.Udon.Common.Interfaces;
|
|
using VRC.Udon.Common.Interfaces;
|
|
@@ -44,7 +43,7 @@ public class LinkedObjectSystem : UdonSharpBehaviour
|
|
|
|
|
|
|
|
[Header("Station\n")]
|
|
[Header("Station\n")]
|
|
|
[Tooltip("The player who turns this on by interacting, or who walks into the trigger, is seated here. They leave it themselves")]
|
|
[Tooltip("The player who turns this on by interacting, or who walks into the trigger, is seated here. They leave it themselves")]
|
|
|
- public VRCStation station;
|
|
|
|
|
|
|
+ public VRC.SDK3.Components.VRCStation station; // Named in full: VRC.SDKBase has a VRCStation too
|
|
|
|
|
|
|
|
// PRIVATE VARS
|
|
// PRIVATE VARS
|
|
|
|
|
|
|
@@ -57,6 +56,8 @@ public class LinkedObjectSystem : UdonSharpBehaviour
|
|
|
private bool pickupTriggerEnabled = false;
|
|
private bool pickupTriggerEnabled = false;
|
|
|
private int[] playersInside = new int[100]; // Player IDs: a player can't be counted twice, and leaving the instance removes them
|
|
private int[] playersInside = new int[100]; // Player IDs: a player can't be counted twice, and leaving the instance removes them
|
|
|
private int playerCount;
|
|
private int playerCount;
|
|
|
|
|
+ private bool playerCheckScheduled;
|
|
|
|
|
+ private Collider triggerCollider;
|
|
|
private Collider[] pickupsInside = new Collider[32];
|
|
private Collider[] pickupsInside = new Collider[32];
|
|
|
private int pickupCount;
|
|
private int pickupCount;
|
|
|
private bool pickupCheckScheduled;
|
|
private bool pickupCheckScheduled;
|
|
@@ -66,6 +67,7 @@ public class LinkedObjectSystem : UdonSharpBehaviour
|
|
|
{
|
|
{
|
|
|
playerTriggerEnabled = triggerType == TriggerType.Player || triggerType == TriggerType.BothPlayerAndObject;
|
|
playerTriggerEnabled = triggerType == TriggerType.Player || triggerType == TriggerType.BothPlayerAndObject;
|
|
|
pickupTriggerEnabled = triggerType == TriggerType.Object || triggerType == TriggerType.BothPlayerAndObject;
|
|
pickupTriggerEnabled = triggerType == TriggerType.Object || triggerType == TriggerType.BothPlayerAndObject;
|
|
|
|
|
+ triggerCollider = GetComponent<Collider>();
|
|
|
if (interactionType == InteractionType.None)
|
|
if (interactionType == InteractionType.None)
|
|
|
{
|
|
{
|
|
|
DisableInteractive = true;
|
|
DisableInteractive = true;
|
|
@@ -142,10 +144,54 @@ public class LinkedObjectSystem : UdonSharpBehaviour
|
|
|
playersInside[playerCount] = id;
|
|
playersInside[playerCount] = id;
|
|
|
playerCount++;
|
|
playerCount++;
|
|
|
if (debugMode) Debug.Log("Linked Object System: players inside: " + playerCount.ToString());
|
|
if (debugMode) Debug.Log("Linked Object System: players inside: " + playerCount.ToString());
|
|
|
|
|
+ if (!playerCheckScheduled)
|
|
|
|
|
+ {
|
|
|
|
|
+ playerCheckScheduled = true;
|
|
|
|
|
+ SendCustomEventDelayedSeconds(nameof(_CheckPlayers), 1f);
|
|
|
|
|
+ }
|
|
|
UpdateOutput();
|
|
UpdateOutput();
|
|
|
if (player.isLocal) SeatLocalPlayer();
|
|
if (player.isLocal) SeatLocalPlayer();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Drops players who left without an exit: seated in a station elsewhere, or gone from the instance. Runs every
|
|
|
|
|
+ /// second while any player is inside.
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ public void _CheckPlayers()
|
|
|
|
|
+ {
|
|
|
|
|
+ playerCheckScheduled = false;
|
|
|
|
|
+ for (int i = playerCount - 1; i >= 0; i--)
|
|
|
|
|
+ {
|
|
|
|
|
+ VRCPlayerApi player = VRCPlayerApi.GetPlayerById(playersInside[i]);
|
|
|
|
|
+ if (!Utilities.IsValid(player) || !NearTrigger(player)) RemovePlayer(playersInside[i]);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (playerCount > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ playerCheckScheduled = true;
|
|
|
|
|
+ SendCustomEventDelayedSeconds(nameof(_CheckPlayers), 1f);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// Whether the player's feet or head are within a metre of the trigger's bounds. Generous on purpose: a player
|
|
|
|
|
+ /// dropped here gets no new enter until they walk out and back in.
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private bool NearTrigger(VRCPlayerApi player)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (triggerCollider == null) return true;
|
|
|
|
|
+ Bounds bounds = triggerCollider.bounds;
|
|
|
|
|
+ Vector3 center = bounds.center;
|
|
|
|
|
+ Vector3 reach = bounds.extents + Vector3.one;
|
|
|
|
|
+ return Within(player.GetPosition(), center, reach) ||
|
|
|
|
|
+ Within(player.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).position, center, reach);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private bool Within(Vector3 point, Vector3 center, Vector3 reach)
|
|
|
|
|
+ {
|
|
|
|
|
+ Vector3 d = point - center;
|
|
|
|
|
+ return Mathf.Abs(d.x) <= reach.x && Mathf.Abs(d.y) <= reach.y && Mathf.Abs(d.z) <= reach.z;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public override void OnPlayerTriggerExit(VRCPlayerApi player)
|
|
public override void OnPlayerTriggerExit(VRCPlayerApi player)
|
|
|
{
|
|
{
|
|
|
if (!playerTriggerEnabled || player == null) return;
|
|
if (!playerTriggerEnabled || player == null) return;
|