예제 #1
0
        // Is the character grounded?
        private void GroundCheck()
        {
            Vector3 platformVelocityTarget = Vector3.zero;

            platformAngularVelocity = Vector3.zero;
            float stickyForceTarget = 0f;

            // Spherecasting
            hit = GetSpherecastHit();

            //normal = hit.normal;
            normal = transform.up;
            //groundDistance = r.position.y - hit.point.y;
            groundDistance = Vector3.Project(r.position - hit.point, transform.up).magnitude;

            // if not jumping...
            bool findGround = Time.time > jumpEndTime && velocityY < jumpPower * 0.5f;

            if (findGround)
            {
                bool g = onGround;
                onGround = false;

                // The distance of considering the character grounded
                float groundHeight = !g? airborneThreshold * 0.5f: airborneThreshold;

                //Vector3 horizontalVelocity = r.velocity;
                Vector3 horizontalVelocity = V3Tools.ExtractHorizontal(r.velocity, gravity, 1f);

                float velocityF = horizontalVelocity.magnitude;

                if (groundDistance < groundHeight)
                {
                    // Force the character on the ground
                    stickyForceTarget = groundStickyEffect * velocityF * groundHeight;

                    // On moving platforms
                    if (hit.rigidbody != null)
                    {
                        platformVelocityTarget  = hit.rigidbody.GetPointVelocity(hit.point);
                        platformAngularVelocity = Vector3.Project(hit.rigidbody.angularVelocity, transform.up);
                    }

                    // Flag the character grounded
                    onGround = true;
                }
            }

            // Interpolate the additive velocity of the platform the character might be standing on
            platformVelocity = Vector3.Lerp(platformVelocity, platformVelocityTarget, Time.deltaTime * platformFriction);

            stickyForce = stickyForceTarget;            //Mathf.Lerp(stickyForce, stickyForceTarget, Time.deltaTime * 5f);

            // remember when we were last in air, for jump delay
            if (!onGround)
            {
                lastAirTime = Time.time;
            }
        }
예제 #2
0
        private void MoveFixed(Vector3 deltaPosition)
        {
            // Process horizontal wall-running
            WallRun();

            Vector3 velocity = fixedDeltaTime > 0f? deltaPosition / fixedDeltaTime: Vector3.zero;

            // Add velocity of the rigidbody the character is standing on
            if (!fullRootMotion)
            {
                velocity += V3Tools.ExtractHorizontal(platformVelocity, gravity, 1f);

                if (onGround)
                {
                    // Rotate velocity to ground tangent
                    if (velocityToGroundTangentWeight > 0f)
                    {
                        Quaternion rotation = Quaternion.FromToRotation(transform.up, normal);
                        velocity = Quaternion.Lerp(Quaternion.identity, rotation, velocityToGroundTangentWeight) * velocity;
                    }
                }
                else
                {
                    // Air move
                    //Vector3 airMove = new Vector3 (userControl.state.move.x * airSpeed, 0f, userControl.state.move.z * airSpeed);
                    Vector3 airMove = V3Tools.ExtractHorizontal(userControl.state.move * airSpeed, gravity, 1f);
                    velocity = Vector3.Lerp(r.velocity, airMove, Time.deltaTime * airControl);
                }

                if (onGround && Time.time > jumpEndTime)
                {
                    r.velocity = r.velocity - transform.up * stickyForce * Time.deltaTime;
                }

                // Vertical velocity
                Vector3 verticalVelocity   = V3Tools.ExtractVertical(r.velocity, gravity, 1f);
                Vector3 horizontalVelocity = V3Tools.ExtractHorizontal(velocity, gravity, 1f);

                if (onGround)
                {
                    if (Vector3.Dot(verticalVelocity, gravity) < 0f)
                    {
                        verticalVelocity = Vector3.ClampMagnitude(verticalVelocity, maxVerticalVelocityOnGround);
                    }
                }

                r.velocity = horizontalVelocity + verticalVelocity;
            }
            else
            {
                r.velocity = velocity;
            }

            // Dampering forward speed on the slopes (Not working since Unity 2017.2)
            //float slopeDamper = !onGround? 1f: GetSlopeDamper(-deltaPosition / Time.deltaTime, normal);
            //forwardMlp = Mathf.Lerp(forwardMlp, slopeDamper, Time.deltaTime * 5f);
            forwardMlp = 1f;
        }
