Ejemplo n.º 1
0
        /// <summary>
        /// When we want to rotate based on the camera direction, we need to tweak the actor
        /// rotation AFTER we process the camera. Otherwise, we can get small stutters during camera rotation.
        ///
        /// This is the only way to keep them totally in sync. It also means we can't run any of our AC processing
        /// as the AC already ran. So, we do minimal work here
        /// </summary>
        /// <param name="rDeltaTime"></param>
        /// <param name="rUpdateCount"></param>
        /// <param name="rCamera"></param>
        private void OnCameraUpdated(float rDeltaTime, int rUpdateIndex, BaseCameraRig rCamera)
        {
            if (mMotionController._CameraTransform == null)
            {
                return;
            }

            float lToCameraAngle = Vector3Ext.HorizontalAngleTo(mMotionController._Transform.forward, mMotionController._CameraTransform.forward, mMotionController._Transform.up);

            if (!mLinkRotation && Mathf.Abs(lToCameraAngle) <= _RotationSpeed * rDeltaTime)
            {
                mLinkRotation = true;
            }

            if (!mLinkRotation)
            {
                float lRotationAngle = Mathf.Abs(lToCameraAngle);
                float lRotationSign  = Mathf.Sign(lToCameraAngle);
                lToCameraAngle = lRotationSign * Mathf.Min(_RotationSpeed * rDeltaTime, lRotationAngle);
            }

            Quaternion lRotation = Quaternion.AngleAxis(lToCameraAngle, Vector3.up);

            mActorController.Yaw = mActorController.Yaw * lRotation;
            mActorController._Transform.rotation = mActorController.Tilt * mActorController.Yaw;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Allows the motor to process after the camera and controller have completed
        /// </summary>
        public override void PostRigLateUpdate()
        {
            base.PostRigLateUpdate();

            // Determine if we rotate the anchor to match our rotation
            if (_RotateAnchor && Anchor != null)
            {
                if (_RotateAnchorAlias.Length == 0 || RigController.InputSource == null || RigController.InputSource.IsPressed(_RotateAnchorAlias))
                {
                    if (mCharacterController != null)
                    {
                        float lToCameraAngle = Vector3Ext.HorizontalAngleTo(Anchor.forward, RigController.Transform.forward, Anchor.up);

                        Quaternion lRotation = Quaternion.AngleAxis(lToCameraAngle, Vector3.up);
                        mCharacterController.Yaw = mCharacterController.Yaw * lRotation;
                        Anchor.rotation          = mCharacterController.Tilt * mCharacterController.Yaw;
                    }
                    else
                    {
                        float lToCameraAngle = Vector3Ext.HorizontalAngleTo(Anchor.forward, RigController.Transform.forward, Anchor.up);

                        Quaternion lRotation = Quaternion.AngleAxis(lToCameraAngle, Vector3.up);
                        Anchor.rotation = Anchor.rotation * lRotation;
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Allows the motor to process after the camera and controller have completed
        /// </summary>
        public override void PostRigLateUpdate()
        {
            base.PostRigLateUpdate();

            Transform lAnchorTransform = Anchor;

            // If the anchor updates its rotation based on the rig, we need to get the final position of the rig
            if (_IsActorMatchingRotation && (RigController.ActiveMotor == this))
            {
                RigController._Transform.position = lAnchorTransform.position + (lAnchorTransform.rotation * AnchorOffset) + (lAnchorTransform.rotation * _Offset);
                RigController._Transform.rotation = Quaternion.Euler(RigController._Transform.rotation.eulerAngles.x, lAnchorTransform.rotation.eulerAngles.y, 0f);
            }

            if (_RotateAnchor && lAnchorTransform != null)
            {
                bool lIsRotatingAnchor = _RotateAnchorAlias.Length == 0 || RigController.InputSource == null || RigController.InputSource.IsPressed(_RotateAnchorAlias);

                if (lIsRotatingAnchor || mWasRotatingAnchor)
                {
                    if (mCharacterController != null)
                    {
                        float lToCameraAngle = Vector3Ext.HorizontalAngleTo(lAnchorTransform.forward, RigController.Transform.forward, lAnchorTransform.up);

                        Quaternion lRotation = Quaternion.AngleAxis(lToCameraAngle, Vector3.up);
                        mCharacterController.Yaw  = mCharacterController.Yaw * lRotation;
                        lAnchorTransform.rotation = mCharacterController.Tilt * mCharacterController.Yaw;
                    }
                    else
                    {
                        float lToCameraAngle = Vector3Ext.HorizontalAngleTo(lAnchorTransform.forward, RigController.Transform.forward, lAnchorTransform.up);

                        Quaternion lRotation = Quaternion.AngleAxis(lToCameraAngle, Vector3.up);
                        lAnchorTransform.rotation = lAnchorTransform.rotation * lRotation;
                    }

                    mAnchorLastRotation = lAnchorTransform.rotation;

                    // Since we are no longer rotating, we need to clear our out values
                    if (!lIsRotatingAnchor)
                    {
                        _Euler.y     = LocalYaw;
                        _Euler.x     = LocalPitch;
                        _EulerTarget = _Euler;

                        mViewVelocityY = 0f;
                        mViewVelocityX = 0f;

                        mWasRotatingAnchor = false;
                    }
                }
            }
            else
            {
                mWasRotatingAnchor = false;
            }

            //Debug.Log("Char Yaw:" + RigController.Anchor.rotation.eulerAngles.y.ToString("f5") + " Anchor Yaw:" + Anchor.rotation.eulerAngles.y.ToString("f5") + " Cam Yaw:" + RigController._Transform.eulerAngles.y.ToString("f5"));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Look at the incoming message to determine if it means we should react
        /// </summary>
        /// <param name="rMessage"></param>
        public override void OnMessageReceived(IMessage rMessage)
        {
            if (rMessage == null)
            {
                return;
            }
            if (rMessage.IsHandled)
            {
                return;
            }
            if (mActorController.State.Stance != EnumControllerStance.TRAVERSAL)
            {
                return;
            }

            if (rMessage is CombatMessage)
            {
                CombatMessage lCombatMessage = rMessage as CombatMessage;

                // Attack messages
                if (lCombatMessage.Attacker == mMotionController.gameObject)
                {
                }
                // Defender messages
                else if (lCombatMessage.Defender == mMotionController.gameObject)
                {
                    if (rMessage.ID == CombatMessage.MSG_DEFENDER_DAMAGED)
                    {
                        if (!mIsActive)
                        {
                            Vector3 lLocalPosition  = mMotionController._Transform.InverseTransformPoint(lCombatMessage.HitPoint);
                            Vector3 lLocalDirection = (lLocalPosition - Vector3.zero).normalized;
                            float   lAttackAngle    = Vector3Ext.HorizontalAngleTo(Vector3.forward, lLocalDirection, Vector3.up);

                            mMotionController.ActivateMotion(this, (int)lAttackAngle);
                        }
                        else
                        {
                            mMotionController.SetAnimatorMotionPhase(mMotionLayer._AnimatorLayerIndex, PHASE_START, Parameter, true);
                        }

                        rMessage.IsHandled = true;
                    }
                }
            }
            else if (rMessage is DamageMessage)
            {
                if (rMessage.ID == CombatMessage.MSG_DEFENDER_DAMAGED)
                {
                    mMotionController.ActivateMotion(this, 0);
                    rMessage.IsHandled = true;
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Rotate to the specified target's position over time
        /// </summary>
        /// <param name="rTarget">Transform we are rotating to</param>
        /// <param name="rSpeed">Degrees per second to rotate</param>
        /// <param name="rDeltaTime">Current delta time</param>
        /// <param name="rRotation">Resulting delta rotation needed to get to the target</param>
        protected void RotateToTarget(Transform rTarget, float rSpeed, float rDeltaTime, ref Quaternion rRotation)
        {
            Vector3 lNewPosition = mMotionController._Transform.position + (mMotionController._Transform.rotation * mMotionController.RootMotionMovement);
            Vector3 lToTarget    = rTarget.position - lNewPosition;

            float lSpeed = (rSpeed > 0f ? rSpeed : _ToTargetRotationSpeed);

            float lToAnchorAngle = Vector3Ext.HorizontalAngleTo(mMotionController._Transform.forward, lToTarget.normalized, mMotionController._Transform.up);

            lToAnchorAngle = Mathf.Sign(lToAnchorAngle) * Mathf.Min(lSpeed * rDeltaTime, Mathf.Abs(lToAnchorAngle));

            rRotation = Quaternion.AngleAxis(lToAnchorAngle, Vector3.up);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// When we want to rotate based on the camera direction, we need to tweak the actor
        /// rotation AFTER we process the camera. Otherwise, we can get small stutters during camera rotation.
        ///
        /// This is the only way to keep them totally in sync. It also means we can't run any of our AC processing
        /// as the AC already ran. So, we do minimal work here
        /// </summary>
        /// <param name="rDeltaTime"></param>
        /// <param name="rUpdateCount"></param>
        /// <param name="rCamera"></param>
        private void OnCameraUpdated(float rDeltaTime, int rUpdateCount, BaseCameraRig rCamera)
        {
            if (mMotionController._CameraTransform == null)
            {
                return;
            }

            float lToCameraAngle = Vector3Ext.HorizontalAngleTo(mMotionController._Transform.forward, mMotionController._CameraTransform.forward, mMotionController._Transform.up);
            float lRotationAngle = Mathf.Abs(lToCameraAngle);
            float lRotationSign  = Mathf.Sign(lToCameraAngle);

            if (!mLinkRotation && lRotationAngle <= (_RotationSpeed / 60f) * TimeManager.Relative60FPSDeltaTime)
            {
                mLinkRotation = true;
            }

            // Record the velocity for our idle pivoting
            if (lRotationAngle < 1f)
            {
                float lVelocitySign = Mathf.Sign(mYawVelocity);
                mYawVelocity = mYawVelocity - (lVelocitySign * rDeltaTime * 10f);

                if (Mathf.Sign(mYawVelocity) != lVelocitySign)
                {
                    mYawVelocity = 0f;
                }
            }
            else
            {
                mYawVelocity = lRotationSign * 12f;
            }

            // If we're not linked, rotate smoothly
            if (!mLinkRotation)
            {
                lToCameraAngle = lRotationSign * Mathf.Min((_RotationSpeed / 60f) * TimeManager.Relative60FPSDeltaTime, lRotationAngle);
            }

            Quaternion lRotation = Quaternion.AngleAxis(lToCameraAngle, Vector3.up);

            mActorController.Yaw = mActorController.Yaw * lRotation;
            mActorController._Transform.rotation = mActorController.Tilt * mActorController.Yaw;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Rotates the body to point towards the cross hairs
        /// </summary>
        protected void RotateChestToTargetForward(Vector3 rTarget, float rWeight)
        {
            if (rWeight == 0f)
            {
                return;
            }

            float lHAngle = 0f;
            float lVAngle = 0f;

            Transform lBody   = mMotionController._Transform;
            Transform lCamera = mMotionController._CameraTransform;
            Transform lSpine  = mMotionController.Animator.GetBoneTransform(HumanBodyBones.Spine);
            Transform lChest  = mMotionController.Animator.GetBoneTransform(HumanBodyBones.Chest);

            // The target direction helps determine how we'll rotate the arm
            Vector3 lTargetDirection = (lCamera != null ? lCamera.forward : rTarget);

            lHAngle = _HorizontalAimAngle * rWeight;
            lVAngle = (_VerticalAimAngle + Vector3Ext.HorizontalAngleTo(lBody.forward, lTargetDirection, lBody.right)) * rWeight;
            lVAngle = Mathf.Clamp(lVAngle, -65f, 65f);

            if (lSpine != null && lChest != null)
            {
                lHAngle = lHAngle * 0.5f;
            }
            if (lSpine != null && lChest != null)
            {
                lVAngle = lVAngle * 0.5f;
            }

            if (lSpine != null)
            {
                lSpine.rotation = Quaternion.AngleAxis(lHAngle, lBody.up) * Quaternion.AngleAxis(lVAngle, lBody.right) * lSpine.rotation;
            }

            if (lChest != null)
            {
                lChest.rotation = Quaternion.AngleAxis(lHAngle, lBody.up) * Quaternion.AngleAxis(lVAngle, lBody.right) * lChest.rotation;
            }
        }
Ejemplo n.º 8
0
        /// <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;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Grabs the euler changes that happen this frame.
        /// </summary>
        /// <param name="rAnchorYaw">Anchor yaw that should be added</param>
        /// <returns></returns>
        public virtual Vector3 GetFrameEuler(bool rUseYawLimits, bool rUsePitchLimits = true)
        {
            Vector3 lFrameEuler = Vector3.zero;

            // If the camera was moved externally, we need to recalculate the last focus position
            if (RigController.LastPosition != RigController._Transform.position)
            {
                mFocusLastPosition = GetFocusPosition(RigController._Transform.rotation);
            }

            // Now we can grab the movement
            if (mTarget != null)
            {
                mTargetForward = (mTarget.position - mRigTransform.Position).normalized;
            }

            if (mTargetForward.sqrMagnitude > 0f)
            {
                Quaternion lTargetRotation = Quaternion.LookRotation(mTargetForward, Anchor.up);

                Quaternion lLocalRotation       = Quaternion.Inverse(Anchor.rotation) * RigController._Transform.rotation;
                Quaternion lLocalTargetRotation = Quaternion.Inverse(Anchor.rotation) * lTargetRotation;

                float lDeltaYaw = lLocalTargetRotation.eulerAngles.y - lLocalRotation.eulerAngles.y;
                if (lDeltaYaw > 180f)
                {
                    lDeltaYaw = lDeltaYaw - 360f;
                }
                else if (lDeltaYaw < -180f)
                {
                    lDeltaYaw = lDeltaYaw + 360f;
                }

                float lDeltaPitch = lLocalTargetRotation.eulerAngles.x - lLocalRotation.eulerAngles.x;
                if (lDeltaPitch > 180f)
                {
                    lDeltaPitch = lDeltaPitch - 360f;
                }
                else if (lDeltaPitch < -180f)
                {
                    lDeltaPitch = lDeltaPitch + 360f;
                }

                if (mTargetYawSpeed <= 0f)
                {
                    lFrameEuler.y = lDeltaYaw;
                }
                else
                {
                    lFrameEuler.y = Mathf.Sign(lDeltaYaw) * Mathf.Min(mTargetYawSpeed * Time.deltaTime, Mathf.Abs(lDeltaYaw));
                }

                if (mTargetPitchSpeed <= 0f)
                {
                    lFrameEuler.x = lDeltaPitch;
                }
                else
                {
                    lFrameEuler.x = Mathf.Sign(lDeltaPitch) * Mathf.Min(mTargetPitchSpeed * Time.deltaTime, Mathf.Abs(lDeltaPitch));
                }

                if (Mathf.Abs(lFrameEuler.y) < EPSILON && Mathf.Abs(lFrameEuler.x) < EPSILON)
                {
                    _Euler.y     = LocalYaw;
                    _Euler.x     = LocalPitch;
                    _EulerTarget = _Euler;

                    if (mAutoClearTarget)
                    {
                        mTargetForward = Vector3.zero;
                    }
                }
            }
            else if (mTargetYaw < float.MaxValue || mTargetPitch < float.MaxValue)
            {
                if (mTargetYaw < float.MaxValue)
                {
                    float lDeltaYaw = mTargetYaw - LocalYaw;

                    if (mTargetYawSpeed <= 0f)
                    {
                        lFrameEuler.y = lDeltaYaw;
                    }
                    else
                    {
                        lFrameEuler.y = Mathf.Sign(lDeltaYaw) * Mathf.Min(mTargetYawSpeed * Time.deltaTime, Mathf.Abs(lDeltaYaw));
                    }

                    // TRT 04/09/2017 - Added to stop trying to reach the target when the character is rotating
                    Transform lAnchorTransform    = Anchor;
                    float     lAnchorRootYawDelta = Vector3Ext.HorizontalAngleTo(mAnchorLastRotation.Forward(), lAnchorTransform.forward, lAnchorTransform.up);
                    if (Mathf.Abs(lFrameEuler.y) - Mathf.Abs(lAnchorRootYawDelta * 2f) < EPSILON)
                    {
                        _Euler.y       = mTargetYaw;
                        _EulerTarget.y = mTargetYaw;

                        //if (mAutoClearTarget) { mTargetYaw = float.MaxValue; }
                    }

                    if (mAutoClearTarget && Mathf.Abs(lDeltaYaw) < EPSILON)
                    {
                        mTargetYaw = float.MaxValue;
                    }
                }

                if (mTargetPitch < float.MaxValue)
                {
                    float lDeltaPitch = mTargetPitch - LocalPitch;

                    if (mTargetPitchSpeed <= 0f)
                    {
                        lFrameEuler.x = lDeltaPitch;
                    }
                    else
                    {
                        lFrameEuler.x = Mathf.Sign(lDeltaPitch) * Mathf.Min(mTargetPitchSpeed * Time.deltaTime, Mathf.Abs(lDeltaPitch));
                    }

                    if (Mathf.Abs(lFrameEuler.x) < EPSILON)
                    {
                        _Euler.x       = mTargetPitch;
                        _EulerTarget.x = mTargetPitch;

                        //if (mAutoClearTarget) { mTargetPitch = float.MaxValue; }
                    }

                    if (mAutoClearTarget && Mathf.Abs(lDeltaPitch) < EPSILON)
                    {
                        mTargetPitch = float.MaxValue;
                    }
                }
            }
            else
            {
                IInputSource lInputSource = RigController.InputSource;

                if (lInputSource.IsViewingActivated)
                {
                    if (_IsYawEnabled && lFrameEuler.y == 0f)
                    {
                        lFrameEuler.y = lInputSource.ViewX * mDegreesYPer60FPSTick;
                    }
                    if (_IsPitchEnabled && lFrameEuler.x == 0f)
                    {
                        lFrameEuler.x = (RigController._InvertPitch || _InvertPitch ? -1f : 1f) * lInputSource.ViewY * mDegreesXPer60FPSTick;
                    }
                }

                // Grab the smoothed yaw
                _EulerTarget.y = (rUseYawLimits && (_MinYaw > -180f || _MaxYaw < 180f) ? Mathf.Clamp(_EulerTarget.y + lFrameEuler.y, _MinYaw, _MaxYaw) : _EulerTarget.y + lFrameEuler.y);
                lFrameEuler.y  = (_Smoothing <= 0f ? _EulerTarget.y : SmoothDamp(_Euler.y, _EulerTarget.y, _Smoothing * 0.001f, Time.deltaTime)) - _Euler.y;
                _Euler.y       = _Euler.y + lFrameEuler.y;

                // Grab the smoothed pitch
                _EulerTarget.x = (rUsePitchLimits && (_MinPitch > -180f || _MaxPitch < 180f) ? Mathf.Clamp(_EulerTarget.x + lFrameEuler.x, _MinPitch, _MaxPitch) : _EulerTarget.x + lFrameEuler.x);
                lFrameEuler.x  = (_Smoothing <= 0f ? _EulerTarget.x : SmoothDamp(_Euler.x, _EulerTarget.x, _Smoothing * 0.001f, Time.deltaTime)) - _Euler.x;
                _Euler.x       = _Euler.x + lFrameEuler.x;
            }

            return(lFrameEuler);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Grabs the combatants that fit the specified criteria
        /// </summary>
        /// <param name="rHunter">Transform who is searching for the combatants</param>
        /// <param name="rSeekOrigin">Combat origin of the hunter</param>
        /// <param name="rFilter">Filters we'll use to limit which combatants are returned</param>
        /// <param name="rCombatantHits">List of CombatantHit values who are the combatants</param>
        /// <param name="rIgnore">Transform that we won't consider a target (typically the character)</param>
        /// <returns>Count of combatants returned</returns>
        public static int QueryCombatTargets(Transform rSeeker, Vector3 rSeekOrigin, CombatFilter rFilter, List <CombatTarget> rCombatTargets, Transform rIgnore)
        {
            if (rSeeker == null)
            {
                return(0);
            }
            if (rCombatTargets == null)
            {
                return(0);
            }

#if OOTII_PROFILE
            com.ootii.Utilities.Profiler.Start(rSeeker.name + ".QueryCombatTargets");
#endif

            Collider[] lHitColliders;

            rCombatTargets.Clear();

            int lHitCount = RaycastExt.SafeOverlapSphere(rSeekOrigin, rFilter.MaxDistance, out lHitColliders, rFilter.Layers, rIgnore);
            for (int i = 0; i < lHitCount; i++)
            {
                GameObject lGameObject = lHitColliders[i].gameObject;

                // Don't count the ignore
                if (lGameObject.transform == rSeeker)
                {
                    continue;
                }
                if (lGameObject.transform == rIgnore)
                {
                    continue;
                }

                // Determine if the combatant has the appropriate tag
                if (rFilter.Tag != null && rFilter.Tag.Length > 0)
                {
                    if (!lGameObject.CompareTag(rFilter.Tag))
                    {
                        continue;
                    }
                }

                // We only care about combatants we'll enage with
                ICombatant lCombatant = null;

                Transform lHitTransform = lHitColliders[i].transform;
                while (lHitTransform != null)
                {
                    lCombatant = lGameObject.GetComponent <ICombatant>();
                    if (lCombatant != null)
                    {
                        break;
                    }

                    lHitTransform = lHitTransform.parent;
                }

                if (rFilter.RequireCombatant && lCombatant == null)
                {
                    continue;
                }

                // Determine if the combatant is within range
                Vector3         lClosestPoint    = Vector3.zero;
                ActorController lActorController = lGameObject.GetComponent <ActorController>();
                if (lActorController != null)
                {
                    lClosestPoint = lActorController.ClosestPoint(rSeekOrigin);
                }
                else
                {
                    lClosestPoint = GeometryExt.ClosestPoint(rSeekOrigin, lHitColliders[i]);
                }

                // If we have an invalid point, stop
                if (lClosestPoint == Vector3Ext.Null)
                {
                    continue;
                }

                // Determine if the point is in range
                bool    lIsValid        = true;
                Vector3 lToClosestPoint = lClosestPoint - rSeekOrigin;

                float lDistance = lToClosestPoint.magnitude;
                if (rFilter.MinDistance > 0f && lDistance < rFilter.MinDistance)
                {
                    lIsValid = false;
                }
                if (rFilter.MaxDistance > 0f && lDistance > rFilter.MaxDistance)
                {
                    lIsValid = false;
                }

                // Ensure we're not ontop of the combatant. In that case, it's probably the ground
                Vector3 lDirection = lToClosestPoint.normalized;
                if (lDirection == -rSeeker.up)
                {
                    lIsValid = false;
                }

                // Check if we're within the field of view
                float lHAngle = Vector3Ext.HorizontalAngleTo(rSeeker.forward, lDirection, rSeeker.up);
                if (rFilter.HorizontalFOA > 0f && Mathf.Abs(lHAngle) > rFilter.HorizontalFOA * 0.5f)
                {
                    lIsValid = false;
                }

                float lVAngle = Vector3Ext.HorizontalAngleTo(rSeeker.forward, lDirection, rSeeker.right);
                if (rFilter.VerticalFOA > 0f && Mathf.Abs(lVAngle) > rFilter.VerticalFOA * 0.5f)
                {
                    lIsValid = false;
                }

                // This is an odd test, but we have to do it. If the closest point of a sphere is out of the FOA, it may
                // be that the top of the sphere is in the FOA. So, we'll grab the top of the sphere and test it.
                if (!lIsValid && lCombatant != null && lHitColliders[i] is SphereCollider)
                {
                    lIsValid = true;
                    SphereCollider lSphereCollider = lHitColliders[i] as SphereCollider;

                    lClosestPoint   = lCombatant.Transform.position + (lCombatant.Transform.rotation * (lSphereCollider.center + (Vector3.up * lSphereCollider.radius)));
                    lToClosestPoint = lClosestPoint - rSeekOrigin;

                    lDistance = lToClosestPoint.magnitude;
                    if (rFilter.MinDistance > 0f && lDistance < rFilter.MinDistance)
                    {
                        lIsValid = false;
                    }
                    if (rFilter.MaxDistance > 0f && lDistance > rFilter.MaxDistance)
                    {
                        lIsValid = false;
                    }

                    // Ensure we're not ontop of the combatant. In that case, it's probably the ground
                    lDirection = lToClosestPoint.normalized;
                    if (lDirection == -rSeeker.up)
                    {
                        lIsValid = false;
                    }

                    // Check if we're within the field of view
                    lHAngle = Vector3Ext.HorizontalAngleTo(rSeeker.forward, lDirection, rSeeker.up);
                    if (rFilter.HorizontalFOA > 0f && Mathf.Abs(lHAngle) > rFilter.HorizontalFOA * 0.5f)
                    {
                        lIsValid = false;
                    }

                    lVAngle = Vector3Ext.HorizontalAngleTo(rSeeker.forward, lDirection, rSeeker.right);
                    if (rFilter.VerticalFOA > 0f && Mathf.Abs(lVAngle) > rFilter.VerticalFOA * 0.5f)
                    {
                        lIsValid = false;
                    }
                }

                if (mShowDebug)
                {
                    GraphicsManager.DrawPoint(rSeekOrigin, Color.white, null, 2f);
                    GraphicsManager.DrawPoint(lClosestPoint, Color.red, null, 2f);
                }

                if (lIsValid)
                {
                    // Add the combatant to our list
                    CombatTarget lTargetInfo = new CombatTarget();
                    lTargetInfo.SeekOrigin      = rSeekOrigin;
                    lTargetInfo.Collider        = lHitColliders[i];
                    lTargetInfo.Combatant       = lCombatant;
                    lTargetInfo.ClosestPoint    = lClosestPoint;
                    lTargetInfo.Distance        = lDistance;
                    lTargetInfo.Direction       = lDirection;
                    lTargetInfo.HorizontalAngle = lHAngle;
                    lTargetInfo.VerticalAngle   = lVAngle;

                    rCombatTargets.Add(lTargetInfo);
                }
            }

            // Sort the combatants by distance
            if (rCombatTargets.Count > 1)
            {
                rCombatTargets.Sort((rLeft, rRight) => rLeft.Distance.CompareTo(rRight.Distance));

                // We also want to remove duplicates
                for (int i = 0; i < rCombatTargets.Count; i++)
                {
                    Transform lTarget = rCombatTargets[i].Collider.transform;
                    if (rCombatTargets[i].Combatant != null)
                    {
                        lTarget = rCombatTargets[i].Combatant.Transform;
                    }

                    // Check if there's a duplicate and remove it
                    for (int j = rCombatTargets.Count - 1; j > i && j > 0; j--)
                    {
                        Transform lNextTarget = rCombatTargets[j].Collider.transform;
                        if (rCombatTargets[j].Combatant != null)
                        {
                            lNextTarget = rCombatTargets[j].Combatant.Transform;
                        }

                        if (lNextTarget == lTarget)
                        {
                            rCombatTargets.RemoveAt(j);
                        }
                    }
                }
            }

#if OOTII_PROFILE
            float lTime = Utilities.Profiler.Stop(rSeeker.name + ".QueryCombatTargets");
            //Utilities.Debug.Log.FileWrite(rSeeker.name + ".QueryCombatTargets time:" + lTime.ToString("f5") + "ms");
#endif

            // Finally, return the count
            return(rCombatTargets.Count);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Updates the motor over time. This is called by the controller
        /// every update cycle so movement can be updated.
        /// </summary>
        /// <param name="rDeltaTime">Time since the last frame (or fixed update call)</param>
        /// <param name="rUpdateIndex">Index of the update to help manage dynamic/fixed updates. [0: Invalid update, >=1: Valid update]</param>
        /// <param name="rTiltAngle">Amount of tilting the camera needs to do to match the anchor</param>
        public override CameraTransform RigLateUpdate(float rDeltaTime, int rUpdateIndex, float rTiltAngle = 0f)
        {
            Transform lAnchorTransform = Anchor;

            if (lAnchorTransform == null)
            {
                return(mRigTransform);
            }

            if (RigController == null)
            {
                return(mRigTransform);
            }
            Transform lCameraTransform = RigController._Transform;

            // Determine how much the anchor's yaw changed (we want to stay relative to the anchor direction)
            float lAnchorRootYawDelta = Vector3Ext.HorizontalAngleTo(mAnchorLastRotation.Forward(), lAnchorTransform.forward, lAnchorTransform.up);
            float lAnchorYaw          = (Mathf.Abs(rTiltAngle) >= 2f ? lAnchorRootYawDelta : 0f);

            if (!RigController.RotateAnchorOffset)
            {
                lAnchorRootYawDelta = 0f;
                lAnchorYaw          = 0f;
            }

            // Grab any euler changes this frame
            mFrameEuler = GetFrameEuler(true, true); // RigController.RotateAnchorOffset);

            // Get our predicted based on the frame and anchor changes. We want this to get the right-vector
            Quaternion lNewCameraRotation = Quaternion.AngleAxis(mFrameEuler.y + lAnchorYaw, (RigController.RotateAnchorOffset ? RigController.Tilt.Up() : Vector3.up)) * lCameraTransform.rotation;

            // Now grab the full (vertical + horizontal) position of our final focus.
            //Vector3 lNewFocusPosition = lAnchorTransform.position + (lAnchorTransform.up * lOffset.y);
            //lNewFocusPosition = lNewFocusPosition + (lNewCameraRotation.Right() * lOffset.x);
            Vector3 lNewFocusPosition = GetFocusPosition(lNewCameraRotation);

            // Default the value
            Vector3 lNewCameraPosition = lCameraTransform.position;
            Vector3 lToFocusPosition   = lCameraTransform.forward;

            // If we're tilting, act like a fixed
            if (RigController.FrameForceToFollowAnchor || Mathf.Abs(rTiltAngle) >= 2f)
            {
                // Get the local position and the right vector of the camera relative to the last frame
                Matrix4x4 lOldFocusMatrix = Matrix4x4.TRS(mFocusLastPosition, (RigController.RotateAnchorOffset ? mAnchorLastRotation : Quaternion.identity), Vector3.one);
                Matrix4x4 lNewFocusMatrix = Matrix4x4.TRS(lNewFocusPosition, (RigController.RotateAnchorOffset ? lAnchorTransform.rotation : Quaternion.identity), Vector3.one);

                // The matrix will add our anchor delta. But, we also added it when we use the LocalYaw
                // We'll remove it so we don't double up.
                if (mTargetYaw < float.MaxValue)
                {
                    mFrameEuler.y = mFrameEuler.y - lAnchorRootYawDelta;
                }

                // If nothing has changed, we won't update. This is important due to the fact
                // that the inverse of the matix causes a small floating point error to move us.
                if (mFrameEuler.sqrMagnitude != 0f || lOldFocusMatrix != lNewFocusMatrix)
                {
                    Vector3 lLocalPosition    = lOldFocusMatrix.inverse.MultiplyPoint(lCameraTransform.position);
                    Vector3 lLocalCameraRight = lOldFocusMatrix.inverse.MultiplyVector(lCameraTransform.right);

                    // Rotate the old local position based on the frame's rotation changes
                    Quaternion lLocalRotation = Quaternion.AngleAxis(mFrameEuler.y, Vector3.up) * Quaternion.AngleAxis(mFrameEuler.x, lLocalCameraRight);
                    lLocalPosition = lLocalRotation * lLocalPosition;

                    // Grab the new position based on the updated matrix
                    lNewCameraPosition = lNewFocusMatrix.MultiplyPoint(lLocalPosition);
                }
            }
            // If we have a target forward, act like a fixed
            else if (mTargetForward.sqrMagnitude > 0f)
            {
                lNewCameraRotation = lNewCameraRotation * Quaternion.AngleAxis(mFrameEuler.x, Vector3.right);
                lNewCameraPosition = lNewFocusPosition - (lNewCameraRotation.Forward() * mDistance);
            }
            else
            {
                lNewCameraRotation = lNewCameraRotation * Quaternion.AngleAxis(mFrameEuler.x, Vector3.right);
                Vector3 lOldCameraPosition = mFocusLastPosition - (lNewCameraRotation.Forward() * mDistance);

                // Grab the new focus position using the drag rotation we get
                lToFocusPosition = lNewFocusPosition - lOldCameraPosition;
                if (lToFocusPosition.sqrMagnitude < 0.0001f)
                {
                    lToFocusPosition = lCameraTransform.forward;
                }

                lNewCameraRotation = Quaternion.LookRotation(lToFocusPosition.normalized, (RigController.RotateAnchorOffset ? lAnchorTransform.up : Vector3.up));
                //lNewFocusPosition = lAnchorTransform.position + (lAnchorTransform.up * lOffset.y);
                //lNewFocusPosition = lNewFocusPosition + (lNewCameraRotation.Right() * lOffset.x);
                lNewFocusPosition = GetFocusPosition(lNewCameraRotation);

                // If something is between the new focus position and the anchor, the new focus position is the anchor
                //Color lHitColor = Color.black;
                //RaycastHit lFocusHit;
                Vector3 lAnchorPosition = Vector3.zero;

                if (RigController.RotateAnchorOffset)
                {
                    lAnchorPosition = lAnchorTransform.position + (lAnchorTransform.rotation * AnchorOffset) + (lAnchorTransform.up * _Offset.y);
                }
                else
                {
                    lAnchorPosition = lAnchorTransform.position + AnchorOffset + (Vector3.up * _Offset.y);
                }

                lToFocusPosition = lNewFocusPosition - lAnchorPosition;

                // Get the drag direction and pull out the horizontal component
                lToFocusPosition = lNewFocusPosition - lOldCameraPosition;
                if (lToFocusPosition.sqrMagnitude < 0.0001f)
                {
                    lToFocusPosition = lCameraTransform.forward;
                }

                Vector3 lToFocusPositionVertical   = Vector3.Project(lToFocusPosition, (RigController.RotateAnchorOffset ? RigController.Tilt.Up() : Vector3.up));
                Vector3 lToFocusPositionHorizontal = lToFocusPosition - lToFocusPositionVertical;

                // Get the pitch rotation regardless of our tilt
                lNewCameraRotation = lCameraTransform.rotation * Quaternion.AngleAxis(mFrameEuler.x, Vector3.right);
                Vector3 lRotationEuler = (RigController.RotateAnchorOffset ? Quaternion.Inverse(RigController.Tilt) * lNewCameraRotation : lNewCameraRotation).eulerAngles;

                // Add the pitch to our look-at rotation
                Quaternion lNewAnchorRotation = Quaternion.LookRotation(lToFocusPositionHorizontal, (RigController.RotateAnchorOffset ? RigController.Tilt.Up() : Vector3.up)) * Quaternion.Euler(lRotationEuler.x, 0f, 0f);

                // Using the rotation, grab the new camera position
                lNewCameraPosition = lNewFocusPosition - (lNewAnchorRotation.Forward() * mDistance);
            }

            // Determine our rotation
            lToFocusPosition = lNewFocusPosition - lNewCameraPosition;
            if (lToFocusPosition.sqrMagnitude < 0.0001f)
            {
                lToFocusPosition = lCameraTransform.forward;
            }

            lNewCameraRotation = Quaternion.LookRotation(lToFocusPosition.normalized, (RigController.RotateAnchorOffset ? lAnchorTransform.up : Vector3.up));

            // We have to do a final check if we have exceeded rotation limits
            Quaternion lNewLocalCameraRotation = (RigController.RotateAnchorOffset ? Quaternion.Inverse(Anchor.transform.rotation) : Quaternion.identity) * lNewCameraRotation;
            Vector3    lNewLocalEuler          = lNewLocalCameraRotation.eulerAngles;

            if (lNewLocalEuler.y > 180f)
            {
                lNewLocalEuler.y = lNewLocalEuler.y - 360f;
            }
            else if (lNewLocalEuler.y < -180f)
            {
                lNewLocalEuler.y = lNewLocalEuler.y + 360f;
            }

            if (lNewLocalEuler.x > 180f)
            {
                lNewLocalEuler.x = lNewLocalEuler.x - 360f;
            }
            else if (lNewLocalEuler.x < -180f)
            {
                lNewLocalEuler.x = lNewLocalEuler.x + 360f;
            }

            float lYaw   = (_MinYaw > -180f || _MaxYaw < 180f ? Mathf.Clamp(lNewLocalEuler.y, _MinYaw, _MaxYaw) : lNewLocalEuler.y);
            float lPitch = Mathf.Clamp(lNewLocalEuler.x, _MinPitch, _MaxPitch);

            if (lYaw != lNewLocalEuler.y || lPitch != lNewLocalEuler.x)
            {
                lNewCameraRotation = (RigController.RotateAnchorOffset ? Anchor.transform.rotation : Quaternion.identity) * Quaternion.Euler(lPitch, lYaw, 0f);
                lNewCameraPosition = lNewFocusPosition - (lNewCameraRotation.Forward() * mDistance);
            }

            // Return the results
            mRigTransform.Position = lNewCameraPosition;
            mRigTransform.Rotation = lNewCameraRotation;
            return(mRigTransform);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Updates the motor over time. This is called by the controller
        /// every update cycle so movement can be updated.
        /// </summary>
        /// <param name="rDeltaTime">Time since the last frame (or fixed update call)</param>
        /// <param name="rUpdateIndex">Index of the update to help manage dynamic/fixed updates. [0: Invalid update, >=1: Valid update]</param>
        /// <param name="rTiltAngle">Amount of tilting the camera needs to do to match the anchor</param>
        public override CameraTransform RigLateUpdate(float rDeltaTime, int rUpdateIndex, float rTiltAngle = 0f)
        {
            Transform lAnchorTransform = Anchor;

            if (lAnchorTransform == null)
            {
                return(mRigTransform);
            }

            if (RigController == null)
            {
                return(mRigTransform);
            }
            //Quaternion lTilt = RigController.Tilt;
            Transform lCameraTransform = RigController._Transform;

            // Determine how much the anchor's yaw changed (we want to stay relative to the anchor direction)
            float lAnchorRootYawDelta = Vector3Ext.HorizontalAngleTo(mAnchorLastRotation.Forward(), lAnchorTransform.forward, lAnchorTransform.up);
            float lAnchorYaw          = (Mathf.Abs(rTiltAngle) >= 2f ? lAnchorRootYawDelta : 0f);

            if (!RigController.RotateAnchorOffset)
            {
                lAnchorRootYawDelta = 0f;
                lAnchorYaw          = 0f;
            }

            // Grab any euler changes this frame
            mFrameEuler = GetFrameEuler(true, RigController.RotateAnchorOffset);

            // Get our predicted based on the frame and anchor changes. We want this to get the right-vector
            Quaternion lNewCameraRotation = Quaternion.AngleAxis(mFrameEuler.y + lAnchorYaw, (RigController.RotateAnchorOffset ? RigController.Tilt.Up() : Vector3.up)) * lCameraTransform.rotation;

            // Now grab the full (vertical + horizontal) position of our final focus.
            //Vector3 lNewFocusPosition = lAnchorTransform.position + (lAnchorTransform.up * lAnchorOffset.y);
            //lNewFocusPosition = lNewFocusPosition + (lNewCameraRotation.Right() * lAnchorOffset.x);
            Vector3 lNewFocusPosition = GetFocusPosition(lNewCameraRotation);

            // Default the value
            Vector3 lNewCameraPosition = lCameraTransform.position;
            Vector3 lToFocusPosition   = lCameraTransform.forward;

            // If we're tilting, act like a fixed
            if (_RotateWithAnchor || RigController.FrameForceToFollowAnchor || Mathf.Abs(rTiltAngle) >= 2f)
            {
                // Get the local position and the right vector of the camera relative to the last frame
                Matrix4x4 lOldFocusMatrix = Matrix4x4.TRS(mFocusLastPosition, (RigController.RotateAnchorOffset ? mAnchorLastRotation : Quaternion.identity), Vector3.one);
                Matrix4x4 lNewFocusMatrix = Matrix4x4.TRS(lNewFocusPosition, (RigController.RotateAnchorOffset ? lAnchorTransform.rotation : Quaternion.identity), Vector3.one);

                // The matrix will add our anchor delta. But, we also added it when we use the LocalYaw
                // We'll remove it so we don't double up.
                if (mTargetYaw < float.MaxValue)
                {
                    mFrameEuler.y = mFrameEuler.y - lAnchorRootYawDelta;
                }

                // If nothing has changed, we won't update. This is important due to the fact
                // that the inverse of the matix causes a small floating point error to move us.
                if (mFrameEuler.sqrMagnitude != 0f || lOldFocusMatrix != lNewFocusMatrix)
                {
                    Vector3 lLocalPosition    = lOldFocusMatrix.inverse.MultiplyPoint(lCameraTransform.position);
                    Vector3 lLocalCameraRight = lOldFocusMatrix.inverse.MultiplyVector(lCameraTransform.right);

                    // Rotate the old local position based on the frame's rotation changes
                    Quaternion lLocalRotation = Quaternion.AngleAxis(mFrameEuler.y, Vector3.up) * Quaternion.AngleAxis(mFrameEuler.x, lLocalCameraRight);
                    lLocalPosition = lLocalRotation * lLocalPosition;

                    // Grab the new position based on the updated matrix
                    lNewCameraPosition = lNewFocusMatrix.MultiplyPoint(lLocalPosition);

                    // The problem is that we may not be allowing the camera to pull back to the desired distance.
                    // So, apply the distance to the direction and that's our new position.
                    Vector3 lDirection = (lNewCameraPosition - lNewFocusPosition).normalized;
                    lNewCameraPosition = lNewFocusPosition + (lDirection * mDistance);
                }

                // Ensure our camera isn't inbetween the focus and the anchor
                float lNewCameraDistance = Vector3.Distance(AnchorPosition, lNewCameraPosition);
                float lNewFocusDistance  = Vector3.Distance(AnchorPosition, lNewFocusPosition);
                if (lNewCameraDistance < lNewFocusDistance)
                {
                    lNewCameraPosition = lNewFocusPosition - (lNewCameraRotation.Forward() * mDistance);
                }
            }
            else
            {
                lNewCameraRotation = lNewCameraRotation * Quaternion.AngleAxis(mFrameEuler.x, Vector3.right);
                lNewCameraPosition = lNewFocusPosition - (lNewCameraRotation.Forward() * mDistance);
            }

            // Determine our rotation
            lToFocusPosition = lNewFocusPosition - lNewCameraPosition;
            if (lToFocusPosition.sqrMagnitude < 0.0001f)
            {
                lToFocusPosition = lCameraTransform.forward;
            }

            // Ensure we have the right rotation
            lNewCameraRotation = Quaternion.LookRotation(lToFocusPosition.normalized, (RigController.RotateAnchorOffset ? lAnchorTransform.up : Vector3.up));

            // Ensure we're the correct distance from the focus point
            if (lToFocusPosition.magnitude != mDistance)
            {
                lNewCameraPosition = lNewFocusPosition - (lToFocusPosition.normalized * mDistance);
            }

            // Return the results
            mRigTransform.Position = lNewCameraPosition;
            mRigTransform.Rotation = lNewCameraRotation;
            return(mRigTransform);
        }