Unity Udexreal开发插件包
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
4.0 KiB

using UDE_HAND_INTERACTION;
using UnityEngine;
public class PhysicalHand : MonoBehaviour
{
public Transform Navigator;
[SerializeField, Min(0)]
private float TraceToloranceDist = 0.75f;
[SerializeField, Min(0)]
private float VelocityLimitation = 12f;
private float lastDistance = float.MaxValue;
private readonly float angularDragValue = 35;
private readonly float trackPosStrength = 70;
private readonly float trackRotStrength = 110;
private Transform VirtualMovePoint;
private Rigidbody _rigidbody;
void Start()
{
if(GetComponentInParent<InteractableObject>() == null)
{
VirtualMovePoint = new GameObject().transform;
VirtualMovePoint.parent = transform.parent;
VirtualMovePoint.name = transform.name + "Virtual Move Point";
_rigidbody = GetComponent<Rigidbody>();
}
}
void FixedUpdate()
{
RefreshTransform();
}
public void VirtualMovePointReset()
{
if (Navigator == null) return;
VirtualMovePoint.SetPositionAndRotation(Navigator.position, Navigator.rotation);
}
void RefreshTransform()
{
if (VirtualMovePoint == null) return;
ResfreshPosition();
RefreshRotation();
}
void ResfreshPosition()
{
VirtualMovePointReset();
var movePos = VirtualMovePoint.position;
var distance = Vector3.Distance(movePos, transform.position);
if (lastDistance != distance)
{
lastDistance = distance;
if (distance > TraceToloranceDist)
{
HandForceTransform(movePos, transform.rotation);
}
distance = Mathf.Clamp(distance, 0, 0.5f);
Vector3 vel = (movePos - transform.position).normalized * trackPosStrength * distance;
vel.x = Mathf.Clamp(vel.x, -VelocityLimitation, VelocityLimitation);
vel.y = Mathf.Clamp(vel.y, -VelocityLimitation, VelocityLimitation);
vel.z = Mathf.Clamp(vel.z, -VelocityLimitation, VelocityLimitation);
var towardsVel = new Vector3(
Mathf.MoveTowards(_rigidbody.velocity.x, vel.x, 0.5f + Mathf.Abs(_rigidbody.velocity.x) * Time.fixedDeltaTime * 60),
Mathf.MoveTowards(_rigidbody.velocity.y, vel.y, 0.5f + Mathf.Abs(_rigidbody.velocity.y) * Time.fixedDeltaTime * 60),
Mathf.MoveTowards(_rigidbody.velocity.z, vel.z, 0.5f + Mathf.Abs(_rigidbody.velocity.z) * Time.fixedDeltaTime * 60)
);
_rigidbody.velocity = towardsVel;
}
}
void RefreshRotation()
{
var delta = (VirtualMovePoint.rotation * Quaternion.Inverse(_rigidbody.rotation));
delta.ToAngleAxis(out float angle, out Vector3 axis);
if (float.IsInfinity(axis.x)) return;
angle = angle > 180f ? angle - 360f : angle;
var multiLinear = Mathf.Deg2Rad * angle * trackRotStrength;
Vector3 angular = multiLinear * axis.normalized;
angle = Mathf.Abs(angle);
var angleStrengthOffset = Mathf.Lerp(1f, 2f, angle / 45f);
_rigidbody.angularDrag = Mathf.Lerp(angularDragValue + 10, angularDragValue, angle) * Time.fixedDeltaTime * 60;
_rigidbody.angularVelocity = new Vector3(
Mathf.MoveTowards(_rigidbody.angularVelocity.x, angular.x, trackRotStrength * 5f * Time.fixedDeltaTime * 60 * angleStrengthOffset),
Mathf.MoveTowards(_rigidbody.angularVelocity.y, angular.y, trackRotStrength * 5f * Time.fixedDeltaTime * 60 * angleStrengthOffset),
Mathf.MoveTowards(_rigidbody.angularVelocity.z, angular.z, trackRotStrength * 5f * Time.fixedDeltaTime * 60 * angleStrengthOffset)
);
}
public virtual void HandForceTransform(Vector3 pos, Quaternion rot)
{
transform.SetPositionAndRotation(pos, rot);
_rigidbody.position = pos;
_rigidbody.rotation = rot;
_rigidbody.velocity = Vector3.zero;
_rigidbody.angularVelocity = Vector3.zero;
VirtualMovePointReset();
}
}