예제 #3
0
            public override void ApplyOffsets(float scale)
            {
                headPosition += headPositionOffset;

                float mHH = minHeadHeight * scale;

                Vector3 rootUp = rootRotation * Vector3.up;

                if (rootUp == Vector3.up)
                {
                    headPosition.y = Math.Max(rootPosition.y + mHH, headPosition.y);
                }
                else
                {
                    Vector3 toHead = headPosition - rootPosition;
                    Vector3 hor    = V3Tools.ExtractHorizontal(toHead, rootUp, 1f);
                    Vector3 ver    = toHead - hor;
                    float   dot    = Vector3.Dot(ver, rootUp);
                    if (dot > 0f)
                    {
                        if (ver.magnitude < mHH)
                        {
                            ver = ver.normalized * mHH;
                        }
                    }
                    else
                    {
                        ver = -ver.normalized * mHH;
                    }

                    headPosition = rootPosition + hor + ver;
                }

                headRotation = headRotationOffset * headRotation;

                headDeltaPosition   = headPosition - head.solverPosition;
                pelvisDeltaRotation = QuaTools.FromToRotation(pelvis.solverRotation, headRotation * pelvisRelativeRotation);

                if (pelvisRotationWeight <= 0f)
                {
                    anchorRotation = headRotation * anchorRelativeToHead;
                }
                else if (pelvisRotationWeight > 0f && pelvisRotationWeight < 1f)
                {
                    anchorRotation = Quaternion.Lerp(headRotation * anchorRelativeToHead, pelvisRotation * anchorRelativeToPelvis, pelvisRotationWeight);
                }
                else if (pelvisRotationWeight >= 1f)
                {
                    anchorRotation = pelvisRotation * anchorRelativeToPelvis;
                }
            }
예제 #4
0
        private void MoveFixed(Vector3 deltaPosition)
        {
            // Process horizontal wall-running
            WallRun();

            Vector3 velocity = deltaPosition / Time.deltaTime;

            // Add velocity of the rigidbody the character is standing on
            velocity += V3Tools.ExtractHorizontal(platformVelocity, gravity, 1f);

            if (onGround)
            {
                // Rotate velocity to ground tangent
                if (velocityToGroundTangentWeight > 0f)
                {
                    Quaternion rotation = Quaternion.FromToRotation(transform.up, normal);
                    velocity = Quaternion.Lerp(Quaternion.identity, rotation, velocityToGroundTangentWeight) * velocity;
                }
            }
            else
            {
                // Air move
                Vector3 airMove = V3Tools.ExtractHorizontal(blackboard.input * airSpeed, gravity, 1f);
                velocity = Vector3.Lerp(_rigidbody.velocity, airMove, Time.deltaTime * airControl);
            }

            if (onGround && Time.time > jumpEndTime)
            {
                _rigidbody.velocity = _rigidbody.velocity - transform.up * stickyForce * Time.deltaTime;
            }

            // Vertical velocity
            Vector3 verticalVelocity   = V3Tools.ExtractVertical(_rigidbody.velocity, gravity, 1f);
            Vector3 horizontalVelocity = V3Tools.ExtractHorizontal(velocity, gravity, 1f);

            if (onGround)
            {
                if (Vector3.Dot(verticalVelocity, gravity) < 0f)
                {
                    verticalVelocity = Vector3.ClampMagnitude(verticalVelocity, maxVerticalVelocityOnGround);
                }
            }

            //rb.velocity = horizontalVelocity + verticalVelocity;

            // Dampering forward speed on the slopes
            float slopeDamper = !onGround ? 1f : GetSlopeDamper(-deltaPosition / Time.deltaTime, normal);

            forwardMlp = Mathf.Lerp(forwardMlp, slopeDamper, Time.deltaTime * 5f);
        }
		// Processing horizontal wall running
		private void WallRun() {
			bool canWallRun = CanWallRun();

			// Remove flickering in and out of wall-running
			if (wallRunWeight > 0f && !canWallRun) wallRunEndTime = Time.time;
			if (Time.time < wallRunEndTime + 0.5f) canWallRun = false;

			wallRunWeight = Mathf.MoveTowards(wallRunWeight, (canWallRun? 1f: 0f), Time.deltaTime * wallRunWeightSpeed);
			
			if (wallRunWeight <= 0f) {
				// Reset
				if (lastWallRunWeight > 0f) {
					Vector3 frw = V3Tools.ExtractHorizontal(transform.forward, gravity, 1f);
					transform.rotation = Quaternion.LookRotation(frw, -gravity);
					wallNormal = -gravity.normalized;
				}
			}

			lastWallRunWeight = wallRunWeight;
			
			if (wallRunWeight <= 0f) return;

			// Make sure the character won't fall down
			if (onGround && velocityY < 0f) r.velocity = V3Tools.ExtractHorizontal(r.velocity, gravity, 1f);
			
			// transform.forward flattened
			Vector3 f = V3Tools.ExtractHorizontal(transform.forward, gravity, 1f);

			// Raycasting to find a walkable wall
			RaycastHit velocityHit = new RaycastHit();
			velocityHit.normal = -gravity.normalized;
			Physics.Raycast(onGround? transform.position: capsule.bounds.center, f, out velocityHit, 3f, wallRunLayers);
			
			// Finding the normal to rotate to
			wallNormal = Vector3.Lerp(wallNormal, velocityHit.normal, Time.deltaTime * wallRunRotationSpeed);

			// Clamping wall normal to max rotation angle
			wallNormal = Vector3.RotateTowards(-gravity.normalized, wallNormal, wallRunMaxRotationAngle * Mathf.Deg2Rad, 0f);

			// Get transform.forward ortho-normalized to the wall normal
			Vector3 fW = transform.forward;
			Vector3 nW = wallNormal;
			Vector3.OrthoNormalize(ref nW, ref fW);

			// Rotate from upright to wall normal
			transform.rotation = Quaternion.Slerp(Quaternion.LookRotation(f, -gravity), Quaternion.LookRotation(fW, wallNormal), wallRunWeight);
		}
예제 #6
0
        private void FixedUpdate()
        {
            // Add torque to the Rigidbody to make it follow the rotation target
            Vector3 angularAcc = PhysXTools.GetAngularAcceleration(_rigidbody.rotation, rotationTarget.rotation);

            _rigidbody.AddTorque(angularAcc * torque);

            // Add snowboard-like skid drag
            if (_isGrounded)
            {
                Vector3 velocity = _rigidbody.velocity;
                Vector3 skid     = V3Tools.ExtractHorizontal(velocity, _rigidbody.rotation * Vector3.up, 1f);
                skid = Vector3.Project(velocity, _rigidbody.rotation * Vector3.right);

                _rigidbody.velocity = velocity - Vector3.ClampMagnitude(skid * skidDrag * Time.deltaTime, skid.magnitude);
            }
        }
예제 #7
0
            public override void ApplyOffsets()
            {
                headPosition += headPositionOffset;

                Vector3 rootUp = rootRotation * Vector3.up;

                if (rootUp == Vector3.up)
                {
                    headPosition.y = Math.Max(rootPosition.y + minHeadHeight, headPosition.y);
                }
                else
                {
                    Vector3 toHead = headPosition - rootPosition;
                    Vector3 hor    = V3Tools.ExtractHorizontal(toHead, rootUp, 1f);
                    Vector3 ver    = toHead - hor;
                    float   dot    = Vector3.Dot(ver, rootUp);
                    if (dot > 0f)
                    {
                        if (ver.magnitude < minHeadHeight)
                        {
                            ver = ver.normalized * minHeadHeight;
                        }
                    }
                    else
                    {
                        ver = -ver.normalized * minHeadHeight;
                    }

                    headPosition = rootPosition + hor + ver;
                }

                headRotation = headRotationOffset * headRotation;

                headDeltaPosition   = headPosition - head.solverPosition;
                pelvisDeltaRotation = QuaTools.FromToRotation(pelvis.solverRotation, headRotation * pelvisRelativeRotation);

                anchorRotation = headRotation * anchorRelativeToHead;
            }
예제 #8
0
            public void Update(IKSolverFullBodyBiped solver, float w, float deltaTime)
            {
                if (this.transform == null || this.relativeTo == null)
                {
                    return;
                }
                Vector3 a = this.relativeTo.InverseTransformDirection(this.transform.position - this.relativeTo.position);

                if (this.firstUpdate)
                {
                    this.lastRelativePos = a;
                    this.firstUpdate     = false;
                }
                Vector3 vector = (a - this.lastRelativePos) / deltaTime;

                this.smoothDelta = ((this.speed > 0f) ? Vector3.Lerp(this.smoothDelta, vector, deltaTime * this.speed) : vector);
                Vector3 v  = this.relativeTo.TransformDirection(this.smoothDelta);
                Vector3 a2 = V3Tools.ExtractVertical(v, solver.GetRoot().up, this.verticalWeight) + V3Tools.ExtractHorizontal(v, solver.GetRoot().up, this.horizontalWeight);

                for (int i = 0; i < this.effectorLinks.Length; i++)
                {
                    solver.GetEffector(this.effectorLinks[i].effector).positionOffset += a2 * w * this.effectorLinks[i].weight;
                }
                this.lastRelativePos = a;
            }
예제 #9
0
            // Update the Body
            public void Update(IKSolverFullBodyBiped solver, float w, float deltaTime)
            {
                if (transform == null || relativeTo == null)
                {
                    return;
                }

                // Find the relative position of the transform
                Vector3 relativePos = relativeTo.InverseTransformDirection(transform.position - relativeTo.position);

                // Initiating
                if (firstUpdate)
                {
                    lastRelativePos = relativePos;
                    firstUpdate     = false;
                }

                // Find how much the relative position has changed
                Vector3 delta = (relativePos - lastRelativePos) / deltaTime;

                // Smooth the change
                smoothDelta = speed <= 0f? delta: Vector3.Lerp(smoothDelta, delta, deltaTime * speed);

                // Convert to world space
                Vector3 worldDelta = relativeTo.TransformDirection(smoothDelta);

                // Extract horizontal and vertical offset
                Vector3 offset = V3Tools.ExtractVertical(worldDelta, solver.GetRoot().up, verticalWeight) + V3Tools.ExtractHorizontal(worldDelta, solver.GetRoot().up, horizontalWeight);

                // Apply the amplitude to the effector links
                for (int i = 0; i < effectorLinks.Length; i++)
                {
                    solver.GetEffector(effectorLinks[i].effector).positionOffset += offset * w * effectorLinks[i].weight;
                }

                lastRelativePos = relativePos;
            }
예제 #10
0
 private void PullBody()
 {
     if (this.iterations < 1)
     {
         return;
     }
     if (this.pullBodyVertical != 0f || this.pullBodyHorizontal != 0f)
     {
         Vector3 bodyOffset = this.GetBodyOffset();
         this.pullBodyOffset = V3Tools.ExtractVertical(bodyOffset, this.root.up, this.pullBodyVertical) + V3Tools.ExtractHorizontal(bodyOffset, this.root.up, this.pullBodyHorizontal);
         this.bodyEffector.positionOffset += this.pullBodyOffset;
     }
 }
예제 #11
0
        /*
         * Pulling the body with the hands
         * */
        private void PullBody()
        {
            if (iterations < 1)
            {
                return;
            }

            // Getting the body positionOffset
            if (pullBodyVertical != 0f || pullBodyHorizontal != 0f)
            {
                Vector3 offset = GetBodyOffset();

                bodyEffector.positionOffset += V3Tools.ExtractVertical(offset, root.up, pullBodyVertical) + V3Tools.ExtractHorizontal(offset, root.up, pullBodyHorizontal);
            }
        }