public override MultiAimInverseConstraintJob Create(Animator animator, ref T data, Component component)
        {
            var job = new MultiAimInverseConstraintJob();

            job.driven       = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject);
            job.drivenParent = ReadOnlyTransformHandle.Bind(animator, data.constrainedObject.parent);
            job.drivenOffset = Vector3Property.Bind(animator, component, data.offsetVector3Property);
            job.aimAxis      = data.aimAxis;

            WeightedTransformArray sourceObjects = data.sourceObjects;

            WeightedTransformArrayBinder.BindReadWriteTransforms(animator, component, sourceObjects, out job.sourceTransforms);
            WeightedTransformArrayBinder.BindWeights(animator, component, sourceObjects, data.sourceObjectsProperty, out job.sourceWeights);

            job.sourceOffsets = new NativeArray <Quaternion>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            for (int i = 0; i < sourceObjects.Count; ++i)
            {
                if (data.maintainOffset)
                {
                    var aimDirection = data.constrainedObject.rotation * data.aimAxis;
                    var dataToSource = sourceObjects[i].transform.position - data.constrainedObject.position;
                    var rot          = QuaternionExt.FromToRotation(dataToSource, aimDirection);
                    job.sourceOffsets[i] = Quaternion.Inverse(rot);
                }
                else
                {
                    job.sourceOffsets[i] = Quaternion.identity;
                }
            }

            job.weightBuffer = new NativeArray <float>(sourceObjects.Count, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);

            return(job);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Use this for initialization
        /// </summary>
        protected override void Awake()
        {
            base.Awake();

            if (_Anchor != null && this.enabled)
            {
                ICharacterController lController = InterfaceHelper.GetComponent <ICharacterController>(_Anchor.gameObject);
                if (lController != null)
                {
                    IsInternalUpdateEnabled = false;
                    IsFixedUpdateEnabled    = false;
                    lController.OnControllerPostLateUpdate += OnControllerLateUpdate;
                }

                mTilt = QuaternionExt.FromToRotation(_Transform.up, _Anchor.up);

                mToCameraDirection   = _Transform.position - _Anchor.position;
                mToCameraDirection.y = 0f;
                mToCameraDirection.Normalize();

                if (mToCameraDirection.sqrMagnitude == 0f)
                {
                    mToCameraDirection = -_Anchor.forward;
                }
            }

            // Object that will provide access to the keyboard, mouse, etc
            if (_InputSourceOwner != null)
            {
                mInputSource = InterfaceHelper.GetComponent <IInputSource>(_InputSourceOwner);
            }

            // Default the speed we'll use to rotate
            mDegreesPer60FPSTick = _RotationSpeed / 60f;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Determines if we'll treat input as if we're strafing
        /// </summary>
        protected void SimulateStrafeInput()
        {
            // Direction we need to travel in
            Vector3 lDirection = mWaypointVector;

            lDirection.y = lDirection.y - _PathHeight;
            lDirection.Normalize();

            // Determine our view
            Vector3 lVerticalDirection = Vector3.Project(lDirection, _Transform.up);
            Vector3 lLateralDirection  = (lDirection - lVerticalDirection).normalized;

            mInputFromAvatarAngle = Vector3Ext.SignedAngle(_Transform.forward, lLateralDirection);

            // Determine our movement
            if (mTargetDistance > _StopDistance)
            {
                // Calculate our own slowing
                float lRelativeMoveSpeed = 1f;
                if (mIsInSlowDistance && _SlowFactor > 0f)
                {
                    float lSlowPercent = (mTargetDistance - _StopDistance) / (_SlowDistance - _StopDistance);
                    lRelativeMoveSpeed = ((1f - _SlowFactor) * lSlowPercent) + _SlowFactor;
                }

                // TRT 4/5/2016: Force the slow distance as an absolute value
                if (mIsInSlowDistance && _SlowFactor > 0f)
                {
                    lRelativeMoveSpeed = _SlowFactor;
                }

                lLateralDirection = _Transform.InverseTransformDirection(lLateralDirection);
                mMovementX        = lLateralDirection.x * lRelativeMoveSpeed;
                mMovementY        = lLateralDirection.z * lRelativeMoveSpeed;
            }

            // Grab extra input information if we can
            if (mMotionController._CameraTransform == null)
            {
                mInputFromCameraAngle = mInputFromAvatarAngle;
            }
            else
            {
                Vector3 lInputForward = new Vector3(mMovementX, 0f, mMovementY);

                // We do the inverse tilt so we calculate the rotation in "natural up" space vs. "actor up" space.
                Quaternion lInvTilt = QuaternionExt.FromToRotation(_Transform.up, Vector3.up);

                // Camera forward in "natural up"
                Vector3 lCameraForward = lInvTilt * mMotionController._CameraTransform.forward;

                // Create a quaternion that gets us from our world-forward to our camera direction.
                Quaternion lToCamera = Quaternion.LookRotation(lCameraForward, lInvTilt * _Transform.up);

                // Transform joystick from world space to camera space. Now the input is relative
                // to how the camera is facing.
                Vector3 lMoveDirection = lToCamera * lInputForward;
                mInputFromCameraAngle = NumberHelper.GetHorizontalAngle(lCameraForward, lMoveDirection);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Create a rotation velocity that rotates the character based on input
        /// </summary>
        /// <param name="rInputFromAvatarAngle"></param>
        /// <param name="rDeltaTime"></param>
        protected virtual void RotateActorToTarget(Transform rTarget, float rSpeed)
        {
            // Get the forward looking direction
            Vector3 lForward = (rTarget.position - mActorController._Transform.position).normalized;

            // We do the inverse tilt so we calculate the rotation in "natural up" space vs. "actor up" space.
            Quaternion lInvTilt = QuaternionExt.FromToRotation(mActorController._Transform.up, Vector3.up);

            // Character's forward direction of the actor in "natural up"
            Vector3 lActorForward = lInvTilt * mActorController._Transform.forward;

            // Target forward in "natural up"
            Vector3 lTargetForward = lInvTilt * lForward;

            // Ensure we don't exceed our rotation speed
            float lActorToTargetAngle = NumberHelper.GetHorizontalAngle(lActorForward, lTargetForward);

            if (rSpeed > 0f && Mathf.Abs(lActorToTargetAngle) > rSpeed * Time.deltaTime)
            {
                lActorToTargetAngle = Mathf.Sign(lActorToTargetAngle) * rSpeed * Time.deltaTime;
            }

            // Add the rotation to our character
            Quaternion lRotation = Quaternion.AngleAxis(lActorToTargetAngle, Vector3.up);

            if (mActorController._UseTransformPosition && mActorController._UseTransformRotation)
            {
                _Transform.rotation = _Transform.rotation * lRotation;
            }
            else
            {
                mActorController.Rotate(lRotation, Quaternion.identity);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Provides a place to set the properties of the animator
        /// </summary>
        /// <param name="rInput">Vector3 representing the input</param>
        /// <param name="rMove">Vector3 representing the amount of movement taking place (in world space)</param>
        /// <param name="rRotate">Quaternion representing the amount of rotation taking place</param>
        protected override void SetAnimatorProperties(Vector3 rInput, Vector3 rMovement, Quaternion rRotation)
        {
            if (mInputSource == null || !mInputSource.IsEnabled)
            {
                return;
            }

            // Jump based on space
            bool lIsInJump = !mActorController.State.IsGrounded;

            if (mInputSource.IsJustPressed("Jump"))
            {
                if (!lIsInJump && !mIsInJumpToWall)
                {
                    lIsInJump = true;

                    // We need to check if we're actually jumping towards a wall
                    RaycastHit lHitInfo;
                    if (RaycastExt.SafeRaycast(transform.position + (transform.up * JumpToWallHeight), transform.forward, out lHitInfo, JumpToWallDistance))
                    {
                        mIsInJumpToWall        = true;
                        mJumpToWallPoint       = lHitInfo.point;
                        mJumpToWallNormal      = lHitInfo.normal;
                        mJumpToWallElapsedTime = 0f;

                        mSavedOrientToGroundSpeed            = mActorController.OrientToGroundSpeed;
                        mActorController.OrientToGroundSpeed = JumpToWallOrientSpeed;
                    }

                    // Perform the jump
                    mActorController.AddImpulse(transform.up * _JumpForce);
                }
            }

            // Direction of the camera
            float lDirection = 0f;

            // We do the inverse tilt so we calculate the rotation in "natural up" space vs. "actor up" space.
            Quaternion lInvTilt = QuaternionExt.FromToRotation(mActorController._Transform.up, Vector3.up);

            // Forward direction of the actor in "natural up"
            Vector3 lControllerForward = lInvTilt * mActorController._Transform.forward;

            // Get the angular difference between the camera-based input and the spider's "natural-up" forward
            lDirection = NumberHelper.GetHorizontalAngle(lControllerForward, rInput);

            mAnimator.SetFloat("Direction", lDirection);
            mAnimator.SetFloat("Speed", rInput.magnitude);
            mAnimator.SetBool("Jump", lIsInJump);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Causes us to ignore user input and force the camera to the specified localangles
        /// </summary>
        /// <param name="rYaw">Target local yaw</param>
        /// <param name="rPitch">Target local pitch</param>
        /// <param name="rSpeed">Degrees per second we'll rotate. A value of -1 uses the current yaw speed.</param>
        /// <param name="rAutoClearTarget">Determines if we'll clear the target once we reach it.</param>
        public override void SetTargetYawPitch(float rYaw, float rPitch, float rSpeed = -1F, bool rAutoClearTarget = true)
        {
            Vector3 lNewAnchorPosition = _Anchor.position + (_Anchor.rotation * _AnchorOffset);

            // Grab the rotation amount. We do the inverse tilt so we calculate the rotation in
            // "natural up" space. Later we'll use the tilt to put it back into "anchor up" space.
            Quaternion lInvTilt = QuaternionExt.FromToRotation(_Anchor.up, Vector3.up);

            // Yaw is simple as we can go 360
            Quaternion lYaw = Quaternion.AngleAxis((rYaw - LocalYaw), lInvTilt * _Transform.up);

            // Pitch is more complicated since we can't go beyond the north/south pole
            float lPitchAngle = Vector3.Angle(mToCameraDirection, lInvTilt * _Anchor.up);

            float lPitchDelta = rPitch - LocalPitch;

            if (lPitchAngle < MIN_PITCH && lPitchDelta > 0f)
            {
                lPitchDelta = 0f;
            }
            else if (lPitchAngle > MAX_PITCH && lPitchDelta < 0f)
            {
                lPitchDelta = 0f;
            }

            Quaternion lPitch = Quaternion.AngleAxis(lPitchDelta, lInvTilt * _Transform.right);

            // Calculate the new "natural up" direction
            mToCameraDirection = lPitch * lYaw * mToCameraDirection;

            // Update our tilt to match the anchor's tilt
            mTilt = QuaternionExt.FromToRotation(mTilt.Up(), _Anchor.up) * mTilt;

            // Put the new direction relative to the anchor's tilt
            Vector3 lToCameraDirection = mTilt * mToCameraDirection;

            if (lToCameraDirection.sqrMagnitude == 0f)
            {
                lToCameraDirection = -_Anchor.forward;
            }

            // Calculate the new orbit center (anchor) and camera position
            Vector3    lNewCameraPosition = lNewAnchorPosition + (lToCameraDirection.normalized * _Radius);
            Quaternion lNewCameraRotation = Quaternion.LookRotation(lNewAnchorPosition - lNewCameraPosition, _Anchor.up);

            _Transform.position = lNewCameraPosition;
            _Transform.rotation = lNewCameraRotation;
        }
Exemplo n.º 7
0
        /// <summary>
        /// When we want to rotate based on the camera direction (which input does), 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;
            }

            // Get out early if we we aren't modifying the view.
            if (mMotionController._InputSource != null && mMotionController._InputSource.ViewX == 0f)
            {
                return;
            }

            // We do the inverse tilt so we calculate the rotation in "natural up" space vs. "actor up" space.
            Quaternion lInvTilt = QuaternionExt.FromToRotation(mMotionController._Transform.up, Vector3.up);

            // Forward direction of the actor in "natural up"
            Vector3 lControllerForward = lInvTilt * mMotionController._Transform.forward;

            // Camera forward in "natural up"
            Vector3 lCameraForward = lInvTilt * mMotionController._CameraTransform.forward;

            // Create a quaternion that gets us from our world-forward to our camera direction.
            Quaternion lToCamera = Quaternion.LookRotation(lCameraForward, Vector3.up);

            // Transform joystick from world space to camera space. Now the input is relative
            // to how the camera is facing.
            Vector3 lMoveDirection        = lToCamera * mMotionController.State.InputForward;
            float   lInputFromAvatarAngle = NumberHelper.GetHorizontalAngle(lControllerForward, lMoveDirection);

            // Clear the link if we're out of rotation range
            if (Mathf.Abs(lInputFromAvatarAngle) > _RotationSpeed * rDeltaTime * 5f)
            {
                mIsRotationLocked = false;
            }

            // We only want to do this is we're very very close to the desired angle. This will remove any stuttering
            if (_RotationSpeed == 0f || mIsRotationLocked || Mathf.Abs(lInputFromAvatarAngle) < _RotationSpeed * rDeltaTime * 1f)
            {
                mIsRotationLocked = true;

                // Since we're after the camera update, we have to force the rotation outside the normal flow
                Quaternion lRotation = Quaternion.AngleAxis(lInputFromAvatarAngle, Vector3.up);
                mActorController.Yaw = mActorController.Yaw * lRotation;
                mActorController._Transform.rotation = mActorController.Tilt * mActorController.Yaw;
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// When we want to rotate based on the camera direction (which input does), 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>
        protected virtual void OnCameraUpdated(float rDeltaTime, int rUpdateIndex, BaseCameraRig rCamera)
        {
            if (!_RotateWithCamera)
            {
                return;
            }
            if (_RequireTarget && mCombatant != null && mCombatant.IsTargetLocked)
            {
                return;
            }

            // Get out early if we we aren't modifying the view.
            if (mMotionController._InputSource != null && mMotionController._InputSource.ViewX == 0f)
            {
                return;
            }

            // We do the inverse tilt so we calculate the rotation in "natural up" space vs. "actor up" space.
            Quaternion lInvTilt = QuaternionExt.FromToRotation(mMotionController._Transform.up, Vector3.up);

            // Forward direction of the actor in "natural up"
            Vector3 lActorForward = lInvTilt * mMotionController._Transform.forward;

            // Camera forward in "natural up"
            Vector3 lCameraForward = lInvTilt * mMotionController._CameraTransform.forward;

            // Get the rotation angle to the camera
            float lActorToCameraAngle = NumberHelper.GetHorizontalAngle(lActorForward, lCameraForward);

            // Clear the link if we're out of rotation range
            if (Mathf.Abs(lActorToCameraAngle) > _RotationSpeed * rDeltaTime * 5f)
            {
                mIsRotationLocked = false;
            }

            // We only want to do this is we're very very close to the desired angle. This will remove any stuttering
            if (_RotationSpeed == 0f || mIsRotationLocked || Mathf.Abs(lActorToCameraAngle) < _RotationSpeed * rDeltaTime * 1f)
            {
                mIsRotationLocked = true;

                // Since we're after the camera update, we have to force the rotation outside the normal flow
                Quaternion lRotation = Quaternion.AngleAxis(lActorToCameraAngle, Vector3.up);
                mActorController.Yaw = mActorController.Yaw * lRotation;
                mActorController._Transform.rotation = mActorController.Tilt * mActorController.Yaw;
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Create a rotation velocity that rotates the character based on input
        /// </summary>
        /// <param name="rInputFromAvatarAngle"></param>
        /// <param name="rDeltaTime"></param>
        protected void RotateToDirection(Vector3 rForward, float rSpeed, float rDeltaTime, ref Quaternion rRotation)
        {
            // We do the inverse tilt so we calculate the rotation in "natural up" space vs. "actor up" space.
            Quaternion lInvTilt = QuaternionExt.FromToRotation(mMotionController._Transform.up, Vector3.up);

            // Forward direction of the actor in "natural up"
            Vector3 lActorForward = lInvTilt * mMotionController._Transform.forward;

            // Camera forward in "natural up"
            Vector3 lTargetForward = lInvTilt * rForward;

            // Ensure we don't exceed our rotation speed
            float lActorToCameraAngle = NumberHelper.GetHorizontalAngle(lActorForward, lTargetForward);

            if (rSpeed > 0f && Mathf.Abs(lActorToCameraAngle) > rSpeed * rDeltaTime)
            {
                lActorToCameraAngle = Mathf.Sign(lActorToCameraAngle) * rSpeed * rDeltaTime;
            }

            // We only want to do this is we're very very close to the desired angle. This will remove any stuttering
            rRotation = Quaternion.AngleAxis(lActorToCameraAngle, Vector3.up);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Called every frame so the driver can process input and
        /// update the actor controller.
        /// </summary>
        protected virtual void Update()
        {
            // Ensure we have everything we need
            if (mActorController == null)
            {
                return;
            }
            if (mInputSource == null || !mInputSource.IsEnabled)
            {
                return;
            }

            // Initialize some variables
            Vector3    lMovement = Vector3.zero;
            Quaternion lRotation = Quaternion.identity;

            // -----------------------------------------------------------------
            // INPUT
            // -----------------------------------------------------------------

            // This is the horizontal movement of the mouse or Xbox controller's right stick
            //float lYaw = mInputSource.ViewX;

            // This is the WASD buttons or Xbox controller's left stick
            Vector3 lInput = new Vector3(mInputSource.MovementX, 0f, mInputSource.MovementY);


            // -----------------------------------------------------------------
            // ATTACH TO WALL
            // -----------------------------------------------------------------
            if (mIsInToWall)
            {
                Vector3 lToWallHit       = mToWallPoint - transform.position;
                float   lToWallHitNormal = Vector3.Angle(mActorController._Transform.up, mToWallNormal);

                // Move to the target and ensure we orient ourselves to the wall
                if (lToWallHit.magnitude > 0.03f || lToWallHitNormal > 0.5f)
                {
                    mActorController.SetTargetGroundNormal(mToWallNormal);

                    lMovement = lToWallHit.normalized * Mathf.Min(MovementSpeed * Time.deltaTime, lToWallHit.magnitude);
                    mActorController.Move(lMovement);
                }
                // Once we're there, clean up
                else
                {
                    mIsInToWall   = false;
                    mToWallPoint  = Vector3.zero;
                    mToWallNormal = Vector3.zero;

                    mActorController.MaxSlopeAngle       = mSavedMaxSlopeAngle;
                    mActorController.OrientToGroundSpeed = mSavedOrientToGroundSpeed;
                    mActorController.SetTargetGroundNormal(Vector3.zero);

                    // Disable gravity temporarily
                    mActorController.IsGravityEnabled     = true;
                    mActorController.FixGroundPenetration = true;
                }
            }
            else
            {
                // -----------------------------------------------------------------
                // ROTATE
                // -----------------------------------------------------------------

                // Set the target based on the input. This works because we're looking down
                // the world's z-axis.
                if (lInput.x < 0f)
                {
                    mTargetForward = Vector3.left;
                }
                else if (lInput.x > 0f)
                {
                    mTargetForward = Vector3.right;
                }

                // If we have a target forward start rotating towards it and ignore input
                if (mTargetForward.sqrMagnitude > 0f)
                {
                    // Determine how much we need to rotate to get to the target
                    float lTargetAngle = Vector3Ext.SignedAngle(mActorController.Yaw.Forward(), mTargetForward);

                    // If there is no difference, we can turn off the target
                    if (lTargetAngle == 0f)
                    {
                        mTargetForward = Vector3.zero;
                    }
                    else
                    {
                        // Grab the actual rotation angle based on our speed. However, make sure we don't overshoot the
                        // angle. So, we do this logic to truncate it if we're only a tiny bit off.
                        float lRotationAngle = Mathf.Sign(lTargetAngle) * Mathf.Min(RotationSpeed * Time.deltaTime, Mathf.Abs(lTargetAngle));

                        // Since the rotate function deals with the actor's yaw, we just to a vector3.up (it's
                        // relative to the actor regardless of his orientation/tilt
                        lRotation = Quaternion.AngleAxis(lRotationAngle, Vector3.up);

                        // Rotate.
                        mActorController.Rotate(lRotation);
                    }
                }

                // -----------------------------------------------------------------
                // MOVE
                // -----------------------------------------------------------------

                // We get the tilt so we can add this up/down direction to the camera input. This helps
                // characters to not run off ramps since they are moving how they are facing (ie down a ramp)
                // vs. simply forward (off the ramp)
                Quaternion lTilt = QuaternionExt.FromToRotation(Vector3.up, mActorController._Transform.up);

                // Move based on WASD we add the tilt
                lMovement = lTilt * lInput * MovementSpeed * Time.deltaTime;
                mActorController.Move(lMovement);

                // -----------------------------------------------------------------
                // JUMP
                // -----------------------------------------------------------------

                // Only jump if the button is pressed and we're on the ground
                if (mInputSource.IsJustPressed("Jump"))
                {
                    if (mActorController.State.IsGrounded)
                    {
                        mActorController.AddImpulse(mActorController._Transform.up * JumpForce);
                    }
                }

                // -----------------------------------------------------------------
                // TEST FOR WALL
                // -----------------------------------------------------------------

                RaycastHit lWallHitInfo;
                if (TestForWallCollision(lMovement, out lWallHitInfo) ||
                    TestForWallAt90DegreeDrop(lMovement, out lWallHitInfo))
                {
                    // Save the tilt values
                    mIsInToWall   = true;
                    mToWallPoint  = lWallHitInfo.point;
                    mToWallNormal = lWallHitInfo.normal;

                    // Save and reset some AC values that will help us to tilt
                    mSavedOrientToGroundSpeed            = mActorController.OrientToGroundSpeed;
                    mActorController.OrientToGroundSpeed = 0.75f;

                    mSavedMaxSlopeAngle            = mActorController.MaxSlopeAngle;
                    mActorController.MaxSlopeAngle = 0f;

                    // Disable gravity temporarily
                    mActorController.IsGravityEnabled     = false;
                    mActorController.FixGroundPenetration = false;
                }
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// LateUpdate logic for the controller should be done here. This allows us
        /// to support dynamic and fixed update times
        /// </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>
        public override void RigLateUpdate(float rDeltaTime, int rUpdateIndex)
        {
            Vector3    lNewAnchorPosition = _Anchor.position + (_Anchor.rotation * _AnchorOffset);
            Vector3    lNewCameraPosition = _Transform.position;
            Quaternion lNewCameraRotation = _Transform.rotation;

            // At certain times, we may force the rig to face the direction of the actor
            if (_FrameForceToFollowAnchor)
            {
                // Grab the rotation amount. We do the inverse tilt so we calculate the rotation in
                // "natural up" space. Later we'll use the tilt to put it back into "anchor up" space.
                Quaternion lInvTilt = QuaternionExt.FromToRotation(_Anchor.up, Vector3.up);

                // Determine the global direction the character should face
                float      lAngle = NumberHelper.GetHorizontalAngle(_Transform.forward, _Anchor.forward, _Anchor.up);
                Quaternion lYaw   = Quaternion.AngleAxis(lAngle, lInvTilt * _Anchor.up);

                // Pitch is more complicated since we can't go beyond the north/south pole
                Quaternion lPitch = Quaternion.identity;
                if (mInputSource.IsViewingActivated)
                {
                    float lPitchAngle = Vector3.Angle(mToCameraDirection, lInvTilt * _Anchor.up);

                    float lPitchDelta = (_InvertPitch ? -1f : 1f) * mInputSource.ViewY;
                    if (lPitchAngle < MIN_PITCH && lPitchDelta > 0f)
                    {
                        lPitchDelta = 0f;
                    }
                    else if (lPitchAngle > MAX_PITCH && lPitchDelta < 0f)
                    {
                        lPitchDelta = 0f;
                    }

                    lPitch = Quaternion.AngleAxis(lPitchDelta, lInvTilt * _Transform.right);
                }

                // Calculate the new "natural up" direction
                mToCameraDirection = lPitch * lYaw * mToCameraDirection;

                // Update our tilt to match the anchor's tilt
                mTilt = QuaternionExt.FromToRotation(mTilt.Up(), _Anchor.up) * mTilt;

                // Put the new direction relative to the anchor's tilt
                Vector3 lToCameraDirection = mTilt * mToCameraDirection;
                if (lToCameraDirection.sqrMagnitude == 0f)
                {
                    lToCameraDirection = -_Anchor.forward;
                }

                // Calculate the new orbit center (anchor) and camera position
                lNewCameraPosition = lNewAnchorPosition + (lToCameraDirection.normalized * _Radius);
                lNewCameraRotation = Quaternion.LookRotation(lNewAnchorPosition - lNewCameraPosition, _Anchor.up);

                // Disable the force
                _FrameForceToFollowAnchor = false;
            }
            // If we're not forcing a follow, do our normal processing
            else
            {
                if (mInputSource.IsViewingActivated)
                {
                    // Grab the rotation amount. We do the inverse tilt so we calculate the rotation in
                    // "natural up" space. Later we'll use the tilt to put it back into "anchor up" space.
                    Quaternion lInvTilt = QuaternionExt.FromToRotation(_Anchor.up, Vector3.up);

                    // Yaw is simple as we can go 360
                    Quaternion lYaw = Quaternion.AngleAxis(mInputSource.ViewX * mDegreesPer60FPSTick, lInvTilt * _Transform.up);

                    // Pitch is more complicated since we can't go beyond the north/south pole
                    float lPitchAngle = Vector3.Angle(mToCameraDirection, lInvTilt * _Anchor.up);

                    float lPitchDelta = (_InvertPitch ? -1f : 1f) * mInputSource.ViewY;
                    if (lPitchAngle < MIN_PITCH && lPitchDelta > 0f)
                    {
                        lPitchDelta = 0f;
                    }
                    else if (lPitchAngle > MAX_PITCH && lPitchDelta < 0f)
                    {
                        lPitchDelta = 0f;
                    }

                    Quaternion lPitch = Quaternion.AngleAxis(lPitchDelta, lInvTilt * _Transform.right);

                    // Calculate the new "natural up" direction
                    mToCameraDirection = lPitch * lYaw * mToCameraDirection;
                }

                // Update our tilt to match the anchor's tilt
                mTilt = QuaternionExt.FromToRotation(mTilt.Up(), _Anchor.up) * mTilt;

                // Put the new direction relative to the anchor's tilt
                Vector3 lToCameraDirection = mTilt * mToCameraDirection;
                if (lToCameraDirection.sqrMagnitude == 0f)
                {
                    lToCameraDirection = -_Anchor.forward;
                }

                // Calculate the new orbit center (anchor) and camera position
                lNewCameraPosition = lNewAnchorPosition + (lToCameraDirection.normalized * _Radius);
                lNewCameraRotation = Quaternion.LookRotation(lNewAnchorPosition - lNewCameraPosition, _Anchor.up);
            }

            // Set the values
            _Transform.position = lNewCameraPosition;
            _Transform.rotation = lNewCameraRotation;
        }
        public void ProcessAnimation(AnimationStream stream)
        {
            var jointCount  = boneChain.Length;
            var boneCount   = jointCount - 1;
            var tipPosition = tipTarget.GetPosition(stream);
            var weight      = jobWeight.Get(stream);
            var positions   = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var tangents    = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var normals     = new NativeArray <float3>(jointCount, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
            var v0          = boneChain[0].GetRotation(stream) * Vector3.up;

            // fill the local buffer of positions
            for (var i = 0; i < jointCount; i++)
            {
                positions[i] = boneChain[i].GetPosition(stream);
            }

            // perform solver iterations
            for (var i = 0; i < iterationCount; i++)
            {
                // force final position to the tip target... unsure if this is the best...
                positions[positions.Length - 1] = tipPosition;

                // project distance constraints
                for (var j = 0; j < boneCount; j++)
                {
                    var invMass0 = j == 0 ? 0f : 1f;
                    var invMass1 = j == boneCount - 1 ? 0 : 1f;
                    var p0       = positions[j + 0];
                    var p1       = positions[j + 1];
                    var d        = restLengths[j];
                    var C        = distance(p0, p1) - d;

                    if (C < float.Epsilon && C > -float.Epsilon)
                    {
                        continue;
                    }

                    var direction = normalize(p0 - p1);
                    var lambda    = C * direction;

                    positions[j + 0] -= invMass0 / (invMass0 + invMass1) * lambda;
                    positions[j + 1] += invMass1 / (invMass0 + invMass1) * lambda;
                }

                // project collisions
                for (var j = 0; j < jointCount; j++)
                {
                    var p = positions[j];

                    p.y          = max(p.y, minimumHeight);
                    positions[j] = p;
                }
            }

            // Set the new bone rotations
            for (var i = 0; i < boneCount; i++)
            {
                var prevDir            = boneChain[i + 1].GetPosition(stream) - boneChain[i + 0].GetPosition(stream);
                var newDir             = positions[i + 1] - positions[i];
                var currentRotation    = boneChain[i].GetRotation(stream);
                var additionalRotation = QuaternionExt.FromToRotation(prevDir, newDir);

                boneChain[i].SetRotation(stream, Quaternion.Lerp(currentRotation, additionalRotation * currentRotation, weight));
            }

            boneChain[jointCount - 1].SetRotation(stream, tipTarget.GetRotation(stream));

            positions.Dispose();
            tangents.Dispose();
            normals.Dispose();
        }
Exemplo n.º 13
0
        /// <summary>
        /// Called every frame so the driver can process input and
        /// update the actor controller.
        /// </summary>
        protected virtual void Update()
        {
            // Ensure we have everything we need
            if (mActorController == null)
            {
                return;
            }
            if (mInputSource == null || !mInputSource.IsEnabled)
            {
                return;
            }

            // Initialize some variables
            Vector3    lMovement = Vector3.zero;
            Quaternion lRotation = Quaternion.identity;

            // -----------------------------------------------------------------
            // INPUT
            // -----------------------------------------------------------------

            // This is the horizontal movement of the mouse or Xbox controller's right stick
            float lYaw = mInputSource.ViewX;

            // This is the WASD buttons or Xbox controller's left stick
            Vector3 lInput = new Vector3(mInputSource.MovementX, 0f, mInputSource.MovementY);

            // -----------------------------------------------------------------
            // ROTATE
            // -----------------------------------------------------------------

            // If the input source says we can, rotate based on the yaw.
            if (mInputSource.IsViewingActivated)
            {
                // The input from the mouse already takes the frame rate into account. By doing
                // the multiplication here, we keep the rotation consistant across frame rates.
                lRotation = Quaternion.Euler(0f, lYaw * mDegreesPer60FPSTick, 0f);

                // Rotate our actor
                mActorController.Rotate(lRotation);
            }

            // -----------------------------------------------------------------
            // MOVE
            // -----------------------------------------------------------------

            // We get the tilt so we can add this up/down direction to the camera input. This helps
            // characters to not run off ramps since they are moving how they are facing (ie down a ramp)
            // vs. simply forward (off the ramp)
            Quaternion lTilt = QuaternionExt.FromToRotation(Vector3.up, mActorController._Transform.up);

            // Move based on WASD we add the tilt
            lMovement = lTilt * lInput * MovementSpeed * Time.deltaTime;
            mActorController.Move(lMovement);

            // -----------------------------------------------------------------
            // JUMP
            // -----------------------------------------------------------------

            // Only jump if the button is pressed and we're on the ground
            if (mInputSource.IsJustPressed("Jump"))
            {
                if (mActorController.State.IsGrounded)
                {
                    mActorController.AddImpulse(mActorController._Transform.up * JumpForce);
                }
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Called every frame so the driver can process input and
        /// update the actor controller.
        /// </summary>
        protected override void Update()
        {
            if (!_IsEnabled)
            {
                return;
            }
            if (mAnimator == null)
            {
                return;
            }
            if (mActorController == null)
            {
                return;
            }
            if (mInputSource == null || !mInputSource.IsEnabled)
            {
                return;
            }

            float lDeltaTime = TimeManager.SmoothedDeltaTime;

            Vector3    lMovement = Vector3.zero;
            Quaternion lRotation = Quaternion.identity;
            Vector3    lInput    = new Vector3(mInputSource.MovementX, 0f, mInputSource.MovementY);

            // Convert the input to be relative to the camera
            Vector3 lCameraBasedInput = lInput;

            if (CameraTransform != null)
            {
                lCameraBasedInput = CameraTransform.rotation * lInput;
            }

            // If we're in the middle of the jump, move towards the wall and rotate if needed
            if (mIsInJumpToWall)
            {
                Vector3 lToPoint = mJumpToWallPoint - transform.position;

                // Increment our timer
                mJumpToWallElapsedTime = mJumpToWallElapsedTime + Time.deltaTime;

                // If we're close to the target or the time has elapsed, stop
                if (lToPoint.magnitude < JumpToWallArrivalDistance ||
                    (JumpToWallTimeout > 0f && mJumpToWallElapsedTime > JumpToWallTimeout))
                {
                    mIsInJumpToWall        = false;
                    mJumpToWallPoint       = Vector3.zero;
                    mJumpToWallNormal      = Vector3.zero;
                    mJumpToWallElapsedTime = 0f;

                    mActorController.OrientToGroundSpeed = mSavedOrientToGroundSpeed;
                    mActorController.SetTargetGroundNormal(Vector3.zero);

                    // Reenable gravity once we're on
                    mActorController.IsGravityEnabled = true;
                }
                else
                {
                    mActorController.SetTargetGroundNormal(mJumpToWallNormal);

                    lMovement = lToPoint.normalized * Mathf.Min(JumpToWallSpeed * lDeltaTime, lToPoint.magnitude);
                    mActorController.Move(lMovement);

                    // Don't let gravity pull us down as we're trying to head to the target
                    mActorController.IsGravityEnabled = false;
                }
            }
            // Move like normal
            else
            {
                // Rotate based on the input (and root motion if there is any)
                Quaternion lUserRotation = Quaternion.identity;
                if (mInputSource.IsViewingActivated)
                {
                    float lYaw = mInputSource.ViewX;
                    lUserRotation = Quaternion.Euler(0f, lYaw * mDegreesPer60FPSTick, 0f);
                }

                lRotation = mRootMotionRotation * lUserRotation;
                mActorController.Rotate(lRotation);

                // We do the tilt so we can add this up/down direction to the camera input. This helps
                // characters to not run off ramps since they are moving how they are facing (ie down a ramp)
                // vs. simply forward (off the ramp)
                Quaternion lTilt = QuaternionExt.FromToRotation(Vector3.up, mActorController._Transform.up);

                // Move based on WASD (relative to the camera), we add the tilt
                lMovement = lTilt * lCameraBasedInput * _MovementSpeed * lDeltaTime;
                if (mRootMotionMovement.sqrMagnitude > 0f)
                {
                    lMovement = mRootMotionMovement;
                }

                mActorController.Move(lMovement);
            }

            // Tell the animator what to do next
            SetAnimatorProperties(lCameraBasedInput, lMovement, lRotation);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Converts the nav mesh agent data into psuedo-input that the motion controller
        /// will use to drive animations.
        /// </summary>
        protected void SimulateInput()
        {
            float lDeltaTime = TimeManager.SmoothedDeltaTime;

            // Direction we need to travel in
            Vector3 lDirection = mWaypointVector;

            lDirection.y = lDirection.y - _PathHeight;
            lDirection.Normalize();

            // Determine our view
            Vector3 lVerticalDirection = Vector3.Project(lDirection, _Transform.up);
            Vector3 lLateralDirection  = lDirection - lVerticalDirection;

            mInputFromAvatarAngle = Vector3Ext.SignedAngle(_Transform.forward, lLateralDirection);

            // Determine how much we simulate the view x. We temper it to make it smooth
            float lYawAngleAbs = Mathf.Min(Mathf.Abs(mInputFromAvatarAngle * lDeltaTime), mViewSpeedPer60FPSTick * lDeltaTime);

            if (lYawAngleAbs < EPSILON)
            {
                lYawAngleAbs = 0f;
            }

            mViewX = Mathf.Sign(mInputFromAvatarAngle) * lYawAngleAbs;

            // Determine our movement
            if (mTargetDistance > _StopDistance)
            {
                // Calculate our own slowing
                float lRelativeMoveSpeed = _NormalizedSpeed;
                if (mIsInSlowDistance && _SlowFactor > 0f)
                {
                    float lSlowPercent = (mTargetDistance - _StopDistance) / (_SlowDistance - _StopDistance);
                    lRelativeMoveSpeed = ((1f - _SlowFactor) * lSlowPercent) + _SlowFactor;
                }

                // TRT 4/5/2016: Force the slow distance as an absolute value
                if (mIsInSlowDistance && _SlowFactor > 0f)
                {
                    lRelativeMoveSpeed = _SlowFactor;
                }

                mMovementY = 1f * lRelativeMoveSpeed;

                mMotionController.TargetNormalizedSpeed = lRelativeMoveSpeed;
            }

            // Grab extra input information if we can
            if (mMotionController._CameraTransform == null)
            {
                mInputFromCameraAngle = mInputFromAvatarAngle;
            }
            else
            {
                Vector3 lInputForward = new Vector3(mMovementX, 0f, mMovementY);

                // We do the inverse tilt so we calculate the rotation in "natural up" space vs. "actor up" space.
                Quaternion lInvTilt = QuaternionExt.FromToRotation(_Transform.up, Vector3.up);

                // Camera forward in "natural up"
                Vector3 lCameraForward = lInvTilt * mMotionController._CameraTransform.forward;

                // Create a quaternion that gets us from our world-forward to our camera direction.
                Quaternion lToCamera = Quaternion.LookRotation(lCameraForward, lInvTilt * _Transform.up);

                // Transform joystick from world space to camera space. Now the input is relative
                // to how the camera is facing.
                Vector3 lMoveDirection = lToCamera * lInputForward;
                mInputFromCameraAngle = NumberHelper.GetHorizontalAngle(lCameraForward, lMoveDirection);
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Called every frame so the driver can process input and
        /// update the actor controller.
        /// </summary>
        protected virtual void Update()
        {
            // Ensure we have everything we need
            if (mActorController == null)
            {
                return;
            }
            if (mInputSource == null || !mInputSource.IsEnabled)
            {
                return;
            }

            // Initialize some variables
            Vector3    lMovement = Vector3.zero;
            Quaternion lRotation = Quaternion.identity;

            // -----------------------------------------------------------------
            // INPUT
            // -----------------------------------------------------------------

            // This is the horizontal movement of the mouse or Xbox controller's right stick
            //float lYaw = mInputSource.ViewX;

            // This is the WASD buttons or Xbox controller's left stick
            Vector3 lInput = new Vector3(mInputSource.MovementX, 0f, mInputSource.MovementY);

            // -----------------------------------------------------------------
            // ROTATE
            // -----------------------------------------------------------------

            // Set the target based on the input. This works because we're looking down
            // the world's z-axis.
            if (lInput.x < 0f)
            {
                mTargetForward = Vector3.left;
            }
            else if (lInput.x > 0f)
            {
                mTargetForward = Vector3.right;
            }

            // If we have a target forward start rotating towards it and ignore input
            if (mTargetForward.sqrMagnitude > 0f)
            {
                // Determine how much we need to rotate to get to the target
                float lTargetAngle = Vector3Ext.SignedAngle(mActorController.Yaw.Forward(), mTargetForward);

                // If there is no difference, we can turn off the target
                if (lTargetAngle == 0f)
                {
                    mTargetForward = Vector3.zero;
                }
                else
                {
                    // Grab the actual rotation angle based on our speed. However, make sure we don't overshoot the
                    // angle. So, we do this logic to truncate it if we're only a tiny bit off.
                    float lRotationAngle = Mathf.Sign(lTargetAngle) * Mathf.Min(RotationSpeed * Time.deltaTime, Mathf.Abs(lTargetAngle));

                    // Since the rotate function deals with the actor's yaw, we just to a vector3.up (it's
                    // relative to the actor regardless of his orientation/tilt
                    lRotation = Quaternion.AngleAxis(lRotationAngle, Vector3.up);

                    // Rotate.
                    mActorController.Rotate(lRotation);
                }
            }

            // -----------------------------------------------------------------
            // MOVE
            // -----------------------------------------------------------------

            // We get the tilt so we can add this up/down direction to the camera input. This helps
            // characters to not run off ramps since they are moving how they are facing (ie down a ramp)
            // vs. simply forward (off the ramp)
            Quaternion lTilt = QuaternionExt.FromToRotation(Vector3.up, mActorController._Transform.up);

            // Move based on WASD we add the tilt
            lMovement = lTilt * lInput * MovementSpeed * Time.deltaTime;
            mActorController.Move(lMovement);

            // -----------------------------------------------------------------
            // JUMP
            // -----------------------------------------------------------------

            // Only jump if the button is pressed and we're on the ground
            if (mInputSource.IsJustPressed("Jump"))
            {
                if (mActorController.State.IsGrounded)
                {
                    mActorController.AddImpulse(mActorController._Transform.up * JumpForce);
                }
            }
        }