From 92ec0ff4c296eec1d0904cb7c27629fb40adf312 Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 2 Jul 2022 20:23:28 +0800 Subject: + PhysicsHelper --- JamHelper/Assets/JamHelper/JamUtils/Physics.meta | 8 ++ .../JamHelper/JamUtils/Physics/PhysicsHelper.cs | 145 +++++++++++++++++++++ .../JamUtils/Physics/PhysicsHelper.cs.meta | 11 ++ 3 files changed, 164 insertions(+) create mode 100644 JamHelper/Assets/JamHelper/JamUtils/Physics.meta create mode 100644 JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs create mode 100644 JamHelper/Assets/JamHelper/JamUtils/Physics/PhysicsHelper.cs.meta 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; + + /// + /// 施加一定大小的力,使速度达到targetVelocity + /// + /// + /// + /// +#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; + } + } + + /// + /// 施加一定大小的力矩,使角速度达到目标值 + /// + /// + /// + /// + /// +#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: -- cgit v1.1-26-g67d0