mirror of
https://github.com/nothke/quality-control.git
synced 2024-12-23 16:27:30 +00:00
233 lines
7.1 KiB
C#
233 lines
7.1 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Nothke.Interaction.Items
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Use this if mass of rigidbody changes while the rigidbody is being held
|
||
|
/// </summary>
|
||
|
public interface IDragRigidbodyReleaseMassSettable
|
||
|
{
|
||
|
float ReleaseMass { get; }
|
||
|
}
|
||
|
|
||
|
public class DragRigidbody : MonoBehaviour
|
||
|
{
|
||
|
public static DragRigidbody e;
|
||
|
private void Awake() { e = this; }
|
||
|
|
||
|
public float k_Spring = 50.0f;
|
||
|
public float k_Damper = 5.0f;
|
||
|
public float k_Drag = 0f;
|
||
|
public float k_AngularDrag = 0.0f;
|
||
|
public float k_Distance = 0.0001f;
|
||
|
public bool k_AttachToCenterOfMass = false;
|
||
|
|
||
|
public float distanceLimit = 2;
|
||
|
public float clampVelocity = 2;
|
||
|
public float clampExitVelocity = 2;
|
||
|
|
||
|
public float fakeMass = 0;
|
||
|
float originalMass;
|
||
|
|
||
|
Rigidbody body;
|
||
|
private ConfigurableJoint joint;
|
||
|
RigidbodyInterpolation originalInterpolation;
|
||
|
|
||
|
public bool Holding => joint && joint.connectedBody;
|
||
|
|
||
|
public event Action OnSlipped;
|
||
|
|
||
|
public bool Hitting { private set; get; }
|
||
|
|
||
|
float hitDistance;
|
||
|
|
||
|
private void Start()
|
||
|
{
|
||
|
CreateJoint();
|
||
|
}
|
||
|
|
||
|
void CreateJoint()
|
||
|
{
|
||
|
var go = new GameObject("Rigidbody dragger");
|
||
|
body = go.AddComponent<Rigidbody>();
|
||
|
//body.rotation = Quaternion.LookRotation(transform.forward, transform.up);
|
||
|
joint = go.AddComponent<ConfigurableJoint>();
|
||
|
body.isKinematic = true;
|
||
|
}
|
||
|
|
||
|
public float GetJointDistance()
|
||
|
{
|
||
|
if (joint && joint.connectedBody)
|
||
|
return Vector3.Distance(
|
||
|
body.position,
|
||
|
joint.connectedBody.transform.TransformPoint(joint.connectedAnchor));
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Quaternion addedRotation = Quaternion.identity;
|
||
|
[NonSerialized] public bool rotate;
|
||
|
[NonSerialized] public float rotateXInput;
|
||
|
[NonSerialized] public float rotateYInput;
|
||
|
|
||
|
bool overrideTarget = false;
|
||
|
Vector3 overrideTargetPoint;
|
||
|
|
||
|
public void OverrideTarget(Vector3 target)
|
||
|
{
|
||
|
overrideTarget = true;
|
||
|
overrideTargetPoint = target;
|
||
|
}
|
||
|
|
||
|
public void EndOverridingTarget()
|
||
|
{
|
||
|
overrideTarget = false;
|
||
|
}
|
||
|
|
||
|
public Vector3 GetFrontTargetPoint()
|
||
|
{
|
||
|
return new Ray(transform.position, transform.forward).GetPoint(hitDistance);
|
||
|
}
|
||
|
|
||
|
void FixedUpdate()
|
||
|
{
|
||
|
if (joint && joint.connectedBody)
|
||
|
{
|
||
|
//var ray = new Ray(transform.position, transform.forward);
|
||
|
|
||
|
Vector3 targetPoint = overrideTarget ? overrideTargetPoint :
|
||
|
GetFrontTargetPoint();
|
||
|
//ray.GetPoint(hitDistance);
|
||
|
|
||
|
joint.transform.position = targetPoint;
|
||
|
|
||
|
//joint.connectedBody.velocity = Vector3.ClampMagnitude(joint.connectedBody.velocity, clampVelocity);
|
||
|
//joint.targetRotation = transform.rotation;
|
||
|
//joint.targetRotation = UnityEngine.Random.rotation;
|
||
|
|
||
|
var bodyRot = body.rotation;
|
||
|
if (rotate)
|
||
|
{
|
||
|
float mx = rotateXInput * 10;
|
||
|
float my = rotateYInput * 10;
|
||
|
|
||
|
addedRotation =
|
||
|
Quaternion.AngleAxis(mx, Vector3.up) *
|
||
|
Quaternion.AngleAxis(my, Vector3.right) * addedRotation;
|
||
|
|
||
|
|
||
|
//addedRotation *= Quaternion.Euler(mx * 10, 0, my * 10);
|
||
|
|
||
|
//body.rotation = rot * addedRotation;
|
||
|
//body.MoveRotation(rot * Quaternion.Euler(4, 0, 0));
|
||
|
//joint.targetRotation = rot * Quaternion.Euler(4, 0, 0);
|
||
|
}
|
||
|
|
||
|
//Quaternion faceTo = Quaternion.Inverse(transform.rotation) * Quaternion.Euler(0, 90, 0);
|
||
|
//addedRotation = Quaternion.Slerp(addedRotation, faceTo, Time.deltaTime * 10);
|
||
|
|
||
|
body.rotation = transform.rotation * addedRotation;
|
||
|
|
||
|
if (GetJointDistance() > distanceLimit)
|
||
|
{
|
||
|
Slip();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Slip()
|
||
|
{
|
||
|
End();
|
||
|
|
||
|
if (OnSlipped != null)
|
||
|
OnSlipped();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
private void Update()
|
||
|
{
|
||
|
if (Input.GetMouseButtonUp(0) && joint && joint.connectedBody)
|
||
|
End();
|
||
|
}*/
|
||
|
|
||
|
public void Attach(RaycastHit hit, bool fixedRotation = true)
|
||
|
{
|
||
|
Attach(hit.rigidbody, hit.point, hit.distance, fixedRotation);
|
||
|
}
|
||
|
|
||
|
public void Attach(Rigidbody rigidbody, Vector3 point, float distance, bool fixedRotation)
|
||
|
{
|
||
|
if (!joint) CreateJoint();
|
||
|
|
||
|
if (fakeMass > 0)
|
||
|
{
|
||
|
originalMass = rigidbody.mass;
|
||
|
rigidbody.mass = fakeMass;
|
||
|
}
|
||
|
|
||
|
originalInterpolation = rigidbody.interpolation;
|
||
|
rigidbody.interpolation = RigidbodyInterpolation.Interpolate;
|
||
|
|
||
|
joint.transform.position = point;
|
||
|
joint.anchor = Vector3.zero;
|
||
|
joint.transform.rotation = transform.rotation;
|
||
|
//joint.targetRotation = Quaternion.identity;
|
||
|
//joint.targetRotation = Quaternion.Inverse(transform.rotation);// Quaternion.LookRotation(transform.forward, transform.up);
|
||
|
|
||
|
joint.angularXMotion = joint.angularYMotion = joint.angularZMotion
|
||
|
= fixedRotation ? ConfigurableJointMotion.Locked : ConfigurableJointMotion.Free;
|
||
|
|
||
|
JointDrive drive = new JointDrive();
|
||
|
drive.positionSpring = k_Spring;
|
||
|
drive.positionDamper = k_Damper;
|
||
|
drive.maximumForce = Mathf.Infinity;
|
||
|
|
||
|
joint.xDrive = drive;
|
||
|
joint.yDrive = drive;
|
||
|
joint.zDrive = drive;
|
||
|
|
||
|
//joint.spring = k_Spring;
|
||
|
//joint.damper = k_Damper;
|
||
|
//joint.maxDistance = k_Distance;
|
||
|
joint.connectedBody = rigidbody;
|
||
|
|
||
|
hitDistance = distance;
|
||
|
}
|
||
|
|
||
|
public void End()
|
||
|
{
|
||
|
if (!joint.connectedBody)
|
||
|
return;
|
||
|
|
||
|
if (fakeMass > 0)
|
||
|
{
|
||
|
var massSettable = joint.connectedBody.GetComponent<IDragRigidbodyReleaseMassSettable>();
|
||
|
|
||
|
if (massSettable != null)
|
||
|
{
|
||
|
joint.connectedBody.mass = massSettable.ReleaseMass;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
joint.connectedBody.mass = originalMass;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
joint.connectedBody.interpolation = originalInterpolation;
|
||
|
|
||
|
if (clampExitVelocity > 0)
|
||
|
joint.connectedBody.velocity =
|
||
|
Vector3.ClampMagnitude(joint.connectedBody.velocity, clampExitVelocity);
|
||
|
|
||
|
addedRotation = Quaternion.identity;
|
||
|
|
||
|
joint.connectedBody = null;
|
||
|
|
||
|
overrideTarget = false;
|
||
|
}
|
||
|
}
|
||
|
}
|