// 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; } }
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; }
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; } }
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); }
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); } }
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; }
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; }
// 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; }
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; } }
/* * 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); } }