Last active
March 27, 2025 08:08
-
-
Save pppoe252110/b57bdb1f51934f1711b552124525db15 to your computer and use it in GitHub Desktop.
This file contains hidden or 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; | |
[System.Serializable] | |
public class RotationConstraints | |
{ | |
public Vector2 x = new Vector2(-30, 30); | |
public Vector2 y = new Vector2(-30, 30); | |
public Vector2 z = new Vector2(-5, 5); | |
} | |
public class FakeBreastSpring : MonoBehaviour | |
{ | |
[Header("Spring Settings")] | |
[SerializeField] private float _springStrength = 6f; | |
[SerializeField] private float _damping = 2f; | |
[Header("Movement Sensitivity")] | |
[SerializeField] private float _positionSensitivity = 0.1f; | |
[SerializeField] private float _rotationSensitivity = 0.5f; | |
[Header("Rotation Constraints")] | |
[SerializeField] private RotationConstraints _rotationConstraints; | |
private Quaternion _initialLocalRotation; | |
private Quaternion _velocity; | |
private Vector3 _lastParentPosition; | |
private Quaternion _lastParentRotation; | |
private void Start() | |
{ | |
_lastParentPosition = transform.parent.position; | |
_lastParentRotation = transform.parent.rotation; | |
_initialLocalRotation = transform.localRotation; | |
} | |
private void Update() | |
{ | |
float deltaTime = Time.deltaTime; | |
// Calculate position-based rotation | |
Vector3 localPositionDelta = transform.InverseTransformVector(transform.parent.position - _lastParentPosition); | |
Vector3 positionRotation = new Vector3( | |
-localPositionDelta.y * _positionSensitivity * Mathf.Rad2Deg, | |
localPositionDelta.x * _positionSensitivity * Mathf.Rad2Deg, | |
0f); | |
// Calculate rotation-based rotation | |
Quaternion parentRotationDelta = transform.parent.rotation * Quaternion.Inverse(_lastParentRotation); | |
Vector3 rotationEuler = new Vector3( | |
FixAngle(parentRotationDelta.eulerAngles.x) * _rotationSensitivity, | |
FixAngle(parentRotationDelta.eulerAngles.y) * _rotationSensitivity, | |
FixAngle(parentRotationDelta.eulerAngles.z) * _rotationSensitivity); | |
// Apply both rotations | |
transform.localRotation *= Quaternion.Euler(positionRotation + rotationEuler); | |
// Spring physics | |
Quaternion targetVelocity = Quaternion.Inverse(transform.localRotation) * _initialLocalRotation; | |
// Damping | |
targetVelocity = Quaternion.Slerp(targetVelocity, Quaternion.Euler(Vector3.zero), deltaTime * _damping); | |
_velocity = Quaternion.Slerp(_velocity, targetVelocity, _springStrength * deltaTime); | |
transform.localRotation *= _velocity; | |
// Damping | |
transform.localRotation = Quaternion.Slerp(transform.localRotation, _initialLocalRotation, _damping * deltaTime); | |
// Apply constraints | |
Vector3 currentEuler = (transform.localRotation * Quaternion.Inverse(_initialLocalRotation)).eulerAngles; | |
currentEuler.x = Mathf.Clamp(FixAngle(currentEuler.x), _rotationConstraints.x.x, _rotationConstraints.x.y); | |
currentEuler.y = Mathf.Clamp(FixAngle(currentEuler.y), _rotationConstraints.y.x, _rotationConstraints.y.y); | |
currentEuler.z = Mathf.Clamp(FixAngle(currentEuler.z), _rotationConstraints.z.x, _rotationConstraints.z.y); | |
transform.localRotation = Quaternion.Euler(currentEuler) * _initialLocalRotation; | |
// Store current state for next frame | |
_lastParentPosition = transform.parent.position; | |
_lastParentRotation = transform.parent.rotation; | |
} | |
private float FixAngle(float angle) | |
{ | |
// Normalize angle to [-180, 180] range | |
angle %= 360f; | |
if (angle > 180f) angle -= 360f; | |
if (angle < -180f) angle += 360f; | |
return angle; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment