PickupFizzler.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. using UdonSharp;
  2. using UnityEngine;
  3. using VRC.SDKBase;
  4. using VRC.SDK3.Components;
  5. using System;
  6. [Obsolete("Component under review for further dubugging... Pardon our dust!")]
  7. [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)]
  8. [DisallowMultipleComponent]
  9. [AddComponentMenu("Artyom Scripting System/Pickup Fizzler")]
  10. public class PickupFizzler : UdonSharpBehaviour
  11. {
  12. public AudioSource fizzlerSound; // Sound to play when a pickup is fizzled
  13. public AudioSource playerEnterSound; // Sound to play when a player enters the collider
  14. public int pickupLayer = 13; // Layer number for the pickup (VRChat's Pickup layer)
  15. public float fizzleDuration = 2.0f; // Duration for the fizzle effect
  16. public Material fizzleMaterial; // Material to apply during the fizzle effect
  17. private Material[][] originalMaterials;
  18. private VRC_Pickup pickup;
  19. private VRCObjectSync objectSync;
  20. private Renderer[] renderers;
  21. private Collider pickupCollider;
  22. private Rigidbody pickupRigidbody;
  23. private bool isFizzling = false;
  24. private float fizzleTimer = 0.0f;
  25. private Vector3 storedVelocity;
  26. private Vector3 storedAngularVelocity;
  27. private Transform soundParent; // Where the fizzle sound goes back to after following a pickup
  28. private Vector3 soundLocalPosition;
  29. private Quaternion soundLocalRotation;
  30. private void Start()
  31. {
  32. // Ensure the AudioSource is initially inactive
  33. if (fizzlerSound != null)
  34. {
  35. fizzlerSound.Stop();
  36. soundParent = fizzlerSound.transform.parent;
  37. soundLocalPosition = fizzlerSound.transform.localPosition;
  38. soundLocalRotation = fizzlerSound.transform.localRotation;
  39. }
  40. if (playerEnterSound != null)
  41. {
  42. playerEnterSound.Stop();
  43. }
  44. }
  45. private void OnTriggerEnter(Collider other)
  46. {
  47. // Check if the collider is on the pickup layer and not already fizzling
  48. if (other == null || other.gameObject.layer != pickupLayer || isFizzling) return;
  49. // Check if the collider has a VRC_Pickup component
  50. pickup = other.GetComponent<VRC_Pickup>();
  51. if (pickup == null) return;
  52. // Get the VRCObjectSync component
  53. objectSync = pickup.GetComponent<VRCObjectSync>();
  54. if (objectSync == null)
  55. {
  56. Debug.LogError("[AUMSS] Pickup Fizzler: no VRCObjectSync on " + pickup.gameObject.name + ", so it can't be respawned.");
  57. return;
  58. }
  59. // Get the pickup's collider and rigidbody
  60. pickupCollider = pickup.GetComponent<Collider>();
  61. pickupRigidbody = pickup.GetComponent<Rigidbody>();
  62. // Store the current velocity and angular velocity
  63. if (pickupRigidbody != null)
  64. {
  65. storedVelocity = pickupRigidbody.velocity;
  66. storedAngularVelocity = pickupRigidbody.angularVelocity;
  67. }
  68. // Swap every material for the fizzle material. sharedMaterials: .materials would copy them all each time
  69. renderers = pickup.GetComponentsInChildren<Renderer>();
  70. originalMaterials = new Material[renderers.Length][];
  71. for (int i = 0; i < renderers.Length; i++)
  72. {
  73. originalMaterials[i] = renderers[i].sharedMaterials;
  74. Material[] newMaterials = new Material[originalMaterials[i].Length];
  75. for (int j = 0; j < newMaterials.Length; j++)
  76. {
  77. newMaterials[j] = fizzleMaterial;
  78. }
  79. renderers[i].sharedMaterials = newMaterials;
  80. }
  81. // Play the fizzler sound
  82. if (fizzlerSound != null)
  83. {
  84. fizzlerSound.transform.SetParent(pickup.transform);
  85. fizzlerSound.transform.localPosition = Vector3.zero;
  86. fizzlerSound.Play();
  87. }
  88. // Disable the pickup's collider
  89. if (pickupCollider != null)
  90. {
  91. pickupCollider.enabled = false;
  92. }
  93. // Force the player to drop the pickup
  94. pickup.Drop();
  95. // Start the fizzling process
  96. isFizzling = true;
  97. fizzleTimer = fizzleDuration;
  98. }
  99. public override void OnPlayerTriggerEnter(VRCPlayerApi player)
  100. {
  101. if (playerEnterSound != null && player.isLocal)
  102. {
  103. playerEnterSound.Play();
  104. }
  105. }
  106. private void Update()
  107. {
  108. if (!isFizzling) return;
  109. if (!Utilities.IsValid(pickup))
  110. {
  111. // The pickup was destroyed mid-fizzle: put the sound back and wait for the next one
  112. ResetSound();
  113. isFizzling = false;
  114. return;
  115. }
  116. fizzleTimer -= Time.deltaTime;
  117. // Only the owner moves and respawns it; anyone else would fight the sync
  118. bool isOwner = Networking.IsOwner(pickup.gameObject);
  119. // Apply the stored velocity and angular velocity
  120. if (isOwner && pickupRigidbody != null)
  121. {
  122. pickupRigidbody.velocity = storedVelocity;
  123. pickupRigidbody.angularVelocity = storedAngularVelocity;
  124. }
  125. pickup.Drop();
  126. if (fizzleTimer <= 0.0f)
  127. {
  128. // Respawn the pickup using VRCObjectSync
  129. if (isOwner && objectSync != null)
  130. {
  131. objectSync.Respawn();
  132. }
  133. ResetSound();
  134. // Re-enable the pickup's collider
  135. if (pickupCollider != null)
  136. {
  137. pickupCollider.enabled = true;
  138. }
  139. // Reset the original materials
  140. for (int i = 0; i < renderers.Length; i++)
  141. {
  142. if (renderers[i] != null) renderers[i].sharedMaterials = originalMaterials[i];
  143. }
  144. isFizzling = false;
  145. }
  146. }
  147. private void ResetSound()
  148. {
  149. if (fizzlerSound == null) return;
  150. fizzlerSound.Stop();
  151. fizzlerSound.transform.SetParent(soundParent);
  152. fizzlerSound.transform.localPosition = soundLocalPosition;
  153. fizzlerSound.transform.localRotation = soundLocalRotation;
  154. }
  155. }