/// <summary> /// Coroutine for moving the actor to the right position /// </summary> /// <param name="rMotion"></param> /// <returns></returns> public virtual IEnumerator MoveToTargetInternal(IInteractableCore rInteractableCore) { bool lStoredWalkRunMotionEnabled = false; bool lStoredUseTransformPosition = false; bool lStoredUseTransformRotation = false; MotionController lMotionController = mMotionController; ActorController lActorController = lMotionController._ActorController; // Enable AC positioning lStoredUseTransformPosition = lActorController.UseTransformPosition; lActorController.UseTransformPosition = true; lStoredUseTransformRotation = lActorController.UseTransformRotation; lActorController.UseTransformRotation = true; // Enable our strafing motion MotionControllerMotion lWalkRunMotion = lMotionController.GetMotion(_WalkRunMotion, true); if (lWalkRunMotion != null) { lStoredWalkRunMotionEnabled = lWalkRunMotion.IsEnabled; lWalkRunMotion.IsEnabled = true; } Vector3 lTargetPosition = lActorController._Transform.position; if (rInteractableCore.ForcePosition) { if (rInteractableCore.TargetLocation != null) { lTargetPosition = rInteractableCore.TargetLocation.position; } else if (rInteractableCore.TargetDistance > 0f) { Vector3 lInteractablePosition = rInteractableCore.gameObject.transform.position; lInteractablePosition.y = lActorController._Transform.position.y; lTargetPosition = lInteractablePosition + ((lActorController._Transform.position - lInteractablePosition).normalized * rInteractableCore.TargetDistance); } } Vector3 lTargetForward = lActorController._Transform.forward; if (rInteractableCore.ForceRotation) { if (rInteractableCore.TargetLocation != null) { lTargetForward = rInteractableCore.TargetLocation.forward; } else { Vector3 lInteractablePosition = rInteractableCore.gameObject.transform.position; lInteractablePosition.y = lActorController._Transform.position.y; lTargetForward = (lInteractablePosition - lActorController._Transform.position).normalized; } } // Move to the target position and rotation Vector3 lDirection = lTargetPosition - lActorController._Transform.position; float lAngle = Vector3Ext.HorizontalAngleTo(lActorController._Transform.forward, lTargetForward); while (HorizontalDistance(lActorController._Transform.position, lTargetPosition) > 0.01f || Mathf.Abs(lAngle) > 0.1f) { float lDistance = Mathf.Min(lDirection.magnitude, _WalkSpeed * Time.deltaTime); lActorController._Transform.position = lActorController._Transform.position + (lDirection.normalized * lDistance); float lYaw = Mathf.Sign(lAngle) * Mathf.Min(Mathf.Abs(lAngle), _RotationSpeed * Time.deltaTime); lActorController._Transform.rotation = (lActorController._Transform.rotation * Quaternion.Euler(0f, lYaw, 0f)); yield return(new WaitForEndOfFrame()); lDirection = lTargetPosition - lActorController._Transform.position; lAngle = Vector3Ext.HorizontalAngleTo(lActorController._Transform.forward, lTargetForward); } // Activate BasicInteraction mActiveForm = rInteractableCore.Form; InteractableCore = rInteractableCore; lMotionController.ActivateMotion(this); // Give some final frames to get to the exact position yield return(new WaitForSeconds(0.2f)); // Reset the motion and movement options if (lWalkRunMotion != null) { lWalkRunMotion.IsEnabled = lStoredWalkRunMotionEnabled; } lActorController.UseTransformPosition = lStoredUseTransformPosition; lActorController.UseTransformRotation = lStoredUseTransformRotation; lMotionController.TargetNormalizedSpeed = 1f; }
/// <summary> /// Tests if this motion should be started. However, the motion /// isn't actually started. /// </summary> /// <returns></returns> public override bool TestActivate() { if (!mIsStartable) { return(false); } if (!mMotionController.IsGrounded) { return(false); } // Raycast if needed if (_IsInteractableRaycastEnabled) { bool lIsFound = false; RaycastHit lHitInfo; // Even though we have a raycast root, we really want to shoot from the camera. We'll check distance with the root later. Vector3 lStart = (mMotionController.CameraTransform != null ? mMotionController.CameraTransform.position : mMotionController._Transform.position); Vector3 lForward = (mMotionController.CameraTransform != null ? mMotionController.CameraTransform.forward : mMotionController._Transform.forward); if (RaycastExt.SafeRaycast(lStart, lForward, out lHitInfo, _InteractableDistance * 5f, _InteractableLayers, mMotionController._Transform)) { bool lIsValid = true; if (mRaycastRoot != null) { float lDistance = Vector3.Distance(lHitInfo.point, mRaycastRoot.position); if (lDistance > _InteractableDistance) { lIsValid = false; } } if (lIsValid) { IInteractableCore lCore = lHitInfo.collider.gameObject.GetComponent <IInteractableCore>(); if (lCore == null) { lCore = lHitInfo.collider.gameObject.GetComponentInParent <IInteractableCore>(); } if (!_IsInteractableCoreRequired && lCore == null) { lIsFound = true; Interactable = lHitInfo.collider.gameObject; } else { if (lCore == null) { lIsValid = false; } if (lIsValid && !lCore.IsEnabled) { lIsValid = false; } if (lIsValid && !lCore.TestActivator(mMotionController._Transform)) { lIsValid = false; } if (lIsValid && lCore.RaycastCollider != null && lHitInfo.collider != lCore.RaycastCollider) { lIsValid = false; } if (lIsValid) { lIsFound = true; InteractableCore = lCore; InteractableCore.StartFocus(); mActiveForm = lCore.Form; } } } } // Deselect any interactable if none is found if (!lIsFound && _IsInteractableRaycastEnabled) { Interactable = null; } } // Test if we're supposed to activate if (_ActionAlias.Length > 0 && mMotionController._InputSource != null) { if (mMotionController._InputSource.IsJustPressed(_ActionAlias)) { // Check if the interactable is going to prepare thier activator. If so, we // aren't going to activate here. The activator will trigger the activation. if (InteractableCore != null) { if (InteractableCore.ForcePosition || InteractableCore.ForceRotation) { mMotionController.StartCoroutine(MoveToTargetInternal(InteractableCore)); } else { return(true); } } // Since we're just dealing with a simple game object, activate else if (Interactable != null) { return(true); } } } return(false); }