aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--JamHelper/Assets/JamHelper/JamUtils/Physics.meta8
-rw-r--r--JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs145
-rw-r--r--JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs.meta11
3 files changed, 164 insertions, 0 deletions
diff --git a/JamHelper/Assets/JamHelper/JamUtils/Physics.meta b/JamHelper/Assets/JamHelper/JamUtils/Physics.meta
new file mode 100644
index 0000000..d5b0db8
--- /dev/null
+++ b/JamHelper/Assets/JamHelper/JamUtils/Physics.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ee37b26dd339f8746a27ed8efe0e1f1f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs b/JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs
new file mode 100644
index 0000000..7cd1e5a
--- /dev/null
+++ b/JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs
@@ -0,0 +1,145 @@
+//#define PHYSICS_EXTENSION
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+// 参考
+// * https://www.youtube.com/watch?v=BNiAt0HnC5M&ab_channel=DitzelGames
+
+namespace JamUtils.Physics
+{
+
+ public static class PhysicsHelper
+ {
+ public const int VERSION_CODE = 1;
+
+ /// <summary>
+ /// 施加一定大小的力,使速度达到targetVelocity
+ /// </summary>
+ /// <param name="rigidbody"></param>
+ /// <param name="velocity"></param>
+ /// <param name="mode"></param>
+#if PHYSICS_EXTENSION
+ public static Vector3 AddForceToReachVelocity(this Rigidbody rigidbody, Vector3 targetVelocity, float force = 1, ForceMode mode = ForceMode.Force)
+#else
+ public static Vector3 AddForceToReachVelocity(Rigidbody rigidbody, Vector3 targetVelocity, float force = 1, ForceMode mode = ForceMode.Force)
+#endif
+ {
+ if (targetVelocity.magnitude == 0)
+ {
+ return Vector3.zero;
+ }
+
+ Vector3 velocity = targetVelocity + targetVelocity.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);
+ return velocity * force;
+ }
+ else
+ {
+ var velocityProjectedToTarget = (velocity.normalized * Vector3.Dot(velocity, rigidbody.velocity) / velocity.magnitude);
+ rigidbody.AddForce((velocity - velocityProjectedToTarget) * force, mode);
+ return (velocity - velocityProjectedToTarget) * force;
+ }
+ }
+
+ /// <summary>
+ /// 施加一定大小的力矩,使角速度达到目标值
+ /// </summary>
+ /// <param name="rigidbody"></param>
+ /// <param name="rotation"></param>
+ /// <param name="rps"></param>
+ /// <param name="force"></param>
+#if PHYSICS_EXTENSION
+ public static void ApplyTorqueToReachRPS(this Rigidbody rigidbody, Quaternion rotation, float rps, float force = 1)
+#else
+ public static void ApplyTorqueToReachRPS(Rigidbody rigidbody, Quaternion rotation, float rps, float force = 1)
+#endif
+ {
+ 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;
+ }
+
+
+ }
+}
diff --git a/JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs.meta b/JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs.meta
new file mode 100644
index 0000000..be3b5e6
--- /dev/null
+++ b/JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 074e0715a475fe84a9a2de82d2f7f3e0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: