| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- using UdonSharp;
- using UnityEngine;
- using VRC.SDKBase;
- [UdonBehaviourSyncMode(BehaviourSyncMode.NoVariableSync)]
- [DisallowMultipleComponent]
- [AddComponentMenu("Artyom Scripting System/Laser Receiver Controller")]
- public class LaserReceiver : UdonSharpBehaviour
- {
- public GameObject targetObject; // The object to turn on/off
- public int laserLayer = 22; // Layer number to detect the laser
- public Animator[] animators; // Array to hold Animators
- public string[] parameterNames; // Array to hold corresponding parameter names
- public GameObject audioObjectTrue; // GameObject to enable when the state changes to true
- public GameObject audioObjectFalse; // GameObject to enable when the state changes to false
- public GameObject audioObjectLoop; // GameObject to loop while the state is true
- public Collider triggerCollider; // Reference to the trigger collider (this object's collider if empty)
- public Renderer targetRenderer; // Renderer to change material
- public Material materialTrue; // Material to apply when the state is true
- public Material materialFalse; // Material to apply when the state is false
- public int materialIndex = 0; // Index of the material to change
- [Tooltip("Log each change of the number of lasers inside")]
- public bool debugMode;
- private int colliderCount = 0; // Counter for colliders with the laser layer
- private Collider[] collidersInsideTrigger = new Collider[16]; // Reused every frame
- private BoxCollider box; // Set when the trigger is a box: checked exactly, rotation included
- private void Start()
- {
- if (triggerCollider == null) triggerCollider = GetComponent<Collider>();
- if (triggerCollider == null)
- {
- Debug.LogError("[AUMSS] Laser Receiver Controller: no Trigger Collider assigned, and none on this object.");
- enabled = false; // Stops Update, which would otherwise throw and halt the script
- return;
- }
- box = triggerCollider.GetComponent<BoxCollider>();
- if (box != triggerCollider) box = null; // Another collider on the same object: fall back to the bounds
- // Ensure the target object is initially off
- if (targetObject != null)
- {
- targetObject.SetActive(false);
- }
- // Ensure the looping audio is initially off
- if (audioObjectLoop != null)
- {
- audioObjectLoop.SetActive(false);
- }
- // Initial check for colliders inside the trigger
- UpdateColliderCount();
- }
- private void Update()
- {
- if (triggerCollider == null) return; // Not set up (enabled = false only takes effect next frame)
- // Continuously check for colliders inside the trigger
- UpdateColliderCount();
- }
- private void UpdateColliderCount()
- {
- Vector3 boxCenter;
- Vector3 boxHalfExtents;
- Quaternion boxRotation;
- if (box != null)
- {
- Transform boxTransform = box.transform;
- boxCenter = boxTransform.TransformPoint(box.center);
- boxHalfExtents = Vector3.Scale(box.size, boxTransform.lossyScale) * 0.5f;
- boxHalfExtents = new Vector3(Mathf.Abs(boxHalfExtents.x), Mathf.Abs(boxHalfExtents.y), Mathf.Abs(boxHalfExtents.z));
- boxRotation = boxTransform.rotation;
- }
- else
- {
- // Other collider shapes: the world-space box around them
- boxCenter = triggerCollider.bounds.center;
- boxHalfExtents = triggerCollider.bounds.extents;
- boxRotation = Quaternion.identity;
- }
- int found = Physics.OverlapBoxNonAlloc(boxCenter, boxHalfExtents, collidersInsideTrigger, boxRotation,
- 1 << laserLayer, QueryTriggerInteraction.UseGlobal);
- // Update the collider count based on the result
- int newColliderCount = 0;
- for (int i = 0; i < found; i++)
- {
- if (collidersInsideTrigger[i].GetComponent<VRC_Pickup>() == null)
- {
- newColliderCount++;
- }
- }
- if (newColliderCount != colliderCount)
- {
- colliderCount = newColliderCount;
- if (debugMode) Debug.Log("[AUMSS] Laser Receiver Controller: lasers inside: " + colliderCount);
- // Turn on or off the target object based on the collider count
- bool on = colliderCount > 0;
- if (targetObject != null)
- {
- targetObject.SetActive(on);
- }
- UpdateAnims(on);
- }
- }
- private void UpdateAnims(bool state)
- {
- int count = Mathf.Min(animators.Length, parameterNames.Length);
- for (int i = 0; i < count; i++)
- {
- if (animators[i] != null && !string.IsNullOrEmpty(parameterNames[i]))
- {
- animators[i].SetBool(parameterNames[i], state);
- }
- }
- // Enable or disable GameObjects based on the state
- if (state)
- {
- if (audioObjectFalse != null) audioObjectFalse.SetActive(false);
- if (audioObjectTrue != null) audioObjectTrue.SetActive(true);
- if (audioObjectLoop != null) audioObjectLoop.SetActive(true); // Enable looping audio
- if (targetRenderer != null && materialTrue != null) SetMaterial(materialTrue); // Change material to true
- }
- else
- {
- if (audioObjectTrue != null) audioObjectTrue.SetActive(false);
- if (audioObjectFalse != null) audioObjectFalse.SetActive(true);
- if (audioObjectLoop != null) audioObjectLoop.SetActive(false); // Disable looping audio
- if (targetRenderer != null && materialFalse != null) SetMaterial(materialFalse); // Change material to false
- }
- }
- private void SetMaterial(Material material)
- {
- // sharedMaterials: .materials would make a new copy of every material on each change
- Material[] materials = targetRenderer.sharedMaterials;
- if (materialIndex >= 0 && materialIndex < materials.Length)
- {
- materials[materialIndex] = material;
- targetRenderer.sharedMaterials = materials;
- }
- }
- }
|