//---------------------------------------------- // Flip Web Apps: Beautiful Transitions // Copyright © 2016 Flip Web Apps / Mark Hewitt // // Please direct any bugs/comments/suggestions to http://www.flipwebapps.com // // The copyright owner grants to the end user a non-exclusive, worldwide, and perpetual license to this Asset // to integrate only as incorporated and embedded components of electronic games and interactive media and // distribute such electronic game and interactive media. End user may modify Assets. End user may otherwise // not reproduce, distribute, sublicense, rent, lease or lend the Assets. It is emphasized that the end // user shall not be entitled to distribute or transfer in any way (including, without, limitation by way of // sublicense) the Assets in any other way than as integrated components of electronic games and interactive media. // The above copyright notice and this permission notice must not be removed from any files. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. //---------------------------------------------- using System.Collections; using System.Collections.Generic; using UnityEngine; namespace BeautifulTransitions.Scripts.Shake { /// /// Shake helper functions that you can use for triggering and running your own shakes. /// /// Note: this is a work in progress. Improvements are consider movement by other scripts. improved shake algorithm. [HelpURL("http://www.flipwebapps.com/beautiful-transitions/shake/")] public class ShakeHelper { static readonly List ActiveShakes = new List(2); /// /// Shake the specified transform using the passed duration, range and decay start. /// /// Note: this will use the caller object to start a coroutine as when /// deactivating a display item we need to wait for the animation to /// complete before deactivating the gameobject. /// /// A MonoBehaviour used to start the shake coroutine. If calling from your own component you can usually just pass 'this'. /// The transform that you want to shake. /// The duration to shake the gameobject for. /// The shake movement range from the origin. Set any dimension to 0 to stop movement along that axis. /// The offset relative to duration after which to start decaying (slowing down) the movement in the range 0 to 1. public static void Shake(MonoBehaviour caller, Transform transform, float duration, Vector3 range, float decayStart = 1f) { caller.StartCoroutine(ShakeCoroutine(transform, duration, range, decayStart)); } /// /// Coroutine called to shake the specified transform. /// /// /// /// /// /// static IEnumerator ShakeCoroutine(Transform transform, float duration, Vector3 range, float decayStart = 1f) { // if we run multiple shakes then we can record the wrong originalPositino. For now just disallow multiple shakes on the same object if (!ActiveShakes.Contains(transform.GetInstanceID())) { ActiveShakes.Add(transform.GetInstanceID()); var originalPosition = transform.localPosition; var randomAngle = Random.Range(0, 361); var decay = 0f; var decayFactor = Mathf.Approximately(decayStart, 1) ? 0 : 1/(1 - decayStart); var elapsedTime = 0f; while (elapsedTime < duration) { if (transform.gameObject != null) { var percentComplete = elapsedTime/duration; if (percentComplete >= decayStart) { decay = 1 - decayFactor + decayFactor*percentComplete; // decay = Mathf.Clamp(v, 0.0f, 1.0f); // should be no need to clamp due to above conditional test! } // perlin movement //var smoothRandom = SmoothRandom.GetVector3(speed); //var target = originalPosition + Vector3.Scale(smoothRandom, range * decay); //speed *= -1; //range *= -1; //= new Vector3(range.x * -1, range.y * -1, range.z * -1); // angle based randomAngle += 180 + Random.Range(-60, 60); // mirror angle and add some varience. var sinAngle = Mathf.Sin(randomAngle); var cosAngle = Mathf.Cos(randomAngle); var offset = new Vector3(cosAngle*sinAngle*range.x, sinAngle*sinAngle*range.y, cosAngle*range.z); var target = originalPosition + (offset*(1 - decay)); transform.localPosition = target; } yield return null; elapsedTime += Time.deltaTime; } // set back to original position - TODO consider movement from other scripts. transform.localPosition = originalPosition; ActiveShakes.Remove(transform.GetInstanceID()); } } } }