//------------------------------------------------- private void ShowPointer(NVRHand newPointerHand, NVRHand oldPointerHand) { if (!visible) { pointedAtTeleportMarker = null; pointerShowStartTime = Time.time; visible = true; meshFading = true; teleportPointerObject.SetActive(false); teleportArc.Show(); foreach (TeleportMarkerBase teleportMarker in teleportMarkers) { if (teleportMarker.markerActive && teleportMarker.ShouldActivate(player.feetPositionGuess)) { teleportMarker.gameObject.SetActive(true); teleportMarker.Highlight(false); } } //NVRReplace//startingFeetOffset = player.trackingOriginTransform.position - player.feetPositionGuess; startingFeetOffset = player.transform.position - player.feetPositionGuess; movedFeetFarEnough = false; if (onDeactivateObjectTransform.gameObject.activeSelf) { onDeactivateObjectTransform.gameObject.SetActive(false); } onActivateObjectTransform.gameObject.SetActive(true); loopingAudioSource.clip = pointerLoopSound; loopingAudioSource.loop = true; loopingAudioSource.Play(); loopingAudioSource.volume = 0.0f; } if (oldPointerHand) { //NVRReplace Debug.LogWarning("Skipping ShouldOverrideHoverLock() on Teleportation - oldPointerHand"); /* * if ( ShouldOverrideHoverLock() ) * { * //Restore the original hovering interactable on the hand * if ( originalHoverLockState == true ) * { * oldPointerHand.HoverLock( originalHoveringInteractable ); * } * else * { * oldPointerHand.HoverUnlock( null ); * } * } */ } pointerHand = newPointerHand; if (visible && oldPointerHand != pointerHand) { PlayAudioClip(pointerAudioSource, pointerStartSound); } if (pointerHand) { pointerStartTransform = GetPointerStartTransform(pointerHand); //NVRReplace //if ( pointerHand.currentAttachedObject != null ) if (pointerHand.CurrentlyInteracting != null) { //NVRReplace//allowTeleportWhileAttached = pointerHand.currentAttachedObject.GetComponent<AllowTeleportWhileAttachedToHand>(); allowTeleportWhileAttached = pointerHand.CurrentlyInteracting.GetComponent <AllowTeleportWhileAttachedToHand>(); } //NVRReplace //Keep track of any existing hovering interactable on the hand /* * originalHoverLockState = pointerHand.hoverLocked; * originalHoveringInteractable = pointerHand.hoveringInteractable; * * if ( ShouldOverrideHoverLock() ) * { * pointerHand.HoverLock( null ); * } */ pointerAudioSource.transform.SetParent(pointerStartTransform); pointerAudioSource.transform.localPosition = Vector3.zero; loopingAudioSource.transform.SetParent(pointerStartTransform); loopingAudioSource.transform.localPosition = Vector3.zero; } }
//------------------------------------------------- private void UpdatePointer() { Vector3 pointerStart = pointerStartTransform.position; Vector3 pointerEnd; Vector3 pointerDir = pointerStartTransform.forward; bool hitSomething = false; bool showPlayAreaPreview = false; //Vector3 playerFeetOffset = player.trackingOriginTransform.position - player.feetPositionGuess; Vector3 playerFeetOffset = player.transform.position - player.feetPositionGuess; Vector3 arcVelocity = pointerDir * arcDistance; TeleportMarkerBase hitTeleportMarker = null; //Check pointer angle float dotUp = Vector3.Dot(pointerDir, Vector3.up); //NVRReplace//float dotForward = Vector3.Dot( pointerDir, player.hmdTransform.forward ); float dotForward = Vector3.Dot(pointerDir, player.Head.transform.forward); bool pointerAtBadAngle = false; if ((dotForward > 0 && dotUp > 0.75f) || (dotForward < 0.0f && dotUp > 0.5f)) { pointerAtBadAngle = true; } //Trace to see if the pointer hit anything RaycastHit hitInfo; teleportArc.SetArcData(pointerStart, arcVelocity, true, pointerAtBadAngle); if (teleportArc.DrawArc(out hitInfo)) { hitSomething = true; hitTeleportMarker = hitInfo.collider.GetComponentInParent <TeleportMarkerBase>(); } if (pointerAtBadAngle) { hitTeleportMarker = null; } HighlightSelected(hitTeleportMarker); if (hitTeleportMarker != null) //Hit a teleport marker { if (hitTeleportMarker.locked) { teleportArc.SetColor(pointerLockedColor); #if (UNITY_5_4) pointerLineRenderer.SetColors(pointerLockedColor, pointerLockedColor); #else pointerLineRenderer.startColor = pointerLockedColor; pointerLineRenderer.endColor = pointerLockedColor; #endif destinationReticleTransform.gameObject.SetActive(false); } else { teleportArc.SetColor(pointerValidColor); #if (UNITY_5_4) pointerLineRenderer.SetColors(pointerValidColor, pointerValidColor); #else pointerLineRenderer.startColor = pointerValidColor; pointerLineRenderer.endColor = pointerValidColor; #endif destinationReticleTransform.gameObject.SetActive(hitTeleportMarker.showReticle); } offsetReticleTransform.gameObject.SetActive(true); invalidReticleTransform.gameObject.SetActive(false); pointedAtTeleportMarker = hitTeleportMarker; pointedAtPosition = hitInfo.point; if (showPlayAreaMarker) { //Show the play area marker if this is a teleport area VHONTeleportArea teleportArea = pointedAtTeleportMarker as VHONTeleportArea; if (teleportArea != null && !teleportArea.locked && playAreaPreviewTransform != null) { Vector3 offsetToUse = playerFeetOffset; //Adjust the actual offset to prevent the play area marker from moving too much if (!movedFeetFarEnough) { float distanceFromStartingOffset = Vector3.Distance(playerFeetOffset, startingFeetOffset); if (distanceFromStartingOffset < 0.1f) { offsetToUse = startingFeetOffset; } else if (distanceFromStartingOffset < 0.4f) { offsetToUse = Vector3.Lerp(startingFeetOffset, playerFeetOffset, (distanceFromStartingOffset - 0.1f) / 0.3f); } else { movedFeetFarEnough = true; } } playAreaPreviewTransform.position = pointedAtPosition + offsetToUse; showPlayAreaPreview = true; } } pointerEnd = hitInfo.point; } else //Hit neither { destinationReticleTransform.gameObject.SetActive(false); offsetReticleTransform.gameObject.SetActive(false); teleportArc.SetColor(pointerInvalidColor); #if (UNITY_5_4) pointerLineRenderer.SetColors(pointerInvalidColor, pointerInvalidColor); #else pointerLineRenderer.startColor = pointerInvalidColor; pointerLineRenderer.endColor = pointerInvalidColor; #endif invalidReticleTransform.gameObject.SetActive(!pointerAtBadAngle); //Orient the invalid reticle to the normal of the trace hit point Vector3 normalToUse = hitInfo.normal; float angle = Vector3.Angle(hitInfo.normal, Vector3.up); if (angle < 15.0f) { normalToUse = Vector3.up; } invalidReticleTargetRotation = Quaternion.FromToRotation(Vector3.up, normalToUse); invalidReticleTransform.rotation = Quaternion.Slerp(invalidReticleTransform.rotation, invalidReticleTargetRotation, 0.1f); //Scale the invalid reticle based on the distance from the player //NVRReplace//float distanceFromPlayer = Vector3.Distance( hitInfo.point, player.hmdTransform.position ); float distanceFromPlayer = Vector3.Distance(hitInfo.point, player.Head.transform.position); float invalidReticleCurrentScale = Util.RemapNumberClamped(distanceFromPlayer, invalidReticleMinScaleDistance, invalidReticleMaxScaleDistance, invalidReticleMinScale, invalidReticleMaxScale); invalidReticleScale.x = invalidReticleCurrentScale; invalidReticleScale.y = invalidReticleCurrentScale; invalidReticleScale.z = invalidReticleCurrentScale; invalidReticleTransform.transform.localScale = invalidReticleScale; pointedAtTeleportMarker = null; if (hitSomething) { pointerEnd = hitInfo.point; } else { pointerEnd = teleportArc.GetArcPositionAtTime(teleportArc.arcDuration); } //Debug floor if (debugFloor) { floorDebugSphere.gameObject.SetActive(false); floorDebugLine.gameObject.SetActive(false); } } if (playAreaPreviewTransform != null) { playAreaPreviewTransform.gameObject.SetActive(showPlayAreaPreview); } if (!showOffsetReticle) { offsetReticleTransform.gameObject.SetActive(false); } destinationReticleTransform.position = pointedAtPosition; invalidReticleTransform.position = pointerEnd; onActivateObjectTransform.position = pointerEnd; onDeactivateObjectTransform.position = pointerEnd; offsetReticleTransform.position = pointerEnd - playerFeetOffset; reticleAudioSource.transform.position = pointedAtPosition; pointerLineRenderer.SetPosition(0, pointerStart); pointerLineRenderer.SetPosition(1, pointerEnd); }
void TeleportDone(TeleportMarkerBase teleportMarkerBase) { onTeleportedHere.Invoke(); }
private void UpdatePointer() { if (Controller.GetAxis().y - trackPadStart.y > .2) { teleport = true; } else { teleport = false; } Vector3 pointerStart = trackedObj.transform.position; Vector3 pointerEnd; Vector3 pointerDir = trackedObj.transform.forward; bool hitSomething = false; Vector3 playerFeetOffset = playerTrackingOriginTransform.position - feetPositionGuess; Vector3 arcVelocity = pointerDir * arcDistance; TeleportMarkerBase hitTeleportMarker = null; //Check pointer angle float dotUp = Vector3.Dot(pointerDir, Vector3.up); float dotForward = Vector3.Dot(pointerDir, playerHMD.transform.forward); bool pointerAtBadAngle = false; if ((dotForward > 0 && dotUp > 0.75f) || (dotForward < 0.0f && dotUp > 0.5f)) { pointerAtBadAngle = true; } //Trace to see if the pointer hit anything RaycastHit hitInfo; teleportArc.SetArcData(pointerStart, arcVelocity, true, pointerAtBadAngle); if (teleportArc.DrawArc(out hitInfo)) { hitSomething = true; hitTeleportMarker = hitInfo.collider.GetComponentInParent <TeleportMarkerBase>(); } if (pointerAtBadAngle) { hitTeleportMarker = null; } if (teleport) { teleportArc.SetColor(pointerTeleportColor); teleportPointMaterial.SetColor("_TintColor", pointerTeleportColor); } else { teleportArc.SetColor(pointerValidColor); teleportPointMaterial.SetColor("_TintColor", pointerValidColor); } ///////////////////////// //////////////////////// /////////////// //////////// ///////// /////// /////////////////LOOK AT teleportPointerObject for line color invalidReticleTransform.gameObject.SetActive(!pointerAtBadAngle); //Orient the invalid reticle to the normal of the trace hit point Vector3 normalToUse = hitInfo.normal; float angle = Vector3.Angle(hitInfo.normal, Vector3.up); if (angle < 15.0f) { normalToUse = Vector3.up; } float distanceFromPlayer = Vector3.Distance(hitInfo.point, playerHMD.transform.position); if (hitSomething) { pointerEnd = hitInfo.point; } else { pointerEnd = teleportArc.GetArcPositionAtTime(teleportArc.arcDuration); } invalidReticleTransform.position = pointerEnd; //pointerLineRenderer.SetPosition(0, pointerStart); // pointerLineRenderer.SetPosition(1, pointerEnd); }
public void Teleported(TeleportMarkerBase teleportMarkerBase) { // This method needs to be called whenever a teleport was completed. For this some changes need to be made to the Steam VR code :-( // The changes are described in the Readme file of the Github repo. // Debug.LogWarning("Teleported!"); if (player != null) { // Assign the appropriate tag for raycasting: string tagForRaycast; if (teleportingShape == TeleportingShape.ShapeRings) { tagForRaycast = ringTag; } else { tagForRaycast = squareTag; } // Calculate the POV for line of site origin Vector3 PointOfView = player.feetPositionGuess; PointOfView.y += player.eyeHeight; // Store the player's position Vector3 playerPosition = player.trackingOriginTransform.position; // Cycle to each of the raycast positions to determine if the teleport point needs to be positioned underneath it for (int i = 0; i < raycastPositions.Count; i++) { Vector3 currentPosition = playerPosition + raycastPositions[i]; Vector3 down = Vector3.down; // Get the teleportpoint associated with this raycastPosition (by index) TeleportPoint teleportPoint = teleportPoints[i]; RaycastHit hit; // Assume the teleportpoint needs to be parked unless all conditions are met (terrain angle low enough, raycast hits an object tagged "Terrain") bool parkTeleportSpot = true; if (Physics.Raycast(currentPosition, down, out hit, yOffsetRaycast * 4) && hit.transform.tag == tagForRaycast) { // Check for fixed Teleportpoints here // // TODO // move a teleportpoint to this position when it hits the terrain / floor if (teleportingShape == TeleportingShape.ShapeRings) { // step 1: check the angle, using code from http://thehiddensignal.com/unity-angle-of-sloped-ground-under-player/ Vector3 temp = Vector3.Cross(hit.normal, Vector3.down); Vector3 groundSlopeDir = Vector3.Cross(temp, hit.normal); float groundSlopeAngle = Vector3.Angle(hit.normal, Vector3.up); // step 2: if within maximum allowed angle then place teleport spot if (groundSlopeAngle < maximumTerrainAngle) { // The yOffsetTeleportPoints may be needed, for example if you use Microsplat with tessellation enabled. // Otherwise the teleportpoint may sink too far into the ground. teleportPoint.transform.position = new Vector3(hit.point.x, hit.point.y + yOffsetTeleportPoints, hit.point.z); parkTeleportSpot = false; } } else { // For squares we don't don the angle check. // The yOffsetTeleportPoints may be needed, for example if you use Microsplat with tessellation enabled. // Otherwise the teleportpoint may sink too far into the ground. teleportPoint.transform.position = new Vector3(hit.point.x, hit.point.y + yOffsetTeleportPoints, hit.point.z); parkTeleportSpot = false; } } if (lineOfSightPlacement && parkTeleportSpot == false) { // This is where we check if the teleport point we are going to place hides behind an obstacle. If so the park it instead. RaycastHit hitPOV; // Get a direction from the Player (eyes) to the teleport point to be placed: Vector3 direction = (teleportPoint.transform.position - PointOfView).normalized; // Cast a ray from the Player (eyes) to the teleport point and see if we hit something: if (Physics.Raycast(PointOfView, direction, out hitPOV, distance * 1, 5) && hitPOV.transform.tag != tagForRaycast) { // Looks like we hit something else than Floor or Terrain so park thsi teleport point instead parkTeleportSpot = true; } } if (checkProximity && parkTeleportSpot == false) { // Here we'll check if the teleport point to be placed is near any of the manually placed teleport points. // This can be an expensive operation however we're only doing it on each teleport action. If you want you can optimize it using the examples here: // https://forum.unity.com/threads/different-ways-to-find-distance.285226/ // We collected the manually placed teleport points in the Awake function and now we'll check each of them for proximity. // This can also become an expensive operation if a lot of teleport points have been placed in the level manually. foreach (TeleportMarkerBase tmb in teleportMarkers) { float distance = Vector3.Distance(tmb.transform.position, teleportPoint.transform.position); if (distance < proximity) { // Debug.Log("Skipping teleport point due to proximity of "+distance); parkTeleportSpot = true; } } } if (parkTeleportSpot) { // move teleport point [i] to parking spot which defaults to (0,0,0). Move it somewhere else if (0,0,0) is actually used in the scene. teleportPoint.transform.position = parkingSpot; } } } else { Debug.LogError("<b>TeleportPointsTerrain.Teleported():</b> player == null"); } }