Last active
October 21, 2022 23:49
-
-
Save LordNed/cf9c87477b548be3af37 to your computer and use it in GitHub Desktop.
A quick example of creating a gear or object that can spin with mouse cursor. Expects object to rotate around its Forward vector.
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; | |
public class GearRotator : MonoBehaviour | |
{ | |
[SerializeField] private float m_radiusThreshold = 4f; | |
private float m_startingAngle; | |
private bool m_isBeingRotated; | |
private void OnDrawGizmos() | |
{ | |
Gizmos.DrawLine(transform.position, transform.position + (transform.right * 2f)); | |
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one); | |
Gizmos.DrawWireCube(Vector3.zero, new Vector3(m_radiusThreshold, m_radiusThreshold, 0f)); | |
} | |
private void Update() | |
{ | |
if (Input.GetMouseButtonUp(0)) | |
{ | |
m_isBeingRotated = false; | |
} | |
if (Input.GetMouseButton(0)) | |
{ | |
// Create a Ray using the mouse's position into the world. | |
Ray mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition); | |
// Construct a plane using our current point. This could probably be cached | |
// on first frame of GetMouseButton but meh. | |
Plane plane = new Plane(transform.forward, transform.position); | |
float intersectDist; | |
bool bIntersected = plane.Raycast(mouseRay, out intersectDist); | |
// Calculate an intersection point by seeing how far awa from our mouseRay origin | |
// the plane lies. | |
Vector3 intersectPoint = mouseRay.origin + (mouseRay.direction * intersectDist); | |
// When they first press the mouse, check if they're within range. If they are, mark us as | |
// being rotated, otherwise, we ignore it. | |
if (Input.GetMouseButtonDown(0)) | |
{ | |
// Early out if this intersection point is too far away from our gear. | |
if (Vector3.Distance(transform.position, intersectPoint) > m_radiusThreshold) | |
return; | |
m_isBeingRotated = true; | |
} | |
// Draw a green line to our mouse so we know where it thinks the intersection is. | |
Debug.DrawLine(transform.position, intersectPoint, Color.green); | |
// Early out if we're not currently being rotated. | |
if (!m_isBeingRotated || !bIntersected) | |
return; | |
// Get a angle between the intersect point and us. | |
float deltaAngleDegrees = PointPairToBearingDegrees(intersectPoint); | |
// Store the angle if the mouse was just pressed so we can subtract it. | |
// This lets us know the delta on each frame (in degrees), allowing us to | |
// smoothly rotate from current position instead of snapping. | |
if(Input.GetMouseButtonDown(0)) | |
{ | |
m_startingAngle = deltaAngleDegrees; | |
Debug.Log("Set Starting Angle: " + m_startingAngle); | |
} | |
float deltaAngle = deltaAngleDegrees - m_startingAngle; | |
Debug.Log("deltaAngle: " + deltaAngle); | |
// We use Vector3.forward here and not transform.forward, otehrwise we add weird off-axis | |
// rotations and it breaks everything. Quaternions! | |
Quaternion additiveRot = Quaternion.AngleAxis(deltaAngle, Vector3.forward); | |
// Finally add the rotation. | |
transform.rotation = transform.rotation * additiveRot; | |
} | |
} | |
private float PointPairToBearingDegrees(Vector3 endPoint) | |
{ | |
// Convert this into local space so we can always use the same pair of coordinates, regardless of world orientation of the gear. | |
// endPointLocal is now also already a direction, since it's in local space, so we can use it directly. | |
Vector3 endPointLocal = transform.InverseTransformPoint(endPoint); | |
float dirRadians = Mathf.Atan2(endPointLocal.y, endPointLocal.x); // Atan2 = Direction -> Radians | |
float dirDegrees = dirRadians * (180.0f / Mathf.PI); // To degrees - this returns -180/180. | |
// dirDegrees = (dirDegrees > 0.0f ? dirDegrees : (360.0f + dirDegrees)); // Correct for 0-360 if desired (unneeded in this case) | |
return dirDegrees; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment