Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Coroutine and tweening framework for Unity3D

License

NotificationsYou must be signed in to change notification settings

BeauPrime/BeauRoutine

Repository files navigation

Current Version: 0.11.1
Updated 2 May 2021 |Changelog

About

BeauRoutine is a coroutine framework for Unity3D. Intended as a replacement for Unity's existing coroutine implementation, BeauRoutines are a fast, powerful, and flexible way of sequencing your logic. BeauRoutine implements all the features of default Unity coroutines and several advanced features on top, giving you precise control over how and when your coroutines execute.

BeauRoutine also includes a powerful coroutine-driven tweening system. Tweens are highly configurable and easily integrated into a coroutine, allowing you to quickly iterate on programmatic animations and implement visual polish.

Note: BeauRoutine is still in development. If you encounter any issues, please eithercreate an issue in GitHub orsend me an email.

Table of Contents

  1. Basic Usage
  2. Tweens
  3. Advanced Features
  4. Tips and Tricks
  5. Technical Notes
  6. Reference

Basic Usage

Installing BeauRoutine

Note: BeauRoutine requires Unity version 5.2 or newer.

  1. Download the package from the repository:BeauRoutine.unitypackage
  2. Unpack into your project.

BeauRoutine uses theBeauRoutine namespace. You'll need to add the statementusing BeauRoutine; to the top of any scripts using it.

Running a Routine

To run a BeauRoutine, call

Routine.Start(MyCoroutine());

This will begin executing the given coroutine.

To stop a BeauRoutine, call

Routine.Stop("MyCoroutine");

Note: This method of stopping a BeauRoutine is maintained to make upgrading from Unity's existing coroutines to BeauRoutine as smooth as possible. It is highly recommended you read theHandles section.

Hosting Routines

Much like Unity's default Coroutines will only execute while their host object is alive, a BeauRoutine can be given a host to bind its lifetime to that of the host. To bind a host to a BeauRoutine, call

Routine.Start(this,MyCoroutine());

This will bind the given object as a host. As long as the host is alive, the BeauRoutine will be able to execute. If the host is deactivated, the BeauRoutine will pause until the host is again active. Once the host is destroyed, any BeauRoutines it hosted will be halted.

To stop a hosted BeauRoutine, call

Routine.Stop(this,"MyCoroutine");

It is highly recommended you host your BeauRoutines in most cases. In the event of a scene change, an unhosted BeauRoutine will keep executing, which may cause exceptions if your coroutine references objects from the previous scene.

Note: Unity's built-in coroutineswill not pause while their host is inactive. By default, BeauRoutineswill pause in the same circumstances. If you are depending on the default Unity behavior, it is highly recommended you read theHandles section to understand how to enable it.

Expanded Coroutine Syntax

BeauRoutines allow for more flexibility when writing your coroutine logic.

publicIEnumeratorMyCustomBeauRoutine(){DoAThing();// All four of these statements will wait// one second before resuming execution.yieldreturn1;yieldreturn1.0f;yieldreturnRoutine.WaitSeconds(1.0f);yieldreturnnewWaitForSeconds(1.0f);// You can still yield YieldInstructions,// WWW objects, and CustomYieldInstructions.yieldreturnnewWWW(...);yieldreturnnewWaitForSeconds(2.0f);yieldreturnnewWaitForEndOfFrame();// You can also yield commands that will// modify the state of the currently executing// routine.yieldreturnRoutine.Command.Pause;yieldreturnRoutine.Command.Stop;// You can yield into other coroutines.// This will execute the other coroutine// and return execution here once it has// concluded.yieldreturnMyOtherBeauRoutine();// You can wait for a given function to evaluate to true.yieldreturnRoutine.WaitCondition(CanProceed);}publicIEnumeratorMyOtherBeauRoutine(){...}publicboolCanProceed(){...}

It is recommended you useRoutine.DeltaTime in place of any usages ofTime.deltaTime in your coroutines, as the former takes into account BeauRoutine-specific time scaling. SeeTime Scale for more information.

Handles

Similar to Unity'sCoroutine object, theRoutine object returned after calling many BeauRoutine functions, includingRoutine.Start, is a handle reference to a BeauRoutine. You can use that to modify the BeauRoutine as long as it's running. It's also a safe reference - if the BeauRoutine it points at expires, you can still call functions on the handle without fear of either exceptions or unintentionally modifying other active BeauRoutines.

// Initialize the Routine object to point at nothing.RoutinemyRoutine=Routine.Null;// myRoutine now points to the running BeauRoutinemyRoutine=Routine.Start(this,MyCoroutine());// You can pause, resume, or stop a BeauRoutine with the reference.myRoutine.Pause();myRoutine.Resume();myRoutine.Stop();// You can call these functions even if the BeauRoutine has expired.// If it has expired, there will be no effect.myRoutine=Routine.Start(this,MyCoroutine2());myRoutine.Pause();// PausesmyRoutine.Stop();// StopsmyRoutine.Pause();// No effect// You can even use a Routine as an IDisposableusing(myRoutine.Replace(this,MyCoroutine()){...// Exiting the using statement will stop the BeauRoutine.}// Dispose is an alias of Stop, maintained strictly// for IDisposable compatibilitymyRoutine.Dispose();// You can test if a BeauRoutine still exists.if(myRoutine.Exists()){ ...}// It will also implicitly cast to a bool with the same result.if(myRoutine){ ...}// Routine.Wait will generate a coroutine that waits until// the coroutine that's being pointed at has expired.yieldreturnmyRoutine.Wait();// Yielding a Routine directly will have the same effect// as Routine.WaityieldreturnmyRoutine;// You can direct a BeauRoutine to ignore the active state of its host object.// By calling ExecuteWhileDisabled, your BeauRoutine will continue to execute while// the host object is disabled.// This is the default behavior of Unity's built-in coroutines.// Call this if you depend on that behavior.myRoutine.ExecuteWhileDisabled();// You can also restore the default BeauRoutine pausing behavior.myRoutine.ExecuteWhileEnabled();// You can set when this BeauRoutine is updated.myRoutine.SetUpdatePhase(RoutinePhase.FixedUpdate);// You can delay the routine by a certain number of seconds.// Note that this is cumulative and affected by time scale.// See the section on Time Scale for more information.myRoutine.DelayBy(2f);

Routine objects can also be used to start BeauRoutines.

RoutinemyRoutine=Routine.Null;// You can start a BeauRoutine from the referencemyRoutine.Replace(this,MyCoroutine());// Replace will stop the currently running BeauRoutine// and replace it with another routine.// This also modifies the contents of the handle,// so you don't have to re-assign to the variable.myRoutine.Replace(this,MyCoroutine2());// You can replace a Routine with a reference to another// BeauRoutine if necessary. This will only change the// reference and will not otherwise modify the running// BeauRoutine.RoutinemyRoutine2;myRoutine2.Replace(myRoutine);

You can also assign a name to a BeauRoutine using a Routine object.

// Assign a name with SetNameRoutineexplicitlyNamed=Routine.Start(MyCoroutine());explicitlyNamed.SetName("aDifferentName");// If you don't assign a name, the name of the function// will be used the first time you request the name.RoutineimplicitlyNamed=Routine.Start(MyCoroutine());// Write out the names of each functionDebug.Log(explicitlyNamed.GetName());// "aDifferentName"Debug.Log(implicitlyNamed.GetName());// "MyCoroutine"// You can stop BeauRoutines with these names!Routine.Stop("MyCoroutine");// stops implicitlyNamedRoutine.Stop("aDifferentName");// stops explicitlyNamed

Combine

Routine.Combine is a coroutine that executes multiple coroutines concurrently. This can be incredibly useful for programmatic animations or syncing operations between objects. It concludes when all the given coroutines have either concluded or halted.

publicIEnumeratorMyCombineRoutine(){// This will execute Operation1 and Operation2 concurrently.// Both debug messages will be logged.yieldreturnRoutine.Combine(Operation1(),Operation2());}publicIEnumeratorOperation1(){yieldreturn1.0f;Debug.Log("Operation 1 has concluded.");}publicIEnumeratorOperation2(){yieldreturn2.0f;Debug.Log("Operation 2 has concluded.");}

Race

Routine.Race is similar to Combine, but it concludes when one of the given coroutines has concluded or halted. None of the other given coroutines are allowed to execute after one has concluded.

publicIEnumeratorMyCombineRoutine(){// This will only log the Operation1 debug message.yieldreturnRoutine.Race(Operation1(),Operation2());}publicIEnumeratorOperation1(){yieldreturn1.0f;Debug.Log("Operation 1 has concluded.");}publicIEnumeratorOperation2(){yieldreturn2.0f;Debug.Log("Operation 2 has concluded.");}

Sequences

ASequence is a customizable sequence of coroutines, function calls, and delays. Instead of creating a new function for every combination of coroutines, you can instead construct a coroutine out of common parts.

publicvoidAwake(){// This will run FirstBeauRoutine, wait 5 seconds, then call Destroy(gameObject).Routine.Start(this,Sequence.Create(FirstBeauRoutine()).Wait(5.0f).Then(()=>{Destroy(gameObject);}));}publicIEnumeratorFirstBeauRoutine(){...}

Tweens

Tweens as Coroutines

In BeauRoutine, tweens are implemented as a special kind of coroutine calledTween. They perform animation over time.

// Create the tweenTweentween=Tween.Float(...);// Start it as if it were a coroutine.Routine.Start(this,tween);// Or combine it into one line.Routine.Start(this,Tween.Float(...));// Or use the .Play extension method!Tween.Float(...).Play(this);

Modifying a Tween

After creating a Tween, you can then enhance it with curves, loops, and wave functions before starting it.

// Create the tween.Tweentween=Tween.Float(...);// You can control how many times a Tween will run.tween.Once();// Only run once. Default behavior.tween.Loop();// Loop forever.tween.Loop(2);// Loop 2 times then stop.tween.Yoyo();// Run forwards then reversed once.tween.YoyoLoop();// Run forwards and reversed forever.tween.YoyoLoop(2);// Run forwards then reversed 2 times.// You can even set the Tween to run FROM the given target// to the current value instead of the other way around.tween.From();// You can also apply easing functions.tween.Ease(Curve.Smooth);// Apply a pre-made easing function.tween.Ease(AnimationCurve.Linear(0,0,1,1));// Apply a Unity AnimationCurve for more customizable control.// Wave functions are also supported.// Frequency values are the number of complete waves// over the duration of one run of the Tween.tween.Wave(Wave.Function.Sin,2.0f);// Modify the tween by a sine function with a frequency of 2.tween.Wave(newWave(Wave.Function.Sin,2.0f));// Same effect as previous line.// You can also change the duration.tween.Duration(2.0f);// You can delay a tween or make it start from a specific time.// Note that these are mutually exclusive operations.tween.DelayBy(2.0f);// Will not start for 2 seconds.tween.StartsAt(2.0f);// Will fast forward 2 seconds when starting.// These can be chained together for a more compressed and fluent syntax.Tweentween=Tween.Float(...).Ease(Curve.Smooth).YoyoLoop();

For further info about easing functions, I recommend checking outRobert Penner's Easing Functions andEasings.net.

Value Shortcuts

BeauRoutine comes with a set of shortcut functions and extension methods for generating Tweens.

Value tweens shortcuts will generally have the following signature:

TypeName(Start,End,SetFunction,Duration,[RequiredArgs],[OptionalArgs])//ExamplesTween.Float(0f,1f,(f)=>{myFloat=f;},2);Tween.Color(Color.white,Color.black,(c)=>{myColor=c;},3,ColorUpdate.FullColor);//Generic version requires an interpolator functionTween.Value<float>(0.0f,1.0f,(f)=>{myFloat=f;},Mathf.Lerp,2f);

Extension Methods

Extension methods will generally have the following signature:

// If called from TweenShortcutsPropertyTo(Object,End,Duration,[RequiredArgs],[OptionalArgs])// If called as extension (e.g. transform.MoveTo)PropertyTo(End,Duration,[RequiredArgs],[OptionalArgs])//Examplestransform.MoveTo(newVector3(1.0f,1.0f,1.0f),2.0f);rectTransform.AnchorPosTo(0f,0.3f,Axis.X);audioSource.VolumeTo(0.0f,2.0f);

Mirrored Tweens

Yoyo Tweens have a property calledMirrored, which affects how easing functions are applied when the Tween is reversed. Normally, reversed Tweens apply their easing functions as if the Tween was not reversed. An EaseOut will have the same progression over time from end to start as it did from start to end. A mirrored Tween will reverse the easing function as well.

Put in other terms, a normal Tween that starts slow and speeds up animating from start to end will also start slow and speed up when animating back to start. The same Tween, mirrored, will start fast and slow down when animating back to start.

Advanced Features

Routine Identity

TheRoutineIdentity component can be attached to any GameObject to apply a per-object time scale. Note that this will only apply to BeauRoutines that are started after attaching the RoutineIdentity - it will not retroactively apply time scaling on BeauRoutines run before it was attached.

You can find the RoutineIdentity for a given object by callingRoutineIdentity.Find. If you want to ensure the object has a RoutineIdentity, callRoutineIdentity.Require, which will lazily instantiate an instance on the given object.

Per-object time scale is controlled by theTimeScale property. SeeTime Scale for information about how time scale affects a BeauRoutine.

// Make sure we have a RoutineIdentity for this object.RoutineIdentityidentity=RoutineIdentity.Require(this);// Apply some slow motion.identity.TimeScale=0.25f;// MyCoroutine will now run at 0.25 speed.Routine.Start(this,MyCoroutine());

In the case you may want a BeauRoutine to ignore the per-object time scale, you can callDisableObjectTimeScale.EnableObjectTimeScale will re-enable it.

// Make sure we have a RoutineIdentity for this object.RoutineIdentityidentity=RoutineIdentity.Require(this);// Apply some slow motion.identity.TimeScale=0.25f;// Do something in slow motion.Routine.Start(this,MyCoroutine());// After 2 real seconds, reset the time scale on this object's RoutineIdentity.Routine.Start(this,ResetTimeScale(2.0f)).DisableObjectTimeScale();IEnumeratorMyCoroutine(){...// This will run at 0.25 speed.}IEnumeratorResetTimeScale(floatdelay){// This will run at normal speed.yieldreturndelay;RoutineIdentity.Require(this).TimeScale=1.0f;}

All BeauRoutines on a RoutineIdentity's GameObject can be paused or resumed with thePaused property.

Time Scale

BeauRoutine offers a powerful time scaling system. Every BeauRoutine has its own time scaling value, which can be retrieved or set by callingGetTimeScale orSetTimeScale on a Routine object.

// Create a RoutineRoutiner=Routine.Start(this,MyCoroutine());// Retrieve the time scale for the Routine and double it// Time scaling, by default, starts at 1floattimeScale=r.GetTimeScale();timeScale*=2;r.SetTimeScale(timeScale);// Run at half speedtimeScale=0.5f;r.SetTimeScale(timeScale);

Time scale affectsRoutine.DeltaTime, which is calculated directly before a BeauRoutine is run every frame. DeltaTime is a product ofTime.deltaTime and any scaling factors that need to be applied to a BeauRoutine. If you need unscaled time for any reason, useRoutine.UnscaledDeltaTime.

IEnumeratorIncrementByTime(){floatmyFloat=0.0f;while(true){myFloat+=Routine.DeltaTime;yieldreturnnull;}}

Time scale also affects any waiting you perform within a coroutine (e.g.yield return 1.0f,yield return Routine.WaitSeconds(1.0f)).

// This will wait 1 second.RoutinenormalSpeed=Routine.Start(this,MyCoroutine());RoutinehalfSpeed=Routine.Start(this,MyCoroutine()).SetTimeScale(0.5f);RoutinedoubleSpeed=Routine.Start(this,MyCoroutine()).SetTimeScale(2);IEnumeratorMyCoroutine(){// Any waiting you perform like this is specified in unscaled time.// In normalSpeed, this will take 1 real second.// In halfSpeed, this will take 2 real seconds.// In doubleSpeed, this will take 0.5 real seconds.yieldreturn1.0f;}

Time scale also applies to any Tweens you're currently running.

In total, there are four time scale values that can apply to a BeauRoutine.

  • Routine.TimeScale (multiplied withTime.timeScale to get global time scale)
  • Per-group time scales (seeGroups)
  • Per-object time scales (seeRoutine Identity)
  • Time scale for an individual BeauRoutine

You can calculate the total time scale that will be applied to BeauRoutines on a given object by callingRoutine.CalculateTimeScale. This is the accumulation ofRoutine.TimeScale, the per-object time scale, and the per-group time scale.

Update Phase

By default, BeauRoutines update during Unity's LateUpdate phase. This default can be changed, however, and BeauRoutines can be set to execute at one of six times:LateUpdate,Update,FixedUpdate,ThinkUpdate,CustomUpdate,RealtimeUpdate, andManual. Manual updates, as the name implies, are called manually and have several rules and restrictions, which are documentedhere.

FixedUpdate routines work off of a consistent delta time.

RealtimeUpdate routines work off of unscaled delta time - they aren't affected byTime.timeScale. This allows you to use Unity's timeScale to slow or stop other systems (physics, for example), while leaving other routines unaffected.

ThinkUpdate and CustomUpdate routines execute at custom intervals, after the Update phase. This evaluates as an Update, followed by a possible ThinkUpdate, followed by a possible CustomUpdate. The intervals at which they are executed can be changed by setting theRoutine.Settings.ThinkUpdateInterval andRoutine.Settings.CustomUpdateInterval properties. By default, these are set to 1/10th of a second for ThinkUpdate and 1/8th of a second for CustomUpdate.

Note: ThinkUpdate and CustomUpdate will only execute at most once per frame. A very small interval will not cause the phase to execute multiple times to compensate for a larger delta time, as might happen for a FixedUpdate.

// By default, BeauRoutine starts routines in the LateUpdate phase.Routine.Start(this,MyCoroutine());// This executes in LateUpdate// You can set the phase by calling SetPhase on a routineRoutine.Start(this,MyCoroutine()).SetPhase(RoutinePhase.FixedUpdate);// This will execute during FixedUpdate// You can also set the default phase for new routines.Routine.Settings.DefaultPhase=RoutinePhase.FixedUpdate;Routine.Start(this,MyCoroutine()).GetPhase();// GetPhase will return FixedUpdateRoutine.Start(this,MyCoroutine()).SetPhase(RoutinePhase.Update);// This will execute during Update

Yielding aWaitForFixedUpdate,WaitForEndOfFrame,WaitForLateUpdate,WaitForUpdate,WaitForThinkUpdate,WaitForCustomUpdate,WaitForRealtimeUpdate, or anyRoutinePhase will interrupt the normal timing of a BeauRoutine, and will instead execute it during those events. This does not apply for Manual updates, however; see theManual Updates section for more information.

Routine.Start(this,MyCoroutine()).SetPhase(RoutinePhase.Update);IEnumeratorMyCoroutine(){// Executing during UpdateDebug.Log(Routine.DeltaTime);// Normal deltaTimeyieldreturnRoutine.WaitForFixedUpdate();// Now executing during FixedUpdate.Debug.Log(Routine.DeltaTime);// Now using fixedDeltaTimeyieldreturnnull;// Executing during Update againDebug.Log(Routine.DeltaTime);// Back to normal deltaTimeyieldreturnRoutine.WaitForEndOfFrame();// Executing after all rendering is completedDebug.Log(Routine.DeltaTime);// Still using normal deltaTimeyieldreturnRoutinePhase.FixedUpdate;// Same as WaitForFixedUpdate// Waits until the next Update phaseyieldreturnRoutine.WaitForUpdate();yieldreturnRoutinePhase.Update;// Waits until the next LateUpdate phaseyieldreturnRoutine.WaitForLateUpdate();yieldreturnRoutinePhase.LateUpdate;// This does not do anything meaningful, and is equivalent to yielding null.yieldreturnRoutinePhase.Manual;}

TheWaitForLateUpdate,WaitForUpdate,WaitForThinkUpdate, andWaitForCustomUpdate events occur after their respective phases. If a BeauRoutine is already executing in that phase, yielding for those phases will wait until after the next time the phase is executed, instead of executing immediately after the phase is complete.

See Unity'sExecution Order of Event Function documentation for further information on update timing.

Priority

BeauRoutine provides a way of changing the priority of any individual BeauRoutine. Priority determines the order in which BeauRoutines are executed, from highest priority to lowest. This could be useful if the execution of one routine is dependent on the result of another. BeauRoutines with equal priority will be executed in order of the last time priority was set, or creation if priority was never specifically set. Priority will default to 0.

// Create the routines// r1 will be executed before r2, since it was created firstRoutiner1=Routine.Start(this,MyCoroutineA());Routiner2=Routine.Start(this,MyCoroutineB());// Set the priorities of the routines// Higher priorities will be executed first// Priority defaults to 0intr1Priority=r1.GetPriority();// 0r2.SetPriority(r1Priority+100);// 100// r2 will now execute before r1,// even though it was started after r1.

Note that this only affects order within an update phase. SeeUpdate Phase for more information.

Groups

Routines can be organized into one of 32 groups that can be paused, resumed, or time-scaled. Groups are automatically assigned based on theGroup property of the attached RoutineIdentity. While groups are maintained as integers, it's highly encouraged to use an enum type instead to name your groups.

// Tag any enum with this attribute and the Group property// in the RoutineIdentity inspector will be displayed as// an dropdown list instead of an integer field.[RoutineGroupEnum]publicenumObjectGroup{Default=0,Gameplay=1,UI=2}// Assign a group to this RoutineIdentityRoutineIdentity.Require(this).Group=(int)ObjectGroup.Gameplay;// This BeauRoutine now has ObjectGroup.Gameplay (1) as its group.Routine.Start(this,MyCoroutine());// You can get, set, or reset the timescale for a groupfloatgroupTimeScale=Routine.GetGroupTimeScale(ObjectGroup.Gameplay);Routine.SetGroupTimeScale(ObjectGroup.Gameplay,0.5f);Routine.ResetGroupTimeScale(ObjectGroup.Gameplay);// Resetting resets to 1.// While a single group is referenced by index, the PauseGroups and ResumeGroups// functions take in a bitmask of all affected groups.intgroupMask=Routine.GetGroupMask(ObjectGroup.Gameplay,ObjectGroup.UI);// You can pause and resume multiple groups at a time.Routine.PauseGroups(groupMask);Routine.ResumeGroups(groupMask);

It's important to note that a BeauRoutine can only belong to a single group. This is to ensure consistent timescaling behavior.

Inlined Coroutines

Normally, yielding into a nested coroutine will wait until the next frame to begin executing the nested coroutine. BeauRoutine provides a way of immediately entering and executing a nested coroutine by wrapping your coroutine in aRoutine.Inline call. Inlined coroutines, once finished, will also immediately resume execution on the coroutine that yielded it, skipping the one frame delay. This is useful if you need to time your coroutines in a very precise manner.

IEnumeratorRootCoroutine(){Debug.Log("This is the RootCoroutine log");yieldreturnRoutine.Inline(NestedCoroutine());Debug.Log("This will log on the same frame as the NestedCoroutine log");}IEnumeratorNestedCoroutine(){Debug.Log("This will log on the same frame as the RootCoroutine log");...}

Note that this is not supported when starting a new BeauRoutine. SeeOn Starting BeauRoutines and Update Phases for more information.

// Despite its appearance, this will not execute immediately.Routine.Start(Routine.Inline(RootCoroutine()));IEnumeratorRootCoroutine(){...}

You can also avoid the one frame delay when exiting a nested coroutine by yieldingRoutine.Command.BreakAndResume instead of letting your coroutine exit normally.

IEnumeratorRootCoroutine(){yieldreturnNestedCoroutine();Debug.Log("This will log on the same frame as the NestedCoroutine log");}IEnumeratorNestedCoroutine(){Debug.Log("This is the NestedCoroutine log");yieldreturnRoutine.Command.BreakAndResume;}

Be careful when using these features. Inlined execution offers more precise timing but runs the risk of executing too much in a single frame if overused.

Futures

BeauRoutine includes a basic implementation of Futures. Futures provide a way to asynchronously return values from functions and coroutines, without requiring the use of a callback.

AFuture object represents a value that will be returned by a function or coroutine at some point in the future. A Future must be completed with theComplete call before its value can be obtained. Alternately, a Future canFail with an optional error token. A Future can only be completed or failed once. Once either operation has been performed, future calls to those functions will throw an exception.

Futures are handy when dealing with asynchronous services - making calls to a REST server, for example.

// This will asynchronously calculate the hash of a stringFuture<int>CalculateHashAsync(stringstr){// To create a new future, call Future.Create<T>()Future<int>future=Future.Create<int>();// Start a routine that will eventually complete the promiseRoutineroutine=Routine.Start(CalculateHashAsyncImpl(future,str));// Link the Routine to the Future to ensure the Routine will stop// if the Future is cancelled.// A linked Routine will also cancel the Future if it ends prematurely.future.LinkTo(routine);// This future represents the eventual result of CalculateHashAsyncImplreturnfuture;}// We need access to the Future in order to complete it// We can pass it in as an argument to accomplish thisIEnumeratorCalculateHashAsyncImpl(Future<int>future,stringstr){// Some artificial delay to make this asynchronousyieldreturn0.25f;// Report progress information to the future.future.SetProgress(0.5f);// More artificial delayyieldreturn0.25f;if(str==null){future.Fail();}else{inthash=str.GetHashCode();future.Complete(hash);}}IEnumeratorDoSomething(){varfuture=CalculateHashAsync("someArbitraryString");// You can yield a Future to wait for it to// either complete or failyieldreturnfuture;if(future.IsComplete()){// Implicitly cast a future to its return type// If the future is not complete, this will throw an exception.inthash=future;Debug.Log(hash);}elseif(future.IsFailed()){Debug.Log("error occurred");}// You can provide OnComplete and OnFail callbacks// These will get called at the end of the frame when// the Future completes or fails.varfuture2=CalculateHashAsync(null).OnComplete((i)=>{Debug.Log(i);}).OnFail(()=>{Debug.Log("error occurred");});// You can also provide progress callbacks.// These will get called when progress through a future changes.future2.OnProgress((progress)=>{Debug.Log("progress: "+progress);});}

Custom Tweens

Tweens in BeauRoutine are highly extensible through theITweenData interface. Tweens perform the timing, easing, and looping logic; an ITweenData object applies the animation. To use one of your own ITweenData-derived objects, you can use theTween.Create function with your object as an argument.

// Making your own ITweenDatapublicclassSomeObjectTweenData:ITweenData{privateSomeObjectm_Object;privatefloatm_Start;privatefloatm_End;publicSomeObjectTweenData(SomeObjectinObject,floatinEnd){m_Object=inObject;m_Start=inObject.MyValue;m_End=inEnd;}publicvoidOnTweenStart(){...// Any custom logic when a tween starts can go here}publicvoidApplyTween(floatinPercent){m_Object.MyValue=Mathf.Lerp(m_Start,m_End,inPercent);}publicvoidOnTweenEnd(){...// Any custom logic when a tween ends or is killed can go here}}publicclassSomeObject{publicfloatMyValue=0;publicTweenMyValueTo(floatinValue,floatinTime){SomeObjectTweenDatatweenData=newSomeObjectTween(this,inValue);returnTween.Create(iTweenData,inTime);}}

Manual Updates

You can manually update both individual BeauRoutines and the set of BeauRoutines with their phase set toManual.

Individual Routines

You can callTryManuallyUpdate on a BeauRoutine to attempt to force it to update, optionally providing a timestep. The BeauRoutine will fail to update if it is already updating. You can attempt to force other BeauRoutines to update from within aTryManuallyUpdate call. This call is not restricted by update phase.

Manual Set

You can callRoutine.ManualUpdate to attempt to update the set of BeauRoutines set to theManual phase. BeauRoutines that are already updating will not update. You cannot nest these calls.

Restrictions

Manual BeauRoutines will not respond to yields that would change their update phase, such asWaitForFixedUpdate orWaitForEndOfFrame. While these phase changes make sense for an automatically-updated BeauRoutine, they do not for a manually-updated BeauRoutine. As such, these yields are equivalent to waiting for a frame.

Debugger

BeauRoutine includes a simple profiler and debugger, found under the menu itemWindow/BeauRoutine Debugger.

TheSTATS page displays the number of BeauRoutines currently running, the maximum you've had running at the same time, and the total you can run concurrently without allocating more memory. It also keeps track of the average time it takes to execute all the currently running BeauRoutines, and maintains a snapshot of what was running when the last maximum was recorded.

TheOPTIONS page displays the current time scale, as well as options for resetting it, doubling it, or halving it. It also contains a button enabling or disabling the snapshot feature on the STATS page.

TheDETAILS page displays all the currently running BeauRoutines in a list. From here, you can pause, resume, or stop any of them, as well as rename them or set their time scale. Any Combine or Race routines are presented in a hierarchical format.

Tips and Tricks

UseRoutine handles as slots

MaintainRoutine handles as "slots" for executing coroutines. This can be helpful for ensuring you only have one instance of a particular type of operation executing at a time. It can also help keep track of executing BeauRoutines, allowing you to selectively clean up any operations instead of stopping all BeauRoutines on a given object.

This is particularly necessary if you have operations that execute on shared data. Two Tweens fading the same SpriteRenderer will interfere with one another, so ensuring you only have one Tween executing on that property at a time will help prevent unwanted behavior.

// This class will move and fade the given object on command.// It can also perform an important operation on a string.publicclassMyAnimatingObject:MonoBehaviour{// These Routine objects effectively act as slots.// If you don't want duplicates of an operation running simultaneously,// you can use these handles to stop old operations and start new onesprivateRoutinefadeAnimation;privateRoutinemoveAnimation;privateRoutineimportantRoutine;publicvoidFadeTo(floatalpha,floatduration,Curvecurve=Curve.Linear){// Replace is safe to call, even if the Routine isn't currently referencing an active BeauRoutinefadeAnimation.Replace(this,GetComponent<SpriteRenderer>().FadeTo(alpha,duration).Ease(curve));}publicvoidMoveTo(Vector3position,floatduration,Curvecurve=Curve.Linear){moveAnimation.Replace(this,transform.MoveTo(position,duration).Ease(curve));}publicvoidDoSomethingImportant(stringdata){importantRoutine.Replace(this,DoSomethingImportantRoutine(data));}privateIEnumeratorDoSomethingImportantRoutine(stringdata){...}}

Limit a BeauRoutine's lifetime with ausing statement

Execute a BeauRoutine in the background while executing a block in your coroutine with ausing statement. This is useful if you want an operation to execute only for as long as a block in the coroutine is executing.

IEnumeratorDoImportantWork(string[]importantData){using(Routine.Start(this,PlayAnAnnoyingSoundLoop()){// As long as DoImportantWork is executing within this block,// PlayAnAnnoyingSoundLoop will execute.for(inti=0; i<importantData.Length;++i){Debug.Log("Doing some important work with: "+importantData[i]);yield return1;}}using( Routine.Start(this, PlayAnAnnoyingSoundOnce()){// Within this block, PlayAnAnnoyingSoundOnce will execute// We exit this block before PlayAnnoyingSoundOnce has// a chance to log its message, however.Debug.Log("Doing important work with no data");yield return1;}}IEnumerator PlayAnAnnoyingSoundLoop(){while(true){Debug.Log("Playing an annoying sound");yield return0.2f+Random.value*0.25f;}}IEnumerator PlayAnAnnoyingSoundOnce(){yieldreturn2;Debug.Log("Playing an annoying sound");}

Split your coroutine functions to execute code immediately

When starting a BeauRoutine, the work is queued up to execute at the next opportunity for the BeauRoutine's update phase. If you need some code to execute immediately, you can split your coroutine functions into instant and an over-time portions.

// This needs to happen as soon as the BeauRoutine starts.voidResetVisuals(){}// This happens within the BeauRoutine.voidUpdateVisuals(){}Routine.Start(ReturnsACoroutine());// This is a regular function.IEnumeratorReturnsACoroutine(){// Instant work goes here...Debug.Log("This is executing outside of the BeauRoutine.");// This needs to happen immediately.// Putting it in here ensures it will execute// as soon as InstantWorkIntoRoutine is called.ResetVisuals();// You can return an IEnumerator directly.returnIsACoroutine();}// This is a coroutine.IEnumeratorIsACoroutine(){// If we call ResetVisuals here instead,// it will happen on a one-frame delay.UpdateVisuals();// Important work goes here...// An IEnumerator function only becomes a coroutine// once a yield statement is encountered.yield returnnull;Debug.Log("This is executing within the BeauRoutine.");}

IEnumerator functions only become coroutines once ayield return statement is used. If youreturn normally, it is treated as a regular function.

SeeOn Starting BeauRoutines and Update Phases for more information.

UseTweenUtil.Lerp to asymptotically interpolate to a changing target

Tweens are great for interpolating towards fixed targets, but in cases where the target is changing continuously, they are suboptimal.

As an example: Say you want the camera to smoothly interpolate to a point determined by player input.

  • You have a player character viewed from a top-down angle.
  • You want the camera to rest somewhere halfway between the player and a point extending out from the player's facing direction.
  • The facing direction may change often, since it is tied directly to player input.
  • You want the camera to smoothly transition to its target position.

Given these constraints, there are several approaches you may take.

  • Start a tween every time the direction changes. This may result in jittery, inconsistent camera movement.
  • Interpolate with a fixed time towards your dynamic target. This may result in unwanted acceleration or deceleration as the target position changes during the interpolation.
  • Apply some level of physics simulation to the camera, or perhaps a steering behavior. This is a valid, if more complicated approach.
  • Forgo transitions entirely - instantly snap the camera to the target position. This is also a valid approach, if potentially disorienting depending on the perspective.

There are simpler ways of achieving this effect.

To achieve smoother, more consistent motion, you can asymptotically interpolate towards the target value. This involves moving the value by a percentage of the difference between the value and the target every frame. In effect, as the value gets closer to the target, the rate of change per-frame decreases, resulting in a smooth and pleasant deceleration.

In games with a fixed framerate, or games that calculate based on frame, not delta time, it may look something like this:

// This will interpolate someValue to someTarget by 25% each framesomeValue=Mathf.Lerp(someValue,someTarget,0.25f);

This approach is not sufficient for games with a variable framerate, however. As the game slows down and fewer frames are executed per second, the object will move at a slower rate towards the target.

A revised approach needs to account for varying delta time, perhaps by scaling the percentage. It might look like this:

// This scales the interpolation percent based on delta time.// The expected framerate is 60. Framerate multipled by delta time// should get a ratio of expected frame time to actual frame time.inttargetFrameRate=60;floatlerpScale=targetFrameRate*Time.deltaTime;someValue=Mathf.Lerp(someValue,someTarget,0.25f*lerpScale);

This feels more accurate, and but again, this approach falls apart with large timesteps, resulting in incorrect behavior. If, say, the game slows down enough to skip 60 frames, or 120 frames, you end up with larger and larger multiplies of your desired interpolation percentage, which could lead to reaching the target or even overshooting the target. This becomes more likely as the percentage increases, limiting the range of reasonable percentages you can use in this approach. Ultimately, this is not an accurate approach.

To correctly simulate this type of asymptotic interpolation, we not only need to account for the distance remaining at the time of the lerp, we also need to account for the change in distance remainingwithin the lerp itself. In other words, the change in rate of change needs to occurcontinuously, instead of at discrete intervals. This can be modeled in terms ofexponential decay.

BeauRoutine providesTweenUtil.Lerp. This function scales the rate of change to appropriately handle fluctuations in framerate and maintain the asymptotic nature of the interpolation.

It is important to note that these functions, by default, interpret the given percentages asper-second, not per-frame. If you already have your percentages specified in terms of a fixed framerate, you can callTweenUtil.SetDefaultLerpPeriodByFramerate to specify the expected timestep. Both functions can also accept a period and a timestep. If a timestep is not provide, these functions will useRoutine.DeltaTime.

// Since we've already been using 25% with an expectation of 60 frames per second,// we can modify the default period to match.inttargetFrameRate=60;TweenUtil.SetDefaultLerpPeriodByFramerate(targetFrameRate);floatscaledLerp=TweenUtil.Lerp(0.25f);someValue=Mathf.Lerp(someValue,someTarget,scaledLerp);// You could also multiply out the percentage by the framerate for the same effect.TweenUtil.SetDefaultLerpPeriod(1);scaledLerp=TweenUtil.Lerp(0.25f*targetFrameRate);// This is mathematically equivalent

TweenUtil.LerpDecay returns the equivalent of1 - TweenUtil.Lerp, which can be a useful shortcut when interpolating towards 0. This might occur when simulating friction or drag, for example.

Technical Notes

On Starting BeauRoutines and Update Phases

When you start a BeauRoutine, you are adding it to a queue to execute during the next instance of its update phase. If you start a BeauRoutine for a currently-executing update phase, it will not begin executing until the next instance of that update phase.

Routine.Start(PartA()).SetPhase(RoutinePhase.Update);IEnumeratorPartA(){...// This occurs on one frame// This routine will not execute until the next frame,// since PartA is executing in the same update phaseRoutine.Start(PartB()).SetPhase(RoutinePhase.Update);}IEnumeratorPartB(){...// This occurs on the next frame}

If you need code to execute immediately, this can be worked around by dividing your routine into two functions. SeeSplit your coroutine functions to execute code immediately for more information.

This can also be circumvented by callingTryManuallyUpdate on a routine to attempt to force it to execute immediately. SeeManual Updates for more information.

On Stopping BeauRoutines

When you stop a BeauRoutine, it will not be cleaned up until the next time it attempts to execute. If the BeauRoutine is set to manually update, and is not currently executing, it will be cleaned up immediately.

On Reserved Routine Names

BeauRoutines must not be given a name that starts with[BeauRoutine]__. This is a reserved prefix used for internal purposes. In the (admittedly unlikely) event you attempt to set a name with this prefix, it will log a warning instead and not change the name.

On Delta Time

For BeauRoutines paused for some amount of time, perhaps with aRoutine.WaitSeconds or ayield return 1f,Routine.DeltaTime will adjust when that period ends to account for time overlap. For example, if the BeauRoutine requests to wait for 2 seconds, but we wait for 2.1 seconds, delta time will be decreased by 0.1 seconds to compensate.

This time adjustment does not apply during the FixedUpdate phase, or after yielding aWaitForFixedUpdate. This is to ensure consistent delta time during FixedUpdate.

On Memory Allocation

BeauRoutine will be initialized the first time a BeauRoutine operation is performed. You can also initialize BeauRoutine in advance by callingRoutine.Initialize.

BeauRoutine pre-allocates resources to run a default number of concurrent BeauRoutines. When there are no more resources available to execute all scheduled BeauRoutines, it will allocate more. This doubles the maximum number of concurrent BeauRoutines (16 -> 32 -> 64 -> ...), up to a maximum of 16,777,216. If you desire to reduce runtime allocations, you can callRoutine.Settings.SetCapacity to pre-allocate the resources necessary to run the given number of BeauRoutines.

To determine your game's requirements, open up theDebugger during gameplay and view theMAX field in theSTATS page. This will tell you how many BeauRoutines that the system needed to allocate resources for during the current session. TheCAPACITY field will tell you how many were actually allocated in order to support it. By callingRoutine.Settings.SetCapacity, you can pre-allocate for the peak number of BeauRoutines in your game and optimize your memory usage.

In debug mode, BeauRoutine may generate garbage periodically if profiling is enabled. This is generated by aDebug.Log call, made in order to output stats to the console. This will not occur outside of debug mode. To disable profiling in debug mode, setRoutine.Settings.ProfilingEnabled tofalse. Note that this will also disable stats in the debugging window.

While BeauRoutine attempts to avoid runtime allocations as often as possible, there are unavoidable allocations associated with a C# coroutine framework. Coroutines, as implemented in C#, allocate memory when called. Coroutines are implemented in C# asiterator blocks. C# compilers transform iterator blocks into state machine classes. Calling an iterator block will allocate a new instance of its associated state machine. These allocations are tiny but worth mentioning for memory-constrained applications. Tweens and certain utilities, such asRoutine.Combine andRoutine.Delay, will also allocate small amounts of memory.

For more information on how coroutines are implemented in C# compilers, read this article:C# In Depth: Iterator block implementation details.

On Important Differences between BeauRoutines and Unity Coroutines

CategoryBeauRoutineUnity coroutines
Starting a coroutineRoutine.Start queues the coroutine to be executed during its update phase.StartCoroutine executes the first frame of the coroutine immediately.
Enabling/Disabling MonoBehavioursBy default, BeauRoutines will pause when their host MonoBehaviour is inactive.Unity coroutines will not pause when their host MonoBehaviour is inactive.

Reference

Routine Functions

These functions can be called directly on a Routine handle.

FunctionDescription
Pausing
PausePauses the BeauRoutine.
ResumeResumes the BeauRoutine.
GetPausedReturns if the BeauRoutine is paused.
DelayDelays the BeauRoutine by the given number of seconds. This is cumulative.
GetLockLocks the BeauRoutine and returns a handle to the lock. All locks must be released before the BeauRoutine will resume.
Stopping
StopStops the BeauRoutine.
ReplaceStops the BeauRoutine and replaces it with another one.
Time Scaling
GetTimeScaleReturns the per-BeauRoutine timescale.
SetTimeScaleSets per-BeauRoutine timescale.
DisableObjectTimeScaleIgnores per-object timescale on this BeauRoutine.
EnableObjectTimeScale[Default] Uses per-object timescale on this BeauRoutine.
Execution
ExecuteWhileDisabledBeauRoutine will continue to execute while its host is disabled.
ExecuteWhileEnabled[Default] BeauRoutine will not execute while its host is disabled.
GetPriorityReturns the execution priority of the BeauRoutine.
SetPrioritySets the execution priority of the BeauRoutine. Greater priority BeauRoutines are executed first.
GetPhaseReturns the update phase for the BeauRoutine.
SetPhaseSets the update phase for the BeauRoutine. The Routine be executed the next time the phase updates.
TryManuallyUpdateAttempts to manually update the BeauRoutine with the given delta time.
Name
GetNameGets the name of the BeauRoutine. If a name has not been set, this will return the name of the coroutine provided when starting the BeauRoutine.
SetNameSets the name of the BeauRoutine.
Events
OnCompleteRegisters a function to execute once the BeauRoutine completes naturally.
OnStopRegisters a function to execute once the BeauRoutine completes prematurely.
OnExceptionRegisters a function to execute if an exception is encountered while updating the BeauRoutine.
Miscellaneous
ExistsReturns if this BeauRoutine has not been stopped.
WaitReturns a coroutine that waits for the given BeauRoutine to end.

Routine Utilities

NameDescription
Start
Routine.StartStarts a BeauRoutine.
Routine.StartDelayStarts a BeauRoutine that calls a function or executes a coroutine after a certain number of seconds.
Routine.StartLoopStarts a BeauRoutine that calls a function every frame.
Routine.StartLoopRoutineStarts a BeauRoutine that executes a coroutine in a never-ending loop.
Routine.StartCallStarts a BeauRoutine that calls a function at the end of the frame.
Time
Routine.DeltaTimeDelta time for the current routine, with all applicable scaling applied.
Routine.UnscaledDeltaTimeUnscaled delta time for all routines.
Routine.RemainingFrameBudgetMSRemaining milliseconds left in the current frame, relative to the frame budget.
Flow
Routine.PausePauses the BeauRoutine with the given name.
Routine.PauseAllPauses all BeauRoutines.
Routine.ResumeResumes the BeauRoutine with the given name.
Routine.ResumeAllResumes all BeauRoutines.
Routine.StopStops the BeauRoutine with the given name.
Routine.StopAllStops all BeauRoutines.
Query
Routine.FindReturns the Routine for the BeauRoutine with the given name.
Routine.FindAllReturns a list of Routines for the BeauRoutines with the given host.
Wait
Routine.WaitFramesWaits for the given number of frames.
Routine.WaitSecondsWaits for the given number of seconds.
Routine.WaitRealSecondsWaits for the given number of unscaled seconds.
Routine.WaitConditionWaits for the given function to returntrue.
Routine.WaitForeverWaits until the heat death of the universe.
Routine.WaitRoutinesWaits until the given Routines expire.
Routine.WaitForFixedUpdateWaits until FixedUpdate completes.
Routine.WaitForEndOfFrameWaits until rendering of the current frame completes.
Routine.WaitForLateUpdateWaits until LateUpdate completes.
Routine.WaitForUpdateWaits until Update completes.
Routine.WaitForRealtimeUpdateWaits until RealtimeUpdate completes.
Routine.WaitForThinkUpdateWaits until ThinkUpdate completes.
Routine.WaitForCustomUpdateWaits until CustomUpdate completes.
Execution
Routine.DelayCalls a function after the specified number of seconds.
Routine.CallCalls a function at the end of the frame.
Routine.PerSecondCalls a function the given number of times per second.
Routine.CombineRuns multiple coroutines concurrently, and completes all.
Routine.RaceRuns multiple coroutines concurrently, and stops when one expires.
Routine.InlineExecutes the given coroutine immediately after yielding into it.
Routine.YieldImmediately yields the provided value.
Routine.ManualUpdateUpdates all routines in the Manual phase.
Groups
Routine.PauseGroupsPauses all BeauRoutines in the given groups
Routine.ResumeGroupsResumes all BeauRoutines in the given groups
Routine.GetGroupPausedReturns if the given group is paused
Routine.GetGroupTimeScaleReturns the time scale for the given group
Routine.SetGroupTimeScaleSets the time scale for the given group
Routine.ResetGroupTimeScaleResets the time scale for the given group
Routine.GetGroupMaskReturns the bitmask for the given groups
Collections
Routine.ForEachGenerates and executes, in sequence, a coroutine for every element in the given collection.
Routine.ForEachParallelGenerates and executes, in parallel, a coroutine for every element in the given collection.
Routine.ForEachParallelChunkedGenerates and executes, in parallel, a coroutine for every element in the given collection, in batches.
Amortization
AmortizeExecutes a series of actions across multiple frames, executing for a certain number of milliseconds per frame.
ForEachAmortizeExecutes an action on every element in the given collection across multiple frames, executing for a certain number of milliseconds per frame.
AmortizeQueueExecutes an action on every element in the given queue across multiple frames, executing for a certain number of milliseconds per frame, until the queue is exhausted.
AmortizeQueueLoopExecutes an action on every element in the given queue across multiple frames, executing for a certain number of milliseconds per frame. When the queue is exhausted, will wait until more elements are available and restart.
Misc
Routine.TimerCounts down for the given number of seconds, with a callback for time remaining.
Routine.AccumulateCounts up for the given number of seconds, with a callback for time accumulated.
Routine.WaitForSpareTimeWaits until the desired number of milliseconds are available at the end of the frame before continuing.

Routine Extensions

BeauRoutine contains a few extension methods for generating coroutines.

TypeFunctionDescription
AudioSourceWaitToCompleteWaits until the AudioSource is no longer playing.
ParticleSystemWaitToCompleteWaits until the ParticleSystem is no longer emitting and no longer has any live particles
ThreadWaitToCompleteWaits until the thread is no longer alive.
AnimatorWaitToCompleteAnimationWaits until the current animation stops playing or loops.
WaitToCompleteStateWaits until the Animator is playing and exits the given state.
WaitForStateWaits until the Animator is playing the given state.
WaitForNotStateWaits until the Animator is not playing the given state.
UnityEventWaitForInvokeWaits until the UnityEvent has been invoked, optionally invoking a callback.

BeauRoutine also provides a set of extension methods to set an update phase routine on a MonoBehaviour as a substitute for managing those routines inside the component itself.

TypeFunctionDescription
MonoBehaviourSetUpdateRoutineSets a single update phase routine for the MonoBehaviour.
SetUpdateRoutineGeneratorSets a single update phase routine generator.
GetUpdateRoutineReturns the single update phase routine for the MonoBehaviour.
ClearUpdateRoutineClears the single update phase routine for the MonoBehaviour.

Note that these work with a reserved set of names. SeeOn Reserved Routine Names for more information.

Global Settings

All settings are available in the editor. Non-development builds disable access to several debug settings for performance reasons. Note that those settings can be safely called, but not modified.

NameDescriptionRestrictions
Properties
Routine.Settings.PausedEnables/disables all update loops. Note that manual updates will still function with this disabled.---
Routine.Settings.DefaultPhaseSets the default update phase for new BeauRoutines.---
Routine.Settings.ThinkUpdateIntervalSets the interval between ThinkUpdate phases.---
Routine.Settings.CustomUpdateIntervalSets the interval between CustomUpdate phases.---
Routine.Settings.VersionReturns the BeauRoutine version number.---
Routine.Settings.HandleExceptionsEnables or disables exception handling on all BeauRoutines. Note that BeauRoutines with explicitly set exception handlers will still handle exceptions, regardless of this setting.---
Routine.Settings.DebugModeEnabled or disables additional error checks.Debug Only
Routine.Settings.ProfilingEnabledEnabled or disables profiling. This will track execution time stats and periodically log them to the debug console. This will only function if Debug Mode is enabled.Debug Only
Routine.Settings.SnapshotEnabledEnables or disables snapshot profiling. This will take snapshots of the highest number of simultaneous executing BeauRoutines. This will only function if Profiling is enabled.Debug Only
Routine.Settings.FrameDurationBudgetMSSets the expected millisecond duration per frame.---
Functions
Routine.Settings.SetCapacityPre-allocates for the given number of simultaneous executing BeauRoutines. Useful for avoiding unexpected allocations.---
Routine.InitializeInitializes BeauRoutine. BeauRoutine will auto-initialize when you perform your first BeauRoutine operation, but this can be called earlier to allocate the necessary resources.---
Routine.ShutdownShuts down BeauRoutine. Any BeauRoutine operations will now throw an exception untilRoutine.Initialize is called again.---

Future Functions

FunctionDescription
IsDoneReturns if the Future is no longer in progress.
Progress
IsInProgressReturns if the Future is in progress.
GetProgressReturns the reported Future progress.
SetProgressSets the reported Future progress.
OnProgressRegisters a handler for when progress changes.
Complete
IsCompleteReturns if the Future has been completed.
GetReturns the value the Future successfully completed with. Will throw an exception if the Future did not complete successfully.
TryGetAttempts to get the value the Future successfully completed with.
CompleteCompletes the Future successfully with a value.
OnCompleteRegisters a handler for when the Future successfully completes.
Fail
IsFailedReturns if the Future has failed.
GetFailureReturns aFuture.Failure object if the future has failed. Throws an exception if the Future did not fail.
TryGetFailureAttempts to get theFuture.Failure object the Future failed with.
OnFailRegisters a handle for when the Future fails.
Cancel
IsCancelledReturns if the Future was cancelled.
CancelCancels the Future.
Misc
LinkToLinks the Future to a BeauRoutine. If the Future is cancelled, the BeauRoutine will stop. If the BeauRoutine stops before the Future is completed, the Future will fail.
WaitWaits for the Future to no longer be in progress.

Future Utilities

BeauRoutine contains methods for creating Futures for simple tasks.

FunctionFuture TypeDescription
Download from URL
Future.Download.WWWWWWDownloads and completes with aWWW.
Future.Download.UnityWebRequestUnityWebRequestDownloads and completes with a UnityWebRequest.
Future.Download.TextStringDownloads and completes with text from a WWW/UnityWebRequest.
Future.Download.BytesByte[]Downloads and completes with a byte array from a WWW/UnityWebRequest.
Future.Download.TextureTexture2DDownloads and completes with a texture from a WWW/UnityWebRequest.
Future.Download.AudioClipAudioClipDownloads and completes with an audio clip from a WWW/UnityWebRequest.
Loading Resources
Future.Resources.LoadAsync<T>T (Object)Wrapper for Unity'sResources.LoadAsync. Loads an asset from the Resources folder asynchronously.
Function Calls
Future.Call.Func<T>TCompletes with the return value of the given function.
Future.Call.Resolve<T>TCreates and passes a future into the given function for it to complete or fail.
Shortcuts
Future.CreateLinked<T>TCreates a Future and starts a BeauRoutine with given IEnumerator function and the future as its first argument.

Tween Shortcuts

Generic tween shortcuts currently exist for the following types:

TypeFunction
FloatTween.Float
Tween.ZeroToOne
Tween.OneToZero
IntegerTween.Int
Vector2Tween.Vector
Vector3Tween.Vector
Vector4Tween.Vector
RectTween.Rect
RectOffsetTween.RectOffset
QuaternionTween.Quaternion
ColorTween.Color
AnimationCurveTween.FloatCurve
GradientTween.Gradient

Tween extension methods currently exist for the following types:

TypePropertyFunction
TransformPositionMoveTo,MoveToWithSpeed
ScaleScaleTo,SquashStretchTo
RotationRotateTo,LookAt
TransformTransformTo
RectTransformAnchored PositionAnchorPosTo
AnchorsAnchorTo
Size DeltaSizeDeltaTo
PivotPivotTo
RectTransformRectTransformTo
AudioSourceVolumeVolumeTo
PitchPitchTo
PanPanTo
CameraOrthographic SizeOrthoSizeTo
Field of ViewFieldOfViewTo
Background ColorBackgroundColorTo,BackgroundGradient
Rendering
SpriteRendererColor/AlphaColorTo,FadeTo,Gradient
TextMeshColor/Alpha PropertyColorTo,FadeTo,Gradient
MaterialColor/Alpha PropertyColorTo,FadeTo,Gradient
Float PropertyFloatTo
Vector4 PropertyVectorTo
LightRangeRangeTo
IntensityIntensityTo
Spotlight AngleSpotAngleTo
Shadow StrengthShadowStrengthTo
ColorColorTo,Gradient
SkinnedMeshRendererBlend Shape WeightBlendShapeTo
Canvas
CanvasGroupAlphaFadeTo
CanvasRendererColor/AlphaColorTo,FadeTo,Gradient
GraphicColor/AlphaColorTo,FadeTo,Gradient
ImageFill AmountFillTo
RawImageUV RectUVRectTo,UVRectShift
ScrollRectNormalized PositionNormalizedPosTo
SliderValueValueTo
Normalized ValueNormalizedValueTo
ScrollbarValueValueTo
SizeSizeTo
Layout
LayoutElementMin Width/HeightMinSizeTo
Preferred Width/HeightPreferredSizeTo
Flexible Width/HeightFlexibleSizeTo
LayoutGroupPaddingPaddingTo
HorizontalOrVerticalLayoutGroupSpacingSpacingTo
GridLayoutGroupSpacingSpacingTo
Cell SizeCellSizeTo
BeauRoutine
RoutineTime ScaleTimeScaleTo
RoutineIdentityTime ScaleTimeScaleTo

Tween Modifiers

These functions will modify Tween objects. Do not call once the Tween has started.

FunctionDescription
Modifying Output
EaseApplies a smoothing function or AnimationCurve to the Tween.
WaveApplies a wave function to the Tween.
FromStart and end values are reversed. Tween runs from end to start.
To[Default] Tween runs from start to end.
Looping
LoopTween will loop, with an optional number of loops.
YoyoTween will reach the end value, then repeat from end to start.
YoyoLoopTween will yoyo and loop, with an optional number of loops.
Once[Default] Tween will play once.
Timing
DurationSets the duration, in seconds, of a single cycle.
RandomizeStarts the Tween from a random position in its timeline.
StartsAtStarts the Tween from a set position in its timeline.
DelayByStarts the Tween after a certain amount of seconds have elapsed.
Events
OnStartRegisters a function called when the Tween starts up.
OnUpdateRegisters a function called every frame while the Tween is running.
OnCompleteRegisters a function called when the Tween ends.
Cancel Behavior
RevertOnCancelTween will revert back to starting value if cancelled mid-execution.
ForceOnCancelTween will skip to its end value if cancelled mid-execution.
KeepOnCancel[Default] Tween will keep its current value if cancelled mid-execution.
Playing
PlayStarts a Routine to play the Tween. Shortcut forRoutine.Start( tween ) orRoutine.Start( host, tween ).

Utilities

Components

ComponentDescription
RoutineIdentityProvides per-object time scaling and pausing.
RoutineBootstrapConfigures BeauRoutine settings on Awake.

Classes

ClassDescription
TransformStateRecords the state of a transform's properties in the given space. Can also be reapplied to transforms. Useful for resetting a transform to its original state.
RectTransformStateRecords the state of a RectTransform's properties. Can also be reapplied to RectTransforms. Useful for resetting a transform to its original state, particularly before or after an animation.

Functions

FunctionExtension Method?Description
Tween
Tween.SetPooledEnables Tween pooling. This will reuse Tween instances when possible to reduce garbage generation.
TweenUtil
TweenUtil.EvaluateCurveEvaluates an easing function for a given percentage.
TweenUtil.EvaluateMirroredCurveEvaluates an easing function, mirrored in its progression rate (in becomes out, out becomes in, etc), for a given percentage.
TweenUtil.LerpReturns an interpolation percentage, corrected for delta time.
TweenUtil.LerpDecayReturns a decay multiplier, corrected for delta time.
TweenUtil.SetDefaultLerpPeriodSets the default lerp period for use inTweenUtil.Lerp andTweenUtil.LerpDecay
TweenUtil.SetDefaultLerpPeriodByFramerateSets the default lerp period for use inTweenUtil.Lerp andTweenUtil.LerpDecay to1 / framerate.
TransformUtil
TransformUtil.GetPositionTransformReturns the position of a transform in the given space along the given axes.
TransformUtil.GetPositionAxisTransformReturns the position of transform in the given space for the given single axis.
Transformutil.SetPositionTransformSets the position of a transform in the given space along the given axes.
TransformUtil.GetScaleTransformReturns the scale of a transform along the given axes.
TransformUtil.GetScaleAxisTransformReturns the scale of transform for the given single axis.
Transformutil.SetScaleTransformSets the scale of a transform along the given axes.
TransformUtil.GetRotationTransformReturns the euler rotation of a transform in the given space along the given axes.
TransformUtil.GetRotationAxisTransformReturns the euler rotation of transform in the given space for the given single axis.
Transformutil.SetRotationTransformSets the euler rotation of a transform in the given space along the given axes.
TransformUtil.GetAnchorPosRectTransformReturns the anchored position of a RectTransform along the given axes.
TransformUtil.GetAnchorPosAxisRectTransformReturns the anchored position of a RectTransform for the given single axis.
Transformutil.SetAnchorPosRectTransformSets the anchored position of a RectTransform along the given axes.
TransformUtil.GetSizeDeltaRectTransformReturns the sizeDelta of a RectTransform along the given axes.
TransformUtil.GetSizeDeltaAxisRectTransformReturns the sizeDelta of a RectTransform for the given single axis.
Transformutil.SetSizeDeltaRectTransformSets the sizeDelta of a RectTransform along the given axes.
VectorUtil
VectorUtil.GetAxisReturns the value of a vector along the given axis.
VectorUtil.CopyFromCopies values from one vector to another for the given axes.
VectorUtil.AddAdds one vector to another, applying an optional coefficient to the added vector.
VectorUtil.SubtractSubtracts one vector from another, applying an optional coefficient to the subtracted vector.

About

Coroutine and tweening framework for Unity3D

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp