Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- /// <summary>
- /// 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.
- /// </summary>
- public class PhysicsPickupController : MonoBehaviour {
- [SerializeField]
- ConfigurableJoint _holderJoint;
- [SerializeField]
- Rigidbody _holdingRigidbody;
- [SerializeField]
- float _raycastGrabDistance = 1;
- [SerializeField]
- float _raycastHoldDistance = 3f;
- [SerializeField]
- float _sphereCastRadius = .5f;
- [SerializeField]
- float _minHoldDistance = 1;
- [SerializeField]
- float _offsetHoldDistance = -1;
- [SerializeField]
- bool _freezeRotationOnPickup;
- Rigidbody _attachedRigidbody;
- #region Properties
- public float CurrentHoldDistance { get; private set; }
- public bool FreezeRotationOnPickup {
- get { return _freezeRotationOnPickup; }
- set { _freezeRotationOnPickup = value; }
- }
- public ConfigurableJoint HolderJoint {
- get { return _holderJoint; }
- }
- public Rigidbody HoldingRigidbody {
- get { return _holdingRigidbody; }
- set {
- if(HoldingRigidbody == value) return;
- if(HoldingRigidbody) IgnoreCollisions(HoldingRigidbody, false);
- else IgnoreCollisions(value, true);
- _holdingRigidbody = value;
- HolderJoint.connectedBody = value;
- }
- }
- public float MinHoldDistance {
- get { return _minHoldDistance; }
- set { _minHoldDistance = value; }
- }
- public float OffsetHoldDistance {
- get { return _offsetHoldDistance; }
- set { _offsetHoldDistance = value; }
- }
- public float RaycastGrabDistance {
- get { return _raycastGrabDistance; }
- set { _raycastGrabDistance = value; }
- }
- public float RaycastHoldDistance {
- get { return _raycastHoldDistance; }
- set { _raycastHoldDistance = value; }
- }
- public float SphereCastRadius {
- get { return _sphereCastRadius; }
- set { _sphereCastRadius = value; }
- }
- #endregion
- void Awake() {
- _attachedRigidbody = GetComponentInParent<Rigidbody>();
- }
- void Update() {
- UpdateHold();
- }
- public void Drop() {
- if(!HoldingRigidbody) return;
- if(FreezeRotationOnPickup)
- HoldingRigidbody.constraints &= ~RigidbodyConstraints.FreezeRotation;
- HoldingRigidbody = null;
- }
- public void Grab() {
- if(HoldingRigidbody) return;
- var ray = new Ray(transform.position, transform.forward);
- RaycastHit hit;
- if(Physics.Raycast(ray, out hit, RaycastHoldDistance, -1, QueryTriggerInteraction.Ignore)) {
- HoldingRigidbody = hit.rigidbody;
- if(FreezeRotationOnPickup)
- HoldingRigidbody.constraints |= RigidbodyConstraints.FreezeRotation;
- }
- }
- public void ToggleGrab() {
- if(HoldingRigidbody) Drop();
- else Grab();
- }
- void IgnoreCollisions(Rigidbody rigidbody, bool ignore) {
- if(rigidbody && _attachedRigidbody) {
- Collider holdingCollider = rigidbody.GetComponentInChildren<Collider>();
- foreach(var collider in _attachedRigidbody.GetComponentsInChildren<Collider>())
- Physics.IgnoreCollision(collider, holdingCollider, ignore);
- }
- }
- void UpdateHold() {
- if(!HoldingRigidbody) return;
- var ray = new Ray(transform.position, transform.forward);
- var raycastHits = Physics.SphereCastAll(ray, SphereCastRadius, RaycastHoldDistance, -1, QueryTriggerInteraction.Ignore);
- float maxHoldDistance = RaycastHoldDistance;
- raycastHits = raycastHits.OrderBy(s => s.distance).ToArray();
- for(int i = 0; i < raycastHits.Length; i++) {
- RaycastHit hit = raycastHits[i];
- if(!hit.collider.attachedRigidbody || (hit.collider.attachedRigidbody != HoldingRigidbody && hit.collider.attachedRigidbody != _attachedRigidbody)) {
- maxHoldDistance = Mathf.Min(hit.distance, RaycastHoldDistance);
- break;
- }
- }
- CurrentHoldDistance = Mathf.Max(MinHoldDistance, maxHoldDistance + OffsetHoldDistance);
- HolderJoint.transform.localPosition = new Vector3(0, 0, CurrentHoldDistance);
- }
- void OnDrawGizmos() {
- Gizmos.color = new Color(.2f, .6f, .2f);
- Gizmos.DrawRay(transform.position, transform.forward * RaycastGrabDistance);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment