Instantly share code, notes, and snippets.

# ditzel/PhysicsHelper.cs

Created January 20, 2019 16:54
Show Gist options
• Save ditzel/1f207c838f0023fcbd34c5c67955fd25 to your computer and use it in GitHub Desktop.
Unity Helper for Physic Functions
This file contains 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 UnityEngine; namespace Ditzelgames { public static class PhysicsHelper { public static void ApplyForceToReachVelocity(Rigidbody rigidbody, Vector3 velocity, float force = 1, ForceMode mode = ForceMode.Force) { if (force == 0 || velocity.magnitude == 0) return; velocity = velocity + velocity.normalized * 0.2f * rigidbody.drag; //force = 1 => need 1 s to reach velocity (if mass is 1) => force can be max 1 / Time.fixedDeltaTime force = Mathf.Clamp(force, -rigidbody.mass / Time.fixedDeltaTime, rigidbody.mass / Time.fixedDeltaTime); //dot product is a projection from rhs to lhs with a length of result / lhs.magnitude https://www.youtube.com/watch?v=h0NJK4mEIJU if (rigidbody.velocity.magnitude == 0) { rigidbody.AddForce(velocity * force, mode); } else { var velocityProjectedToTarget = (velocity.normalized * Vector3.Dot(velocity, rigidbody.velocity) / velocity.magnitude); rigidbody.AddForce((velocity - velocityProjectedToTarget) * force, mode); } } public static void ApplyTorqueToReachRPS(Rigidbody rigidbody, Quaternion rotation, float rps, float force = 1) { var radPerSecond = rps * 2 * Mathf.PI + rigidbody.angularDrag * 20; float angleInDegrees; Vector3 rotationAxis; rotation.ToAngleAxis(out angleInDegrees, out rotationAxis); if (force == 0 || rotationAxis == Vector3.zero) return; rigidbody.maxAngularVelocity = Mathf.Max(rigidbody.maxAngularVelocity, radPerSecond); force = Mathf.Clamp(force, -rigidbody.mass * 2 * Mathf.PI / Time.fixedDeltaTime, rigidbody.mass * 2 * Mathf.PI / Time.fixedDeltaTime); var currentSpeed = Vector3.Project(rigidbody.angularVelocity, rotationAxis).magnitude; rigidbody.AddTorque(rotationAxis * (radPerSecond - currentSpeed) * force); } public static Vector3 QuaternionToAngularVelocity(Quaternion rotation) { float angleInDegrees; Vector3 rotationAxis; rotation.ToAngleAxis(out angleInDegrees, out rotationAxis); return rotationAxis * angleInDegrees * Mathf.Deg2Rad; } public static Quaternion AngularVelocityToQuaternion(Vector3 angularVelocity) { var rotationAxis = (angularVelocity * Mathf.Rad2Deg).normalized; float angleInDegrees = (angularVelocity * Mathf.Rad2Deg).magnitude; return Quaternion.AngleAxis(angleInDegrees, rotationAxis); } public static Vector3 GetNormal(Vector3[] points) { //https://www.ilikebigbits.com/2015_03_04_plane_from_points.html if (points.Length < 3) return Vector3.up; var center = GetCenter(points); float xx = 0f, xy = 0f, xz = 0f, yy = 0f, yz = 0f, zz = 0f; for (int i = 0; i < points.Length; i++) { var r = points[i] - center; xx += r.x * r.x; xy += r.x * r.y; xz += r.x * r.z; yy += r.y * r.y; yz += r.y * r.z; zz += r.z * r.z; } var det_x = yy * zz - yz * yz; var det_y = xx * zz - xz * xz; var det_z = xx * yy - xy * xy; if (det_x > det_y && det_x > det_z) return new Vector3(det_x, xz * yz - xy * zz, xy * yz - xz * yy).normalized; if (det_y > det_z) return new Vector3(xz * yz - xy * zz, det_y, xy * xz - yz * xx).normalized; else return new Vector3(xy * yz - xz * yy, xy * xz - yz * xx, det_z).normalized; } public static Vector3 GetCenter(Vector3[] points) { var center = Vector3.zero; for (int i = 0; i < points.Length; i++) center += points[i] / points.Length; return center; } } }

omg