using UdonSharp; using UnityEngine; using VRC.SDKBase; using VRC.SDK3.Components; using System; [Obsolete("Component under review for further dubugging... Pardon our dust!")] [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)] [DisallowMultipleComponent] [AddComponentMenu("Artyom Scripting System/Pickup Fizzler")] public class PickupFizzler : UdonSharpBehaviour { public AudioSource fizzlerSound; // Sound to play when a pickup is fizzled public AudioSource playerEnterSound; // Sound to play when a player enters the collider public int pickupLayer = 13; // Layer number for the pickup (VRChat's Pickup layer) public float fizzleDuration = 2.0f; // Duration for the fizzle effect public Material fizzleMaterial; // Material to apply during the fizzle effect private Material[][] originalMaterials; private VRC_Pickup pickup; private VRCObjectSync objectSync; private Renderer[] renderers; private Collider pickupCollider; private Rigidbody pickupRigidbody; private bool isFizzling = false; private float fizzleTimer = 0.0f; private Vector3 storedVelocity; private Vector3 storedAngularVelocity; private Transform soundParent; // Where the fizzle sound goes back to after following a pickup private Vector3 soundLocalPosition; private Quaternion soundLocalRotation; private void Start() { // Ensure the AudioSource is initially inactive if (fizzlerSound != null) { fizzlerSound.Stop(); soundParent = fizzlerSound.transform.parent; soundLocalPosition = fizzlerSound.transform.localPosition; soundLocalRotation = fizzlerSound.transform.localRotation; } if (playerEnterSound != null) { playerEnterSound.Stop(); } } private void OnTriggerEnter(Collider other) { // Check if the collider is on the pickup layer and not already fizzling if (other == null || other.gameObject.layer != pickupLayer || isFizzling) return; // Check if the collider has a VRC_Pickup component pickup = other.GetComponent(); if (pickup == null) return; // Get the VRCObjectSync component objectSync = pickup.GetComponent(); if (objectSync == null) { Debug.LogError("[AUMSS] Pickup Fizzler: no VRCObjectSync on " + pickup.gameObject.name + ", so it can't be respawned."); return; } // Get the pickup's collider and rigidbody pickupCollider = pickup.GetComponent(); pickupRigidbody = pickup.GetComponent(); // Store the current velocity and angular velocity if (pickupRigidbody != null) { storedVelocity = pickupRigidbody.velocity; storedAngularVelocity = pickupRigidbody.angularVelocity; } // Swap every material for the fizzle material. sharedMaterials: .materials would copy them all each time renderers = pickup.GetComponentsInChildren(); originalMaterials = new Material[renderers.Length][]; for (int i = 0; i < renderers.Length; i++) { originalMaterials[i] = renderers[i].sharedMaterials; Material[] newMaterials = new Material[originalMaterials[i].Length]; for (int j = 0; j < newMaterials.Length; j++) { newMaterials[j] = fizzleMaterial; } renderers[i].sharedMaterials = newMaterials; } // Play the fizzler sound if (fizzlerSound != null) { fizzlerSound.transform.SetParent(pickup.transform); fizzlerSound.transform.localPosition = Vector3.zero; fizzlerSound.Play(); } // Disable the pickup's collider if (pickupCollider != null) { pickupCollider.enabled = false; } // Force the player to drop the pickup pickup.Drop(); // Start the fizzling process isFizzling = true; fizzleTimer = fizzleDuration; } public override void OnPlayerTriggerEnter(VRCPlayerApi player) { if (playerEnterSound != null && player.isLocal) { playerEnterSound.Play(); } } private void Update() { if (!isFizzling) return; if (!Utilities.IsValid(pickup)) { // The pickup was destroyed mid-fizzle: put the sound back and wait for the next one ResetSound(); isFizzling = false; return; } fizzleTimer -= Time.deltaTime; // Only the owner moves and respawns it; anyone else would fight the sync bool isOwner = Networking.IsOwner(pickup.gameObject); // Apply the stored velocity and angular velocity if (isOwner && pickupRigidbody != null) { pickupRigidbody.velocity = storedVelocity; pickupRigidbody.angularVelocity = storedAngularVelocity; } pickup.Drop(); if (fizzleTimer <= 0.0f) { // Respawn the pickup using VRCObjectSync if (isOwner && objectSync != null) { objectSync.Respawn(); } ResetSound(); // Re-enable the pickup's collider if (pickupCollider != null) { pickupCollider.enabled = true; } // Reset the original materials for (int i = 0; i < renderers.Length; i++) { if (renderers[i] != null) renderers[i].sharedMaterials = originalMaterials[i]; } isFizzling = false; } } private void ResetSound() { if (fizzlerSound == null) return; fizzlerSound.Stop(); fizzlerSound.transform.SetParent(soundParent); fizzlerSound.transform.localPosition = soundLocalPosition; fizzlerSound.transform.localRotation = soundLocalRotation; } }