Last active
March 10, 2026 11:24
-
-
Save Drumsmasher17/bf59918cf9105682e8f2dd68484098b1 to your computer and use it in GitHub Desktop.
A copy of Valve's physics following logic as seen in 'The Lab'
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections; | |
| using System.Collections.Generic; | |
| using UnityEngine; | |
| public class PhysicsFollow : MonoBehaviour | |
| { | |
| public Transform follow; | |
| public Rigidbody rb; | |
| void FixedUpdate() | |
| { | |
| if (rb == null) | |
| { | |
| return; | |
| } | |
| Vector3 velocityTarget, angularTarget; | |
| bool success = GetUpdatedAttachedVelocities(follow, out velocityTarget, out angularTarget); | |
| if (success) | |
| { | |
| float maxAngularVelocityChange = MaxAngularVelocityChange; | |
| float maxVelocityChange = MaxVelocityChange; | |
| rb.velocity = Vector3.MoveTowards(rb.velocity, velocityTarget, maxVelocityChange); | |
| rb.angularVelocity = Vector3.MoveTowards(rb.angularVelocity, angularTarget, maxAngularVelocityChange); | |
| } | |
| } | |
| // Magic Numbers | |
| const float MaxVelocityChange = 10f; /// 10f | |
| const float velocityMagic = 6000f; /// 6000f | |
| const float AngularVelocityMagic = 50f; /// 50f | |
| const float MaxAngularVelocityChange = 20f; /// 20f | |
| protected bool GetUpdatedAttachedVelocities(Transform target, out Vector3 velocityTarget, out Vector3 angularTarget) | |
| { | |
| bool realNumbers = false; | |
| Vector3 positionDelta = (target.position - transform.position); | |
| velocityTarget = (positionDelta * velocityMagic * Time.deltaTime); | |
| if (float.IsNaN(velocityTarget.x) == false && float.IsInfinity(velocityTarget.x) == false) | |
| { | |
| realNumbers = true; | |
| } | |
| else | |
| { | |
| velocityTarget = Vector3.zero; | |
| } | |
| Quaternion targetItemRotation = target.rotation; | |
| Quaternion rotationDelta = targetItemRotation * Quaternion.Inverse(transform.rotation); | |
| float angle; | |
| Vector3 axis; | |
| rotationDelta.ToAngleAxis(out angle, out axis); | |
| if (angle > 180) | |
| { | |
| angle -= 360; | |
| } | |
| if (angle != 0 && float.IsNaN(axis.x) == false && float.IsInfinity(axis.x) == false) | |
| { | |
| angularTarget = angle * axis * AngularVelocityMagic * Time.deltaTime; | |
| realNumbers &= true; | |
| } | |
| else | |
| { | |
| angularTarget = Vector3.zero; | |
| } | |
| return realNumbers; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment