GibTreaty

PhysicsPickupController.cs

Sep 8th, 2016
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.66 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEngine;
  4.  
  5. /// <summary>
  6. /// Use Grab, Drop and ToggleGrab to grab/drop. A Holder Joint must be defined. It should be another GameObject that is parented to the camera that has a Rigidbody and ConfigurableJoint.
  7. /// </summary>
  8. public class PhysicsPickupController : MonoBehaviour {
  9.  
  10.     [SerializeField]
  11.     ConfigurableJoint _holderJoint;
  12.  
  13.     [SerializeField]
  14.     Rigidbody _holdingRigidbody;
  15.  
  16.     [SerializeField]
  17.     float _raycastGrabDistance = 1;
  18.  
  19.     [SerializeField]
  20.     float _raycastHoldDistance = 3f;
  21.  
  22.     [SerializeField]
  23.     float _sphereCastRadius = .5f;
  24.  
  25.     [SerializeField]
  26.     float _minHoldDistance = 1;
  27.  
  28.     [SerializeField]
  29.     float _offsetHoldDistance = -1;
  30.  
  31.     [SerializeField]
  32.     bool _freezeRotationOnPickup;
  33.  
  34.     Rigidbody _attachedRigidbody;
  35.  
  36.     #region Properties
  37.     public float CurrentHoldDistance { get; private set; }
  38.  
  39.     public bool FreezeRotationOnPickup {
  40.         get { return _freezeRotationOnPickup; }
  41.         set { _freezeRotationOnPickup = value; }
  42.     }
  43.  
  44.     public ConfigurableJoint HolderJoint {
  45.         get { return _holderJoint; }
  46.     }
  47.  
  48.     public Rigidbody HoldingRigidbody {
  49.         get { return _holdingRigidbody; }
  50.         set {
  51.             if(HoldingRigidbody == value) return;
  52.  
  53.             if(HoldingRigidbody) IgnoreCollisions(HoldingRigidbody, false);
  54.             else IgnoreCollisions(value, true);
  55.  
  56.             _holdingRigidbody = value;
  57.  
  58.             HolderJoint.connectedBody = value;
  59.         }
  60.     }
  61.  
  62.     public float MinHoldDistance {
  63.         get { return _minHoldDistance; }
  64.         set { _minHoldDistance = value; }
  65.     }
  66.  
  67.     public float OffsetHoldDistance {
  68.         get { return _offsetHoldDistance; }
  69.         set { _offsetHoldDistance = value; }
  70.     }
  71.  
  72.     public float RaycastGrabDistance {
  73.         get { return _raycastGrabDistance; }
  74.         set { _raycastGrabDistance = value; }
  75.     }
  76.  
  77.     public float RaycastHoldDistance {
  78.         get { return _raycastHoldDistance; }
  79.         set { _raycastHoldDistance = value; }
  80.     }
  81.  
  82.     public float SphereCastRadius {
  83.         get { return _sphereCastRadius; }
  84.         set { _sphereCastRadius = value; }
  85.     }
  86.     #endregion
  87.  
  88.     void Awake() {
  89.         _attachedRigidbody = GetComponentInParent<Rigidbody>();
  90.     }
  91.  
  92.     void Update() {
  93.         UpdateHold();
  94.     }
  95.  
  96.     public void Drop() {
  97.         if(!HoldingRigidbody) return;
  98.  
  99.         if(FreezeRotationOnPickup)
  100.             HoldingRigidbody.constraints &= ~RigidbodyConstraints.FreezeRotation;
  101.  
  102.         HoldingRigidbody = null;
  103.     }
  104.  
  105.     public void Grab() {
  106.         if(HoldingRigidbody) return;
  107.  
  108.         var ray = new Ray(transform.position, transform.forward);
  109.         RaycastHit hit;
  110.  
  111.         if(Physics.Raycast(ray, out hit, RaycastHoldDistance, -1, QueryTriggerInteraction.Ignore)) {
  112.             HoldingRigidbody = hit.rigidbody;
  113.  
  114.             if(FreezeRotationOnPickup)
  115.                 HoldingRigidbody.constraints |= RigidbodyConstraints.FreezeRotation;
  116.         }
  117.     }
  118.  
  119.     public void ToggleGrab() {
  120.         if(HoldingRigidbody) Drop();
  121.         else Grab();
  122.     }
  123.  
  124.     void IgnoreCollisions(Rigidbody rigidbody, bool ignore) {
  125.         if(rigidbody && _attachedRigidbody) {
  126.             Collider holdingCollider = rigidbody.GetComponentInChildren<Collider>();
  127.  
  128.             foreach(var collider in _attachedRigidbody.GetComponentsInChildren<Collider>())
  129.                 Physics.IgnoreCollision(collider, holdingCollider, ignore);
  130.         }
  131.     }
  132.  
  133.     void UpdateHold() {
  134.         if(!HoldingRigidbody) return;
  135.  
  136.         var ray = new Ray(transform.position, transform.forward);
  137.         var raycastHits = Physics.SphereCastAll(ray, SphereCastRadius, RaycastHoldDistance, -1, QueryTriggerInteraction.Ignore);
  138.         float maxHoldDistance = RaycastHoldDistance;
  139.  
  140.         raycastHits = raycastHits.OrderBy(s => s.distance).ToArray();
  141.  
  142.         for(int i = 0; i < raycastHits.Length; i++) {
  143.             RaycastHit hit = raycastHits[i];
  144.  
  145.             if(!hit.collider.attachedRigidbody || (hit.collider.attachedRigidbody != HoldingRigidbody && hit.collider.attachedRigidbody != _attachedRigidbody)) {
  146.                 maxHoldDistance = Mathf.Min(hit.distance, RaycastHoldDistance);
  147.                 break;
  148.             }
  149.         }
  150.  
  151.         CurrentHoldDistance = Mathf.Max(MinHoldDistance, maxHoldDistance + OffsetHoldDistance);
  152.         HolderJoint.transform.localPosition = new Vector3(0, 0, CurrentHoldDistance);
  153.     }
  154.  
  155.     void OnDrawGizmos() {
  156.         Gizmos.color = new Color(.2f, .6f, .2f);
  157.         Gizmos.DrawRay(transform.position, transform.forward * RaycastGrabDistance);
  158.     }
  159. }
Advertisement
Add Comment
Please, Sign In to add comment