Created
January 20, 2019 16:54
-
-
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; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
omg