You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			164 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
		
		
			
		
	
	
			164 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
| 
								 
											1 year ago
										 
									 | 
							
								using System;
							 | 
						||
| 
								 | 
							
								using System.Collections;
							 | 
						||
| 
								 | 
							
								using UnityEngine;
							 | 
						||
| 
								 | 
							
								using UnityEngine.Events;
							 | 
						||
| 
								 | 
							
								using UnityEngine.SceneManagement;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace Autohand {
							 | 
						||
| 
								 | 
							
								    [Serializable, DefaultExecutionOrder(100)] 
							 | 
						||
| 
								 | 
							
								    public class UnityDispenserEvent : UnityEvent<DispenserPoint, Grabbable> { }
							 | 
						||
| 
								 | 
							
								    public class DispenserPoint : MonoBehaviour {
							 | 
						||
| 
								 | 
							
								        [AutoHeader("Dispenser Point")]
							 | 
						||
| 
								 | 
							
								        public bool ignoreMe;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        [AutoSmallHeader("Dispenser Settings")]
							 | 
						||
| 
								 | 
							
								        public bool showeSettings = true;
							 | 
						||
| 
								 | 
							
								        [Tooltip("The object to be copied and dispensed")]
							 | 
						||
| 
								 | 
							
								        public Grabbable dispenseObject;
							 | 
						||
| 
								 | 
							
								        [Tooltip("The maximum copies allowed to exist from this dispenser before they are destroyed or reset")]
							 | 
						||
| 
								 | 
							
								        public int maxCopies = 3;
							 | 
						||
| 
								 | 
							
								        [Tooltip("The delay in seconds before the next dispense appears after the current dispense is taken")]
							 | 
						||
| 
								 | 
							
								        public float resetDelay = 0f;
							 | 
						||
| 
								 | 
							
								        [Tooltip("Whether or not objects placed in the dispense point should be set to kinematic on placed or not")]
							 | 
						||
| 
								 | 
							
								        public bool disableBody = false;
							 | 
						||
| 
								 | 
							
								        [NaughtyAttributes.HideIf("disableBody"), Tooltip("Whether or not objects placed in the dispense point should be set to kinematic on placed or not")]
							 | 
						||
| 
								 | 
							
								        public bool isKinematic = true;
							 | 
						||
| 
								 | 
							
								        [Tooltip("If true the object will not just reset its position on reset it will be destroyed and a new copy will be placed. Less performant but important for things like ammo that should always respawn as new clips full")]
							 | 
						||
| 
								 | 
							
								        public bool destroyOnReset = false;
							 | 
						||
| 
								 | 
							
								        [Tooltip("The maximum distance a dispensed object can move from the point before the next object is dispensed")]
							 | 
						||
| 
								 | 
							
								        public float maxDistance = 1f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        [Space]
							 | 
						||
| 
								 | 
							
								        public UnityDispenserEvent OnGrabDispenseEvent;
							 | 
						||
| 
								 | 
							
								        public UnityDispenserEvent OnDispenseEvent;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        Grabbable currentDispense;
							 | 
						||
| 
								 | 
							
								        Grabbable lastDispense;
							 | 
						||
| 
								 | 
							
								        GameObject[] dispensePool;
							 | 
						||
| 
								 | 
							
								        int poolCount;
							 | 
						||
| 
								 | 
							
								        Coroutine dispenseRoutine;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        protected virtual void Start() {
							 | 
						||
| 
								 | 
							
								            GameObject instanceObject;
							 | 
						||
| 
								 | 
							
								            dispenseObject.body.gameObject.SetActive(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            instanceObject = Instantiate(dispenseObject.body.gameObject);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            instanceObject.transform.position = transform.position;
							 | 
						||
| 
								 | 
							
								            instanceObject.transform.rotation = transform.rotation;
							 | 
						||
| 
								 | 
							
								            instanceObject.SetActive(true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            dispensePool = new GameObject[maxCopies];
							 | 
						||
| 
								 | 
							
								            dispensePool[0] = instanceObject;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if(dispensePool[0].HasGrabbable(out var grab)) {
							 | 
						||
| 
								 | 
							
								                if(!disableBody && isKinematic && grab.body != null)
							 | 
						||
| 
								 | 
							
								                    grab.body.isKinematic = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                grab.OnGrabEvent += OnGrab;
							 | 
						||
| 
								 | 
							
								                grab.OnPlacePointAddEvent += OnPlaced;
							 | 
						||
| 
								 | 
							
								                currentDispense = grab;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if(disableBody)
							 | 
						||
| 
								 | 
							
								                    grab.DeactivateRigidbody();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            poolCount++;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        protected virtual void OnDisable() {
							 | 
						||
| 
								 | 
							
								            if(dispenseRoutine != null)
							 | 
						||
| 
								 | 
							
								                StopCoroutine(dispenseRoutine);
							 | 
						||
| 
								 | 
							
								            dispenseRoutine = null;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        protected virtual void FixedUpdate() { 
							 | 
						||
| 
								 | 
							
								            if(maxDistance > 0 && currentDispense.gameObject.activeInHierarchy && Vector3.Distance(transform.position, currentDispense.rootTransform.position) > maxDistance)
							 | 
						||
| 
								 | 
							
								                Dispense();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public virtual Grabbable Dispense() {
							 | 
						||
| 
								 | 
							
								            if(dispenseRoutine == null) {
							 | 
						||
| 
								 | 
							
								                var poolIndex = (poolCount) % maxCopies;
							 | 
						||
| 
								 | 
							
								                if(destroyOnReset) {
							 | 
						||
| 
								 | 
							
								                    Destroy(dispensePool[poolIndex]);
							 | 
						||
| 
								 | 
							
								                    dispensePool[poolIndex] = null;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if(poolCount < maxCopies || dispensePool[poolIndex] == null || dispensePool[poolIndex].activeInHierarchy == false)
							 | 
						||
| 
								 | 
							
								                    dispensePool[poolIndex] = Instantiate(dispenseObject.body.gameObject);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                dispensePool[poolIndex].transform.position = transform.position;
							 | 
						||
| 
								 | 
							
								                dispensePool[poolIndex].transform.rotation = transform.rotation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if(dispensePool[poolIndex].HasGrabbable(out var grab)) {
							 | 
						||
| 
								 | 
							
								                    grab.ForceHandsRelease();
							 | 
						||
| 
								 | 
							
								                    if(grab.placePoint != null)
							 | 
						||
| 
								 | 
							
								                        grab.placePoint.Remove();
							 | 
						||
| 
								 | 
							
								                    if(grab.body == null)
							 | 
						||
| 
								 | 
							
								                        grab.ActivateRigidbody();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if(!disableBody && isKinematic)
							 | 
						||
| 
								 | 
							
								                        grab.body.isKinematic = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    if(!grab.body.isKinematic) {
							 | 
						||
| 
								 | 
							
								                        grab.body.velocity = Vector3.zero;
							 | 
						||
| 
								 | 
							
								                        grab.body.angularVelocity = Vector3.zero;
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    grab.OnGrabEvent += OnGrab;
							 | 
						||
| 
								 | 
							
								                    grab.OnPlacePointAddEvent += OnPlaced;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    dispenseRoutine = StartCoroutine(DispenseResetDelay(grab));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    lastDispense = currentDispense;
							 | 
						||
| 
								 | 
							
								                    lastDispense.OnGrabEvent -= OnGrab;
							 | 
						||
| 
								 | 
							
								                    lastDispense.OnPlacePointAddEvent -= OnPlaced;
							 | 
						||
| 
								 | 
							
								                    currentDispense = grab;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    poolCount++;
							 | 
						||
| 
								 | 
							
								                    return grab;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                poolCount++;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            return null;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public virtual void OnGrab(Hand hand, Grabbable grab) {
							 | 
						||
| 
								 | 
							
								            if(grab != null && isKinematic && grab.body != null)
							 | 
						||
| 
								 | 
							
								                grab.body.isKinematic = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            OnGrabDispenseEvent?.Invoke(this, grab);
							 | 
						||
| 
								 | 
							
								            Dispense();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public virtual void OnPlaced(PlacePoint point, Grabbable grab) {
							 | 
						||
| 
								 | 
							
								            if(grab != null && isKinematic && grab.body != null)
							 | 
						||
| 
								 | 
							
								                grab.body.isKinematic = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            Debug.Log("Placed: " + grab.body.isKinematic);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            Dispense();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        IEnumerator DispenseResetDelay(Grabbable dispenseObject) {
							 | 
						||
| 
								 | 
							
								            dispenseObject.body.gameObject.SetActive(false);
							 | 
						||
| 
								 | 
							
								            yield return new WaitForSeconds(resetDelay);
							 | 
						||
| 
								 | 
							
								            dispenseObject.body.gameObject.SetActive(true);
							 | 
						||
| 
								 | 
							
								            dispenseObject.IgnoreGrabbableCollisionUntilNone(lastDispense);
							 | 
						||
| 
								 | 
							
								            foreach(var hand in lastDispense.GetHeldBy())
							 | 
						||
| 
								 | 
							
								                dispenseObject.IgnoreHandCollisionUntilNone(hand);
							 | 
						||
| 
								 | 
							
								            OnDispenseEvent?.Invoke(this, dispenseObject);
							 | 
						||
| 
								 | 
							
								            if(disableBody)
							 | 
						||
| 
								 | 
							
								                dispenseObject.DeactivateRigidbody();
							 | 
						||
| 
								 | 
							
								            dispenseRoutine = null;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |