Created
April 5, 2020 01:53
-
-
Save hvent90/63c5f8cd9312462521d820c97cc5134d 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 System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class SphereShake : MonoBehaviour | |
{ | |
public bool gravity; | |
[Header("Shake")] | |
// When enabled, the object will shake. | |
public bool addRandomForce; | |
// The strength of force applied to the object. | |
public float forceStrength; | |
// The interval between each time the force is applied. | |
public float forceInterval = 1; | |
// The type of force applied. I personally use impulse. | |
public ForceMode forceMode; | |
// The interval between each time the object | |
// is reset to position 0, 0, 0 in local space. | |
public float reset = 1f; | |
[Header("Rotate")] | |
// When enabled, the object will rotate. | |
public bool addRandomRotation; | |
// The interval between each time the object | |
// has a new target to rate towards. | |
public float rotationFrequency = 1f; | |
// The speed at which the object rotates. | |
public float rotationSpeed = 1f; | |
// The limit in degrees in which the object will rotate. | |
// Example: rotationLimit of 180 will mean that the object will never | |
// rotate more than 180 degrees from a rotation of (0, 0, 0). | |
public float rotationLimit = 45f; | |
/** Properties used for shaking */ | |
// The rigidbody for which we use to shake by applying force. | |
private Rigidbody rb; | |
// The time when we began adding force. This is used to keep track | |
// of when the next time force should be applied. | |
private float lastAddForceTime; | |
// This is used to determine when an inverse force should | |
// be applied. Check the comments on Twitch() for more info. | |
private int forceUsageCount; | |
// The direction of the current force. | |
private Vector3 force; | |
// The time when we last reset the local position. This is | |
// used to keep track of the next time to reset the position. | |
private float lastResetTime; | |
/** Properties used for rotating */ | |
// The time when we started rotating towards a new target rotation. | |
// This is used to keep track of when the next time a new | |
// target rotation should be set. | |
private float lastRotateTime; | |
// The target rotation that the object is rotating towards. | |
private Quaternion endingRotation; | |
// Start is called before the first frame update | |
void Start() | |
{ | |
rb = gameObject.AddComponent<Rigidbody>(); | |
} | |
void Update() | |
{ | |
if (addRandomForce) | |
Twitch(); | |
if (addRandomRotation) | |
Rotate(); | |
// Shaking sphere tends to drift away from home. | |
// Occasionally reset it to (0, 0, 0) in local space. | |
Reset(); | |
} | |
// Reset the object to local position (0, 0, 0). | |
void Reset() { | |
if (Time.time - lastResetTime > reset) { | |
lastResetTime = Time.time; | |
transform.localPosition = Vector3.zero; | |
} | |
} | |
// Rotate the object towards the target rotation. | |
void Rotate() { | |
float currentTime = Time.time; | |
if (currentTime - lastRotateTime > rotationFrequency) { | |
lastRotateTime = currentTime; | |
endingRotation = NewRotation(); | |
} | |
transform.rotation = | |
Quaternion.RotateTowards( | |
transform.rotation, | |
endingRotation, rotationSpeed * Time.deltaTime); | |
} | |
// Generate a new random rotation that is | |
// within the rotationLimit. | |
Quaternion NewRotation() { | |
Vector3 angles = new Vector3( | |
Random.Range(-rotationLimit, rotationLimit), | |
Random.Range(-rotationLimit, rotationLimit), | |
Random.Range(-rotationLimit, rotationLimit) | |
); | |
return Quaternion.Euler(angles); | |
} | |
// Semi-randomly twitch the object. | |
// First, apply a force in vector N. | |
// Then, apply a force in vector -N so that the object goes back towards 0, 0, 0. | |
// Then, apply a new force in vector M. | |
// Apply a new force in vector -M. Rinse and repeat. | |
void Twitch() | |
{ | |
float currentTime = Time.time; | |
if (currentTime - lastAddForceTime < forceInterval) | |
{ | |
return; | |
} | |
lastAddForceTime = currentTime; | |
// Set gravity | |
rb.useGravity = gravity; | |
// Determine whether to create a new vectorized force | |
bool changeForce = forceUsageCount % 2 == 0; | |
if (changeForce) | |
{ | |
// Stop the orb's current velocity vector | |
rb.AddRelativeForce(-force, forceMode); | |
// Generate a new vectorized force | |
force = NewForce(); | |
} else { | |
// Go in opposite direction | |
rb.velocity = Vector3.zero; | |
force *= -1f; | |
} | |
rb.AddRelativeForce(force, forceMode); | |
forceUsageCount++; | |
} | |
Vector3 NewForce() | |
{ | |
return new Vector3(Random.value * forceStrength, Random.value * forceStrength, Random.value * forceStrength); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment