Skip to content

Instantly share code, notes, and snippets.

@panckreous
Forked from ditzel/PhysicsHelper.cs
Created October 14, 2019 06:40
Show Gist options
  • Save panckreous/5714d5ac270e776829b0ef7d4de5cec9 to your computer and use it in GitHub Desktop.
Save panckreous/5714d5ac270e776829b0ef7d4de5cec9 to your computer and use it in GitHub Desktop.
Unity Helper for Physic Functions
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