Skip to content

Instantly share code, notes, and snippets.

@kurtdekker
Last active January 22, 2024 06:20
Show Gist options
  • Save kurtdekker/ad051f56462f72a7e184269d9bece32f to your computer and use it in GitHub Desktop.
Save kurtdekker/ad051f56462f72a7e184269d9bece32f to your computer and use it in GitHub Desktop.
Counts revolutions of a Transform (around its +Z axis)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// @kurtdekker
//
// Counts revolutions in degrees around the +Z axis of a transform
//
// NOTE: Like all things in a discrete digital simulation, this takes samples at
// regular intervals. This means rapid rotation of the transform will introduce
// more and more error term. Don't spin your transform rapidly if this is a concern.
//
// NOTE: Transform can be oriented however you like.
// Rotation is alway measured around the local +Z axis
//
// To use:
//
// - place this on a Transform that rotates around its +Z (such as a dial)
// - read the total accumulated rotation out of TotalDegrees
public class RevolutionCounter : MonoBehaviour
{
public float TotalDegrees;
bool ready; // to ensure we've been through once
// last frame
Vector3 previousForward;
Vector3 previousRight;
void Update ()
{
// this frame
Vector3 forward = transform.forward;
Vector3 right = transform.right;
// ready or not, you haven't moved far enough that we can compute reliably.
if ((right - previousRight).magnitude < 0.01f)
{
return;
}
if (ready)
{
// in case your steering axis is changing, we split the difference
Vector3 axisOfRotation = (forward + previousForward) / 2;
// this frame
Vector3 arm1 = previousRight;
// last frame
Vector3 arm2 = right;
// take out incidentals related to axisOfRotation changing
arm1 = Vector3.ProjectOnPlane( arm1, axisOfRotation);
arm2 = Vector3.ProjectOnPlane( arm2, axisOfRotation);
Vector3 cross = Vector3.Cross( arm1, arm2);
// and this is the portion of that cross vector lying along the axis of rotation
float dot = Vector3.Dot( cross, axisOfRotation);
// cross product builds magnitude like a sine curve
float radians = Mathf.Asin( dot);
float degrees = radians * Mathf.Rad2Deg;
TotalDegrees += degrees;
}
// age the data
previousForward = forward;
previousRight = right;
ready = true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment