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.
193 lines
9.2 KiB
C#
193 lines
9.2 KiB
C#
6 months ago
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Autohand
|
||
|
{
|
||
|
[RequireComponent(typeof(Grabbable)), DefaultExecutionOrder(10)]
|
||
|
public class GrabbableHeldJoint : MonoBehaviour
|
||
|
{
|
||
|
[Tooltip("The grabbable that this grabbable is connected to")]
|
||
|
public Grabbable connectedGrabbable;
|
||
|
[Tooltip("Offsets the center of this joint")]
|
||
|
public Vector3 pivotOffset;
|
||
|
[Tooltip("This will multiply the hands strength while holding this grabbable to give it more or less positional priority while holding this joint as a second hand (good to reduce when you dont want this joint having movement priority while being held)")]
|
||
|
[Min(0.1f)]
|
||
|
public float heldMassScale = 1f;
|
||
|
[Space]
|
||
|
[Tooltip("The maximum distance this joint is allowed to move in the local positive x-axis")]
|
||
|
public float xMaxLimit = 0f;
|
||
|
[Tooltip("The maximum distance this joint is allowed to move in the local negative x-axis")]
|
||
|
public float xMinLimit = 0f;
|
||
|
[Tooltip("This will force the joint back into its center position based on the given spring strength while not being held along this axis")]
|
||
|
public float xSpring = 0f;
|
||
|
[Space]
|
||
|
[Tooltip("The maximum distance this joint is allowed to move in the local positive y-axis")]
|
||
|
public float yMaxLimit = 0f;
|
||
|
[Tooltip("The maximum distance this joint is allowed to move in the local negative y-axis")]
|
||
|
public float yMinLimit = 0f;
|
||
|
[Tooltip("This will force the joint back into its center position based on the given spring strength while not being held along this axis")]
|
||
|
public float ySpring = 0f;
|
||
|
[Space]
|
||
|
[Tooltip("The maximum distance this joint is allowed to move in the local positive z-axis")]
|
||
|
public float zMaxLimit = 0f;
|
||
|
[Tooltip("The maximum distance this joint is allowed to move in the local negative z-axis")]
|
||
|
public float zMinLimit = 0f;
|
||
|
[Tooltip("This will force the joint back into its center position based on the given spring strength while not being held along this axis")]
|
||
|
public float zSpring = 0f;
|
||
|
|
||
|
[Space]
|
||
|
[Range(0, 1), Tooltip("The percentage from the min/max distance needed to trigger the event, good for creating a buffer for the event to trigger slightly before the max range to help prevent missed event")]
|
||
|
public float eventOffset = 0.05f;
|
||
|
|
||
|
public UnityHandGrabEvent OnMinDistanceEvent;
|
||
|
public UnityHandGrabEvent OnMaxDistanceEvent;
|
||
|
|
||
|
bool triggeredMaxEvent;
|
||
|
bool triggeredMinEvent;
|
||
|
|
||
|
Vector3 handLocalPosition;
|
||
|
Vector3 localPosition;
|
||
|
Vector3 localTargetPosition;
|
||
|
Vector3 localStartPosition;
|
||
|
|
||
|
Grabbable grabbable;
|
||
|
Vector3 localOrigin;
|
||
|
Vector3 localStartOrigin;
|
||
|
Hand jointHand;
|
||
|
bool grabFrame;
|
||
|
bool started = false;
|
||
|
public void Start()
|
||
|
{
|
||
|
if(started)
|
||
|
return;
|
||
|
|
||
|
ResetOrigin();
|
||
|
|
||
|
if(grabbable == null) {
|
||
|
grabbable = GetComponent<Grabbable>();
|
||
|
grabbable.OnGrabEvent += OnGrabbed;
|
||
|
grabbable.OnReleaseEvent += OnReleased;
|
||
|
}
|
||
|
grabbable.singleHandOnly = true;
|
||
|
|
||
|
if(xMinLimit == 0 && yMinLimit == 0 && zMinLimit == 0)
|
||
|
triggeredMinEvent = true;
|
||
|
started = true;
|
||
|
}
|
||
|
|
||
|
public void ResetOrigin()
|
||
|
{
|
||
|
localOrigin = connectedGrabbable.rootTransform.InverseTransformPoint(transform.position) + pivotOffset;
|
||
|
localStartOrigin = localOrigin;
|
||
|
}
|
||
|
|
||
|
internal void OnGrabbed(Hand hand, Grabbable grab)
|
||
|
{
|
||
|
jointHand = hand;
|
||
|
hand.body.mass *= heldMassScale;
|
||
|
|
||
|
localOrigin = hand.heldJoint.connectedAnchor + pivotOffset;
|
||
|
localTargetPosition = new Vector3(
|
||
|
Mathf.Clamp(handLocalPosition.x, localOrigin.x + xMinLimit, localOrigin.x + xMaxLimit),
|
||
|
Mathf.Clamp(handLocalPosition.y, localOrigin.y + yMinLimit, localOrigin.y + yMaxLimit),
|
||
|
Mathf.Clamp(handLocalPosition.z, localOrigin.z + zMinLimit, localOrigin.z + zMaxLimit)
|
||
|
);
|
||
|
|
||
|
localTargetPosition += pivotOffset;
|
||
|
grabFrame = true;
|
||
|
}
|
||
|
|
||
|
void OnReleased(Hand hand, Grabbable grab)
|
||
|
{
|
||
|
jointHand = null;
|
||
|
hand.body.mass /= heldMassScale;
|
||
|
|
||
|
localOrigin = localStartOrigin;
|
||
|
}
|
||
|
|
||
|
private void FixedUpdate()
|
||
|
{
|
||
|
if(grabFrame) {
|
||
|
grabFrame = false;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UpdateJoint();
|
||
|
}
|
||
|
|
||
|
public void SetJointMax() {
|
||
|
transform.position = connectedGrabbable.rootTransform.TransformPoint(localOrigin + pivotOffset + new Vector3(xMaxLimit, yMaxLimit, zMaxLimit));
|
||
|
}
|
||
|
|
||
|
public void SetJointMin() {
|
||
|
transform.position = connectedGrabbable.rootTransform.TransformPoint(localOrigin + pivotOffset + new Vector3(xMinLimit, yMinLimit, zMinLimit));
|
||
|
}
|
||
|
|
||
|
public void UpdateJoint()
|
||
|
{
|
||
|
if (connectedGrabbable.HeldCount() > 0 && grabbable.HeldCount(false, false, true) > 0 && jointHand != null)
|
||
|
{
|
||
|
handLocalPosition = jointHand.heldJoint.connectedBody.transform.InverseTransformPoint(jointHand.moveTo.position) + pivotOffset;
|
||
|
localPosition = jointHand.heldJoint.connectedAnchor + pivotOffset;
|
||
|
localTargetPosition = new Vector3(
|
||
|
Mathf.MoveTowards(localPosition.x, Mathf.Clamp(handLocalPosition.x, localOrigin.x + xMinLimit, localOrigin.x + xMaxLimit), 1f),
|
||
|
Mathf.MoveTowards(localPosition.y, Mathf.Clamp(handLocalPosition.y, localOrigin.y + yMinLimit, localOrigin.y + yMaxLimit), 1f),
|
||
|
Mathf.MoveTowards(localPosition.z, Mathf.Clamp(handLocalPosition.z, localOrigin.z + zMinLimit, localOrigin.z + zMaxLimit), 1f)
|
||
|
);
|
||
|
|
||
|
if(localPosition != localTargetPosition) {
|
||
|
//Vector3 globalTargetPosition = connectedGrabbable.rootTransform.TransformPoint(localTargetPosition - jointHand.handGrabPoint.localPosition);
|
||
|
transform.localPosition += (localTargetPosition - localPosition); // Adjusting position with pivot offset
|
||
|
transform.localPosition = new Vector3(
|
||
|
Mathf.Clamp(transform.localPosition.x, localStartOrigin.x + xMinLimit, localStartOrigin.x + xMaxLimit),
|
||
|
Mathf.Clamp(transform.localPosition.y, localStartOrigin.y + yMinLimit, localStartOrigin.y + yMaxLimit),
|
||
|
Mathf.Clamp(transform.localPosition.z, localStartOrigin.z + zMinLimit, localStartOrigin.z + zMaxLimit)
|
||
|
);
|
||
|
jointHand.heldJoint.connectedAnchor += (localTargetPosition - localPosition);
|
||
|
jointHand.handGrabPoint.localPosition += (localTargetPosition - localPosition);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Vector3 localPosition = connectedGrabbable.transform.InverseTransformPoint(transform.position) + pivotOffset;
|
||
|
Vector3 localTargetPosition = new Vector3(
|
||
|
Mathf.MoveTowards(localPosition.x, localOrigin.x, Time.fixedDeltaTime * xSpring),
|
||
|
Mathf.MoveTowards(localPosition.y, localOrigin.y, Time.fixedDeltaTime * ySpring),
|
||
|
Mathf.MoveTowards(localPosition.z, localOrigin.z, Time.fixedDeltaTime * zSpring)
|
||
|
);
|
||
|
|
||
|
if(transform.localPosition != localOrigin)
|
||
|
transform.position = connectedGrabbable.rootTransform.TransformPoint(localTargetPosition);
|
||
|
}
|
||
|
|
||
|
if(OnMaxDistanceEvent != null) {
|
||
|
var localPos = connectedGrabbable.rootTransform.InverseTransformPoint(transform.position);
|
||
|
bool greaterOrEqual =
|
||
|
localPos.x >= localStartOrigin.x + xMaxLimit - xMaxLimit * eventOffset - 0.001f &&
|
||
|
localPos.y >= localStartOrigin.y + yMaxLimit - yMaxLimit * eventOffset - 0.001f &&
|
||
|
localPos.z >= localStartOrigin.z + zMaxLimit - zMaxLimit * eventOffset - 0.001f;
|
||
|
|
||
|
if(greaterOrEqual && !triggeredMaxEvent) {
|
||
|
OnMaxDistanceEvent.Invoke(jointHand, connectedGrabbable);
|
||
|
triggeredMaxEvent = true;
|
||
|
triggeredMinEvent = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(OnMinDistanceEvent != null) {
|
||
|
var localPos = connectedGrabbable.rootTransform.InverseTransformPoint(transform.position);
|
||
|
bool lessOrEqual =
|
||
|
localPos.x <= localStartOrigin.x + xMinLimit - xMinLimit * eventOffset + 0.001f &&
|
||
|
localPos.y <= localStartOrigin.y + yMinLimit - yMinLimit * eventOffset + 0.001f &&
|
||
|
localPos.z <= localStartOrigin.z + zMinLimit - zMinLimit * eventOffset + 0.001f;
|
||
|
|
||
|
if(lessOrEqual && !triggeredMinEvent) {
|
||
|
OnMinDistanceEvent.Invoke(jointHand, connectedGrabbable);
|
||
|
triggeredMinEvent = true;
|
||
|
triggeredMaxEvent = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|