|
|
using System.Collections;using System.Collections.Generic;using UnityEngine;
namespace Valve.VR.InteractionSystem{ public class HandCollider : MonoBehaviour { private new Rigidbody rigidbody; [HideInInspector] public HandPhysics hand;
public LayerMask collisionMask;
Collider[] colliders;
public FingerColliders fingerColliders;
[System.Serializable] public class FingerColliders { [Tooltip("Starting at tip and going down. Max 2.")] public Transform[] thumbColliders = new Transform[1]; [Tooltip("Starting at tip and going down. Max 3.")] public Transform[] indexColliders = new Transform[2]; [Tooltip("Starting at tip and going down. Max 3.")] public Transform[] middleColliders = new Transform[2]; [Tooltip("Starting at tip and going down. Max 3.")] public Transform[] ringColliders = new Transform[2]; [Tooltip("Starting at tip and going down. Max 3.")] public Transform[] pinkyColliders = new Transform[2];
public Transform[] this[int finger] { get { switch (finger) { case 0: return thumbColliders; case 1: return indexColliders; case 2: return middleColliders; case 3: return ringColliders; case 4: return pinkyColliders; default: return null; } } set { switch (finger) { case 0: thumbColliders = value; break; case 1: indexColliders = value; break; case 2: middleColliders = value; break; case 3: ringColliders = value; break; case 4: pinkyColliders = value; break; } } }
}
private static PhysicMaterial physicMaterial_lowfriction; private static PhysicMaterial physicMaterial_highfriction;
private void Awake() { rigidbody = GetComponent<Rigidbody>(); rigidbody.maxAngularVelocity = 50; }
private void Start() { colliders = GetComponentsInChildren<Collider>();
if (physicMaterial_lowfriction == null) { physicMaterial_lowfriction = new PhysicMaterial("hand_lowFriction"); physicMaterial_lowfriction.dynamicFriction = 0; physicMaterial_lowfriction.staticFriction = 0; physicMaterial_lowfriction.bounciness = 0; physicMaterial_lowfriction.bounceCombine = PhysicMaterialCombine.Minimum; physicMaterial_lowfriction.frictionCombine = PhysicMaterialCombine.Minimum; }
if (physicMaterial_highfriction == null) { physicMaterial_highfriction = new PhysicMaterial("hand_highFriction"); physicMaterial_highfriction.dynamicFriction = 1f; physicMaterial_highfriction.staticFriction = 1f; physicMaterial_highfriction.bounciness = 0; physicMaterial_highfriction.bounceCombine = PhysicMaterialCombine.Minimum; physicMaterial_highfriction.frictionCombine = PhysicMaterialCombine.Average; }
SetPhysicMaterial(physicMaterial_lowfriction);
scale = SteamVR_Utils.GetLossyScale(hand.transform); }
void SetPhysicMaterial(PhysicMaterial mat) { if (colliders == null) colliders = GetComponentsInChildren<Collider>(); for (int i = 0; i < colliders.Length; i++) { colliders[i].sharedMaterial = mat; } }
float scale;
public void SetCollisionDetectionEnabled(bool value) { rigidbody.detectCollisions = value; }
public void MoveTo(Vector3 position, Quaternion rotation) { targetPosition = position; targetRotation = rotation; //rigidbody.MovePosition(position);
//rigidbody.MoveRotation(rotation);
ExecuteFixedUpdate(); }
public void TeleportTo(Vector3 position, Quaternion rotation) { targetPosition = position; targetRotation = rotation;
MoveTo(position, rotation);
rigidbody.position = position;
if (rotation.x != 0 || rotation.y != 0 || rotation.z != 0 || rotation.w != 0) rigidbody.rotation = rotation;
//also update transform in case physics is disabled
transform.position = position; transform.rotation = rotation; }
public void Reset() { TeleportTo(targetPosition, targetRotation); }
public void SetCenterPoint(Vector3 newCenter) { center = newCenter; }
private Vector3 center;
private Vector3 targetPosition = Vector3.zero; private Quaternion targetRotation = Quaternion.identity;
protected const float MaxVelocityChange = 10f; protected const float VelocityMagic = 6000f; protected const float AngularVelocityMagic = 50f; protected const float MaxAngularVelocityChange = 20f;
public bool collidersInRadius; protected void ExecuteFixedUpdate() { collidersInRadius = Physics.CheckSphere(center, 0.2f, collisionMask); if (collidersInRadius == false) { //keep updating velocity, just in case. Otherwise you get jitter
rigidbody.velocity = Vector3.zero; rigidbody.angularVelocity = Vector3.zero; /* rigidbody.velocity = (targetPosition - rigidbody.position) / Time.fixedDeltaTime; float angle; Vector3 axis; (targetRotation * Quaternion.Inverse(rigidbody.rotation)).ToAngleAxis(out angle, out axis); rigidbody.angularVelocity = axis.normalized * angle / Time.fixedDeltaTime; */
rigidbody.MovePosition(targetPosition); rigidbody.MoveRotation(targetRotation); } else { Vector3 velocityTarget, angularTarget; bool success = GetTargetVelocities(out velocityTarget, out angularTarget); if (success) { float maxAngularVelocityChange = MaxAngularVelocityChange * scale; float maxVelocityChange = MaxVelocityChange * scale;
rigidbody.velocity = Vector3.MoveTowards(rigidbody.velocity, velocityTarget, maxVelocityChange); rigidbody.angularVelocity = Vector3.MoveTowards(rigidbody.angularVelocity, angularTarget, maxAngularVelocityChange); } } }
protected bool GetTargetVelocities(out Vector3 velocityTarget, out Vector3 angularTarget) { bool realNumbers = false;
float velocityMagic = VelocityMagic; float angularVelocityMagic = AngularVelocityMagic;
Vector3 positionDelta = (targetPosition - rigidbody.position); velocityTarget = (positionDelta * velocityMagic * Time.deltaTime);
if (float.IsNaN(velocityTarget.x) == false && float.IsInfinity(velocityTarget.x) == false) { realNumbers = true; } else velocityTarget = Vector3.zero;
Quaternion rotationDelta = targetRotation * Quaternion.Inverse(rigidbody.rotation);
float angle; Vector3 axis; rotationDelta.ToAngleAxis(out angle, out axis);
if (angle > 180) angle -= 360;
if (angle != 0 && float.IsNaN(axis.x) == false && float.IsInfinity(axis.x) == false) { angularTarget = angle * axis * angularVelocityMagic * Time.deltaTime;
realNumbers &= true; } else angularTarget = Vector3.zero;
return realNumbers; }
const float minCollisionEnergy = 0.1f; const float maxCollisionEnergy = 1.0f;
const float minCollisionHapticsTime = 0.2f; private float lastCollisionHapticsTime; private void OnCollisionEnter(Collision collision) { bool touchingDynamic = false; if (collision.rigidbody != null) { if (collision.rigidbody.isKinematic == false) touchingDynamic = true; }
// low friction if touching static object, high friction if touching dynamic
SetPhysicMaterial(touchingDynamic ? physicMaterial_highfriction : physicMaterial_lowfriction);
float energy = collision.relativeVelocity.magnitude;
if(energy > minCollisionEnergy && Time.time - lastCollisionHapticsTime > minCollisionHapticsTime) { lastCollisionHapticsTime = Time.time;
float intensity = Util.RemapNumber(energy, minCollisionEnergy, maxCollisionEnergy, 0.3f, 1.0f); float length = Util.RemapNumber(energy, minCollisionEnergy, maxCollisionEnergy, 0.0f, 0.06f);
hand.hand.TriggerHapticPulse(length, 100, intensity); } }
}}
|