//------------------------------------------------- private bool PhysicsDetach( IF_VR_Steam_Hand hand ) { int i = holdingHands.IndexOf( hand ); if ( i != -1 ) { // Detach this object from the hand holdingHands[i].DetachObject( this.gameObject, false ); // Allow the hand to do other things holdingHands[i].HoverUnlock( null ); // Delete any existing joints from the hand if ( attachMode == AttachMode.FixedJoint ) { Destroy( holdingHands[i].GetComponent<FixedJoint>() ); } IF_VR_Steam_Util.FastRemove( holdingHands, i ); IF_VR_Steam_Util.FastRemove( holdingBodies, i ); IF_VR_Steam_Util.FastRemove( holdingPoints, i ); return true; } return false; }
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 = IF_VR_Steam_Util.RemapNumber(energy, minCollisionEnergy, maxCollisionEnergy, 0.3f, 1.0f); float length = IF_VR_Steam_Util.RemapNumber(energy, minCollisionEnergy, maxCollisionEnergy, 0.0f, 0.06f); hand.hand.TriggerHapticPulse(length, 100, intensity); } }
//------------------------------------------------- void Update() { float value = linearMapping.value; //No need to set the blend if our value hasn't changed. if (value != lastValue) { float blendValue = IF_VR_Steam_Util.RemapNumberClamped(value, 0f, 1f, 1f, 100f); skinnedMesh.SetBlendShapeWeight(0, blendValue); } lastValue = value; }
//------------------------------------------------- public void Play() { if (thisAudioSource != null && thisAudioSource.isActiveAndEnabled && !IF_VR_Steam_Util.IsNullOrEmpty(waveFiles)) { //randomly apply a volume between the volume min max thisAudioSource.volume = Random.Range(volMin, volMax); //randomly apply a pitch between the pitch min max thisAudioSource.pitch = Random.Range(pitchMin, pitchMax); // play the sound thisAudioSource.PlayOneShot(waveFiles[Random.Range(0, waveFiles.Length)]); } }
//------------------------------------------------- private void PhysicsAttach( IF_VR_Steam_Hand hand, IF_VR_Steam_GrabTypes startingGrabType ) { PhysicsDetach( hand ); Rigidbody holdingBody = null; Vector3 holdingPoint = Vector3.zero; // The hand should grab onto the nearest rigid body float closestDistance = float.MaxValue; for ( int i = 0; i < rigidBodies.Count; i++ ) { float distance = Vector3.Distance( rigidBodies[i].worldCenterOfMass, hand.transform.position ); if ( distance < closestDistance ) { holdingBody = rigidBodies[i]; closestDistance = distance; } } // Couldn't grab onto a body if ( holdingBody == null ) return; // Create a fixed joint from the hand to the holding body if ( attachMode == AttachMode.FixedJoint ) { Rigidbody handRigidbody = IF_VR_Steam_Util.FindOrAddComponent<Rigidbody>( hand.gameObject ); handRigidbody.isKinematic = true; FixedJoint handJoint = hand.gameObject.AddComponent<FixedJoint>(); handJoint.connectedBody = holdingBody; } // Don't let the hand interact with other things while it's holding us hand.HoverLock( null ); // Affix this point Vector3 offset = hand.transform.position - holdingBody.worldCenterOfMass; offset = Mathf.Min( offset.magnitude, 1.0f ) * offset.normalized; holdingPoint = holdingBody.transform.InverseTransformPoint( holdingBody.worldCenterOfMass + offset ); hand.AttachObject( this.gameObject, startingGrabType, attachmentFlags ); // Update holding list holdingHands.Add( hand ); holdingBodies.Add( holdingBody ); holdingPoints.Add( holdingPoint ); }
//------------------------------------------------- private IEnumerator HapticPulses(IF_VR_Steam_Hand hand, float flMagnitude, int nCount) { if (hand != null) { int nRangeMax = (int)IF_VR_Steam_Util.RemapNumberClamped(flMagnitude, 0.0f, 1.0f, 100.0f, 900.0f); nCount = Mathf.Clamp(nCount, 1, 10); //float hapticDuration = nRangeMax * nCount; //hand.TriggerHapticPulse(hapticDuration, nRangeMax, flMagnitude); for (ushort i = 0; i < nCount; ++i) { ushort duration = (ushort)Random.Range(100, nRangeMax); hand.TriggerHapticPulse(duration); yield return(new WaitForSeconds(.01f)); } } }
//------------------------------------------------- // Computes the angle to rotate the game object based on the change in the transform //------------------------------------------------- private void ComputeAngle(IF_VR_Steam_Hand hand) { Vector3 toHandProjected = ComputeToTransformProjected(hand.hoverSphereTransform); if (!toHandProjected.Equals(lastHandProjected)) { float absAngleDelta = Vector3.Angle(lastHandProjected, toHandProjected); if (absAngleDelta > 0.0f) { if (frozen) { float frozenSqDist = (hand.hoverSphereTransform.position - frozenHandWorldPos).sqrMagnitude; if (frozenSqDist > frozenSqDistanceMinMaxThreshold.x) { outAngle = frozenAngle + Random.Range(-1.0f, 1.0f); float magnitude = IF_VR_Steam_Util.RemapNumberClamped(frozenSqDist, frozenSqDistanceMinMaxThreshold.x, frozenSqDistanceMinMaxThreshold.y, 0.0f, 1.0f); if (magnitude > 0) { StartCoroutine(HapticPulses(hand, magnitude, 10)); } else { StartCoroutine(HapticPulses(hand, 0.5f, 10)); } if (frozenSqDist >= frozenSqDistanceMinMaxThreshold.y) { onFrozenDistanceThreshold.Invoke(); } } } else { Vector3 cross = Vector3.Cross(lastHandProjected, toHandProjected).normalized; float dot = Vector3.Dot(worldPlaneNormal, cross); float signedAngleDelta = absAngleDelta; if (dot < 0.0f) { signedAngleDelta = -signedAngleDelta; } if (limited) { float angleTmp = Mathf.Clamp(outAngle + signedAngleDelta, minAngle, maxAngle); if (outAngle == minAngle) { if (angleTmp > minAngle && absAngleDelta < minMaxAngularThreshold) { outAngle = angleTmp; lastHandProjected = toHandProjected; } } else if (outAngle == maxAngle) { if (angleTmp < maxAngle && absAngleDelta < minMaxAngularThreshold) { outAngle = angleTmp; lastHandProjected = toHandProjected; } } else if (angleTmp == minAngle) { outAngle = angleTmp; lastHandProjected = toHandProjected; onMinAngle.Invoke(); if (freezeOnMin) { Freeze(hand); } } else if (angleTmp == maxAngle) { outAngle = angleTmp; lastHandProjected = toHandProjected; onMaxAngle.Invoke(); if (freezeOnMax) { Freeze(hand); } } else { outAngle = angleTmp; lastHandProjected = toHandProjected; } } else { outAngle += signedAngleDelta; lastHandProjected = toHandProjected; } } } } }