aboutsummaryrefslogtreecommitdiff
path: root/Assets/Scripts/PhysGun.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/Scripts/PhysGun.cs')
-rw-r--r--Assets/Scripts/PhysGun.cs126
1 files changed, 126 insertions, 0 deletions
diff --git a/Assets/Scripts/PhysGun.cs b/Assets/Scripts/PhysGun.cs
new file mode 100644
index 0000000..5a00a1a
--- /dev/null
+++ b/Assets/Scripts/PhysGun.cs
@@ -0,0 +1,126 @@
+using UnityEngine;
+//Code is taken from UMod
+public class PhysGun : MonoBehaviour
+{
+ [SerializeField]
+ private float _maxGrabDistance = 40f;
+ [SerializeField]
+ private float _minGrabDistance = 1f;
+ [SerializeField]
+ private LineRenderer _pickLine;
+ [SerializeField]
+ private Transform _barrelPoint;
+
+ private Rigidbody _grabbedObject;
+ private float _pickDistance;
+ private Vector3 _pickOffset;
+ private Vector3 _pickTargetPosition;
+ private Vector3 _pickForce;
+
+ private void Start()
+ {
+ if (!_barrelPoint)
+ {
+ _barrelPoint = transform;
+ }
+ if (!_pickLine)
+ {
+ var obj = new GameObject("PhysGun Pick Line");
+ _pickLine = obj.AddComponent<LineRenderer>();
+ _pickLine.startWidth = 0.02f;
+ _pickLine.endWidth = 0.02f;
+ _pickLine.useWorldSpace = true;
+ _pickLine.gameObject.SetActive(false);
+ }
+ }
+
+ void Update()
+ {
+ if (Input.GetKeyDown(KeyCode.Mouse0))
+ {
+ Grab();
+ }
+
+ if (Input.GetKeyUp(KeyCode.Mouse0))
+ {
+ if (_grabbedObject)
+ {
+ Release();
+ }
+ }
+
+ if (Input.GetKeyDown(KeyCode.Mouse1))
+ {
+ if (_grabbedObject)
+ {
+ Release(true);
+ }
+ }
+
+ _pickDistance = Mathf.Clamp(_pickDistance + Input.mouseScrollDelta.y, _minGrabDistance, _maxGrabDistance);
+ }
+
+ private void LateUpdate()
+ {
+ if (_grabbedObject)
+ {
+ var midpoint = (transform.position + _pickTargetPosition) / 2f;
+ midpoint += Vector3.ClampMagnitude(_pickForce / 2f, 1f);
+ DrawQuadraticBezierCurve(_pickLine, _barrelPoint.position, midpoint, _grabbedObject.worldCenterOfMass - _pickOffset);
+ }
+ }
+
+ private void FixedUpdate()
+ {
+ if (_grabbedObject != null)
+ {
+ var ray = Camera.main.ViewportPointToRay(Vector3.one * .5f);
+ _pickTargetPosition = (ray.origin + ray.direction * _pickDistance) + _pickOffset;
+ var forceDir = _pickTargetPosition - _grabbedObject.position;
+ _pickForce = forceDir / Time.fixedDeltaTime * 0.3f / _grabbedObject.mass;
+ _grabbedObject.velocity = _pickForce;
+ }
+ }
+
+ private void Grab()
+ {
+ var ray = Camera.main.ViewportPointToRay(Vector3.one * .5f);
+ if(Physics.Raycast(ray, out RaycastHit hit, _maxGrabDistance)
+ && hit.rigidbody != null)
+ {
+ _pickOffset = hit.rigidbody.worldCenterOfMass - hit.point;
+ _pickDistance = hit.distance;
+ _grabbedObject = hit.rigidbody;
+ _grabbedObject.collisionDetectionMode = CollisionDetectionMode.Continuous;
+ _grabbedObject.useGravity = false;
+ _grabbedObject.freezeRotation = true;
+ _grabbedObject.isKinematic = false;
+ _pickLine.gameObject.SetActive(true);
+ }
+ }
+
+ private void Release(bool setKinematic = false)
+ {
+ _grabbedObject.collisionDetectionMode = CollisionDetectionMode.Discrete;
+ _grabbedObject.useGravity = true;
+ _grabbedObject.freezeRotation = false;
+ _grabbedObject.isKinematic = setKinematic;
+ _grabbedObject = null;
+ _pickLine.gameObject.SetActive(false);
+ }
+
+ // https://www.codinblack.com/how-to-draw-lines-circles-or-anything-else-using-linerenderer/
+ void DrawQuadraticBezierCurve(LineRenderer line, Vector3 point0, Vector3 point1, Vector3 point2)
+ {
+ line.positionCount = 10;
+ float t = 0f;
+ Vector3 B = new Vector3(0, 0, 0);
+ for (int i = 0; i < line.positionCount; i++)
+ {
+ B = (1 - t) * (1 - t) * point0 + 2 * (1 - t) * t * point1 + t * t * point2;
+ line.SetPosition(i, B);
+ t += (1 / (float)line.positionCount);
+ }
+ }
+
+}