{"id":16209912,"url":"https://github.com/annulusgames/magictween","last_synced_at":"2025-10-17T04:31:21.356Z","repository":{"id":193470784,"uuid":"688856456","full_name":"AnnulusGames/MagicTween","owner":"AnnulusGames","description":"Extremely fast, GC-free and customizable tween library implemented with Unity ECS","archived":false,"fork":false,"pushed_at":"2024-06-16T02:55:54.000Z","size":9899,"stargazers_count":489,"open_issues_count":6,"forks_count":28,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-01-26T08:11:13.186Z","etag":null,"topics":["animation","ease","easing","ecs","tween","tweening","unity"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AnnulusGames.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-08T08:47:51.000Z","updated_at":"2025-01-25T13:05:23.000Z","dependencies_parsed_at":"2024-01-04T05:34:41.275Z","dependency_job_id":"0bfbdcf0-54f4-43bf-9fdc-32c15c29ba6a","html_url":"https://github.com/AnnulusGames/MagicTween","commit_stats":null,"previous_names":["annulusgames/magictween"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnnulusGames%2FMagicTween","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnnulusGames%2FMagicTween/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnnulusGames%2FMagicTween/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AnnulusGames%2FMagicTween/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AnnulusGames","download_url":"https://codeload.github.com/AnnulusGames/MagicTween/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236772551,"owners_count":19202283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","ease","easing","ecs","tween","tweening","unity"],"created_at":"2024-10-10T10:34:03.524Z","updated_at":"2025-10-17T04:31:21.349Z","avatar_url":"https://github.com/AnnulusGames.png","language":"C#","readme":"# Magic Tween\n Extremely fast, GC-free and customizable tween library implemented with Unity ECS\n\n\u003cimg src=\"https://github.com/AnnulusGames/MagicTween/blob/main/MagicTween/Assets/MagicTween/Documentation~/Header.png\" width=\"800\"\u003e\n\n[![license](https://img.shields.io/badge/LICENSE-MIT-green.svg)](LICENSE)\n\n[日本語版READMEはこちら](README_JA.md)\n\n\u003e [!IMPORTANT]\n\u003e MagicTween has been archived. Please consider migrating to [LitMotion](https://github.com/yn01-dev/LitMotion).\n\n## Overview\n\nMagic Tween is a high-performance tweening library implemented with Unity Entity Component System (ECS).\n\nIn addition to powerful tweening functionality compatible with traditional components, it also offers even higher-performance APIs for ECS.\n\n\u003e [!NOTE]\n\u003e MagicTween is currently provided as an experimental library. If you need a higher performance and stable tween library, I recommend using [LitMotion](https://github.com/AnnulusGames/LitMotion). LitMotion is built with minimal dependencies and a modern design, offering extremely high performance and full functionality.\n\n## Table of Contents\n- [Overview](#overview)\n- [Table of Contents](#table-of-contents)\n- [Features](#features)\n- [Performance](#performance)\n- [Samples](#samples)\n- [Setup](#setup)\n- [Basic Usage](#basic-usage)\n- [Tweening Custom Value](#tweening-custom-value)\n- [Tween Control](#tween-control)\n- [Getting Tween Information](#getting-tween-information)\n- [Adding Settings](#adding-settings)\n- [Callbacks](#callbacks)\n- [DelayedCall / Empty](#delayedcall--empty)\n- [Sequence](#sequence)\n- [Waiting for Tweens Using Coroutines](#waiting-for-tweens-using-coroutines)\n- [Logging](#logging)\n- [Project Settings](#project-settings)\n- [Accelerating Transform Tweens with Jobs](#accelerating-transform-tweens-with-jobs)\n- [TextMesh Pro](#textmesh-pro)\n- [UniRx](#unirx)\n- [UniTask](#unitask)\n- [Creating Custom Tween Plugins](#creating-custom-tween-plugins)\n- [Implementation for ECS](#implementation-for-ecs)\n- [Other Features](#other-features)\n- [Optimization](#optimization)\n- [Experimental Features](#experimental-features)\n- [Known Issues](#known-issues)\n- [Support](#support)\n- [License](#license)\n\n## Features\n\n* High-performance tweening library implemented in ECS.\n* No GC allocation when creating Tween. (Excluding some special tweens)\n* Add extension methods compatible with many components.\n* Transform-optimized fast tween support\n* Tween anything with Tween.To.\n* Apply various settings using method chaining.\n* Create complex animations with Sequences.\n* Add processing via callbacks.\n* Supports Tween waits with coroutines\n* Support for tweening TextMesh Pro.\n* Support for conversion to Observable with UniRx.\n* Support for async/await with UniTask.\n* Create your own type of tween using a custom TweenPlugin.\n* Even higher-performance implementation for ECS.\n\n## Performance\n\n\u003cimg src=\"https://github.com/AnnulusGames/MagicTween/blob/main/MagicTween.Benchmarks/Assets/Documentation~/benchmark_64000_floats.png\" width=\"800\"\u003e\n\nWhen tweening the float values of a regular class with `Tween.To()`, it operates 2 to 5 times faster than other libraries. When tweening the float values within ECS components using `Tween.Entity.To()`, even faster performance can be achieved.\n\nFurthermore, there are no additional GC allocations generated for each tween creation (excluding tweens involving strings).\n\n\u003cimg src=\"https://github.com/AnnulusGames/MagicTween/blob/main/MagicTween.Benchmarks/Assets/Documentation~/benchmark_50000_transform_position.png\" width=\"800\"\u003e\n\nEnabling `MAGICTWEEN_ENABLE_TRANSFORM_JOBS` allows you to create tweens specialized for Transforms. This dramatically improves performance when tweening a large number of Transforms.\n\nFor more details on performance, please refer to the [README](https://github.com/AnnulusGames/MagicTween/blob/main/MagicTween.Benchmarks/README.md) in the `MagicTween.Benchmarks` project.\n\n## Samples\n\nThe `MagicTween.Samples` project includes several samples implemented using Magic Tween. For more details, please refer to the [README](https://github.com/AnnulusGames/MagicTween/blob/main/MagicTween.Samples/README.md) in the project.\n\n## Setup\n\n### Requirement\n\n* Unity 2022.1 or higher\n* Entities 1.0.0 or higher\n* Burst 1.8.8 or higher\n\n### Install\n\n1. Open the Package Manager from Window \u003e Package Manager\n2. \"+\" button \u003e Add package from git URL\n3. Enter the following to install\n\n```\nhttps://github.com/AnnulusGames/MagicTween.git?path=/MagicTween/Assets/MagicTween\n```\n\nor open Packages/manifest.json and add the following to the dependencies block.\n\n```json\n{\n    \"dependencies\": {\n        \"com.annulusgames.magic-tween\": \"https://github.com/AnnulusGames/MagicTween.git?path=/MagicTween/Assets/MagicTween\"\n    }\n}\n```\n\n### Migration Guides\n\nMagic Tween is an actively developed library, and there is a possibility of breaking changes with each version. For information on migrating from previous versions, please refer to the [Migration Guides](migration.md).\n\n## Basic Usage\n\nBy introducing Magic Tween, numerous extension methods for creating tweens on traditional Unity components are added. Below is an example of animating the position of a Transform using these extension methods:\n\n```cs\n// Move from the current position to (1, 2, 3) over 5 seconds\ntransform.TweenPosition(\n    new Vector3(1f, 2f, 3f), // Target value\n    5f // Duration of the change\n);\n\n// Move from (0, 0, 0) to (1, 2, 3) over 5 seconds\ntransform.TweenPosition(\n    new Vector3(0f, 0f, 0f), // Starting value\n    new Vector3(1f, 2f, 3f), // Target value\n    5f // Duration of the change\n);\n```\n\n\u003e **Warning**\n\u003e Do not play multiple tweens on the same parameter simultaneously. This can lead to unexpected behavior due to overlapping value changes. (Tweens on different axes, such as TweenPositionX and TweenPositionY, will work.)\n\n\u003e **Warning**\n\u003e Creating tweens in the editor is not supported.\n\n### Extension Methods\n\nMagic Tween provides extension methods for most components included in Unity. These extension methods allow for more concise and optimized code compared to `Tween.To()`. It's recommended to use extension methods when available.\n\nYou can find a list of available extension methods [here](https://github.com/AnnulusGames/MagicTween/wiki) (a wiki is currently being created).\n\n### Classification\n\nThe extension methods added for tweening are classified into several categories:\n\n| Method Name | Description |\n| ----------- | ----------- |\n| Tween...    | Creates a tween for a specific field/property. |\n| Punch...    | Creates a tween to vibrate the value of a specific field/property. |\n| Shake...    | Creates a tween to randomly vibrate the value of a specific field/property. |\n| Set...      | Adds settings to customize the behavior of the tween. |\n| On...       | Adds callbacks at specific timings of the tween. |\n| Log...      | Outputs information about the tween and its callbacks to the console. |\n| WaitFor...  | Waits for the tween in a coroutine. |\n| AwaitFor... | Awaits the tween using async/await. Requires UniTask to use this extension method. |\n\n## Tweening Custom Value\n\nYou can animate custom value using the `Tween.To()` method:\n\n```cs\nfloat foo;\n\nfloat endValue = 10f;\nfloat duration = 2f;\n\nTween.To(\n    () =\u003e foo,\n    x =\u003e foo = x,\n    endValue,\n    duration\n);\n```\n\nIf you want to use only values without defining variables, you can use `Tween.FromTo()`:\n\n```cs\nfloat startValue = 0f;\nfloat endValue = 10f;\nfloat duration = 2f;\n\nTween.FromTo(\n    x =\u003e Debug.Log(\"current value: \" + x),\n    startValue,\n    endValue,\n    duration\n);\n```\n\nYou can create tweens that follow a curve passing through multiple points using `Tween.Path()`:\n\n```cs\nVector3 foo;\n\nVector3[] points;\nfloat duration = 2f;\n\nTween.Path(\n    () =\u003e foo,\n    x =\u003e foo = x,\n    points,\n    duration\n);\n```\n\n### Avoiding Allocations\n\nThe `To` and `FromTo` methods mentioned above cause allocations because they capture external variables. To reduce unnecessary allocations when performing tweens on an object, you can specify the target object as the first argument to avoid lambda expression allocations:\n\n```cs\n// A class with a field named 'foo'\nExampleClass target;\n\nfloat endValue = 10f;\nfloat duration = 2f;\n\n// Pass the object as the first argument to avoid allocations\nTween.To(\n    target,\n    obj =\u003e obj.foo,\n    (obj, x) =\u003e obj.foo = x,\n    endValue,\n    duration\n);\n```\n\n## Tween Control\n\nIn general, created tweens play and are destroyed automatically, so there's no need for explicit control. However, there are situations where manual control is necessary, such as when dealing with tweens that loop indefinitely. In such cases, you can control tweens through the `Tween` struct:\n\n```cs\nTween tween = transform.TweenPosition(Vector3.up, 2f);\n\n// Start/resume the tween\ntween.Play();\n\n// Pause the tween\ntween.Pause();\n\n// Restart the tween from the beginning\ntween.Restart();\n\n// Complete the tween\ntween.Complete();\n\n// Kill the tween\ntween.Kill();\n\n// Complete and kill the tween\ntween.CompleteAndKill();\n```\n\nYou can also perform operations on all playing tweens collectively. If you specify an ID as an argument, you can target only the tweens with matching IDs:\n\n```cs\n// Kill all playing tweens\nTween.KillAll();\n\n// Complete all tweens with an ID of 1\nTween.CompleteAll(1);\n\n// Pause all tweens with an ID of \"Alpha\"\nTween.PauseAll(\"Alpha\");\n```\n\n## Getting Tween Information\n\nYou can check if a tween is currently active using `IsActive()`. When performing operations on tweens, it's a good practice to check for activity, especially when there's a possibility that the tween may not be active:\n\n```cs\n// Kill the tween if it's active\nif (tween.IsActive()) tween.Kill();\n```\n\nYou can also retrieve the duration of a tween using `GetDuration()`:\n\n```cs\nfloat duration = tween.GetDuration();\n```\n\n## Adding Settings\n\nYou can customize the behavior of a tween using the Set methods. These methods can be chained together for concise code. The following code is an example of applying custom settings to a tween:\n\n```cs\ntransform.TweenLocalScale(Vector3.one * 2f, 5f)\n    .SetEase(Ease.OutSine) // Set the easing function to OutSine\n    .SetLoops(3, LoopType.Restart) // Repeat 3 times with restart behavior\n    .SetDelay(1f); // Delay the start by 1 second\n```\n\n### SetEase\n\nSets the easing function to use for the tween. You can also use your own easing function by passing an `AnimationCurve`.\n\n### SetLoops\n\nSets the number of times the tween should loop. By default, it's set to 1. You can create a tween that loops infinitely by setting it to -1. You can also specify the loop behavior using the second argument, `LoopType`.\n\n### SetPlaybackSpeed\n\nSets the playback speed of the tween. The default is 1, and negative values are not supported.\n\n### SetDelay\n\nSets a delay in seconds before the tween starts.\n\n### SetIgnoreTimeScale\n\nIgnores the effect of TimeScale.\n\n### SetRelative\n\nSets the end value as a relative value from the start value.\n\n### SetInvert\n\nSwaps the start and end values. You can adjust the behavior using the `InvertMode`.\n\n| InvertMode | Behavior |\n| - | - |\n| InvertMode.None | Moves from the start value to the end value as usual. |\n| InvertMode.Immediate | Moves to the end value as soon as the tween starts and then transitions towards the start value. |\n| InvertMode.AfterDelay | Waits until the tween starts, then moves to the end value and transitions towards the start value. |\n\n### SetId\n\nAssigns an ID to the tween. This allows you to operate on tweens with the same ID in bulk when performing operations like KillAll. You can pass an int or a string with a length of 32 bytes or less as an ID (default is int 0 or an empty string).\n\n### SetLink\n\nLinks the tween's lifecycle to a GameObject. You can change the behavior by setting the `LinkBehaviour` as the second argument. However, regardless of the option set, Kill will be called on OnDestroy.\n\n### SetAutoPlay\n\nSets whether the tween should automatically play (default is true). If set to false, you need to manually call `Play()` to start the tween.\n\n### SetAutoKill\n\nSets whether the tween should automatically be killed at the end (default is true). If set to false, you need to manually call `Kill()` to remove the tween. This option is useful when you want to reuse the same tween multiple times.\n\n### SetFrequency (Punch, Shake)\n\nAvailable options for Punch and Shake tweens to set the frequency of vibration (default is 10).\n\n### SetDampingRatio (Punch, Shake)\n\nAvailable options for Punch and Shake tweens to set the damping ratio of vibration. A value of 1 will completely dampen the vibration at the end, and a value of 0 will result in no damping (default is 1).\n\n### SetRandomSeed (Shake)\n\nAvailable option for Shake tweens to set the seed value for the random numbers used in vibration. This option must be applied before playback.\n\n### SetPathType (Path)\n\nAvailable option for Path-based tweens to set how the points are connected.\n\n| PathType | Behavior |\n| - | - |\n| PathType.Linear | Connects each point using a straight line. |\n| PathType.CatmullRom | Connects each point using a Catmull-Rom spline curve. |\n\n### SetClosed (Path)\n\nAvailable option for Path-based tweens to set whether the path is closed, allowing it to return to the starting point.\n\n### SetRoundingMode (int, int2, int3, int4, long)\n\nSets the rounding mode for decimal values. This option is applicable only to integer-based types.\n\n| RoundingMode | Behavior |\n| - | - |\n| RoundingMode.ToEven | Default setting. Rounds the value to the nearest integer, and if the value is midway, it rounds to the nearest even integer. |\n| RoundingMode.AwayFromZero | Rounds the value to the nearest integer, and if the value is midway, it rounds away from zero. |\n| RoundingMode.ToZero | Rounds the value towards zero. |\n| RoundingMode.ToPositiveInfinity | Rounds the value towards positive infinity. |\n| RoundingMode.ToNegativeInfinity | Rounds the value towards negative infinity. |\n\n### SetScrambleMode (string)\n\nAllows you to fill unrevealed characters with random characters. This option is only applicable to string tweens.\n\n| ScrambleMode | Behavior |\n| - | - |\n| ScrambleMode.None | Default setting. Nothing is displayed for unrevealed parts. |\n| ScrambleMode.Uppercase | Fills unrevealed parts with random uppercase letters. |\n| ScrambleMode.Lowercase | Fills unrevealed parts with random lowercase letters. |\n| ScrambleMode.Numerals | Fills unrevealed parts with random numbers. |\n| ScrambleMode.All | Fills unrevealed parts with random uppercase letters, lowercase letters, or numbers. |\n| (ScrambleMode.Custom) | Fills unrevealed parts with random numbers from the specified string. This option cannot be explicitly set and is determined when passing a string as an argument to SetScrambleMode. |\n\n### SetRichTextEnabled (string)\n\nEnables RichText support, allowing text with RichText tags to be animated with proper character advancement. This option is only applicable to string tweens.\n\n## Callbacks\n\nWhen you want to perform some actions at specific times, such as the start or completion of a tween, you can use the On-series methods. Callback methods, like other settings, can be written using method chaining.\n\n```cs\ntransform.TweenPosition(new Vector3(1f, 2f, 3f), 5f)\n    .SetLoops(5)\n    .OnUpdate(() =\u003e Debug.Log(\"update\"))\n    .OnStepComplete(() =\u003e Debug.Log(\"step complete\"))\n    .OnComplete(() =\u003e Debug.Log(\"complete\"));\n```\n\n\u003e **Note**\n\u003e Enabling one or more callbacks can reduce performance during playback. In most cases, the impact on performance is minimal, but it's recommended to avoid using callbacks when creating a large number of tweens.\n\n### OnPlay\n\nCalled when the tween starts playing. Unlike OnStart, it ignores delays set with SetDelay and is also called if Play is invoked after a pause.\n\n### OnStart\n\nCalled when the tween begins its operation. If a delay is set with SetDelay, it is called after the delay has passed.\n\n### OnUpdate\n\nCalled every frame during the tween's playback.\n\n### OnStepComplete\n\nCalled at the end of each loop when SetLoops is configured.\n\n### OnComplete\n\nCalled when the tween is completed.\n\n### OnKill\n\nCalled when the tween is killed.\n\n### Avoiding Allocations\n\nSimilar to `Tween.To()` and `Tween.FromTo()`, you can avoid lambda expression allocations by passing the target instance as the first argument.\n\n```cs\n// A class with a field named \"foo\"\nExampleClass target;\n\nfloat endValue = 10f;\nfloat duration = 2f;\n\n// Avoiding lambda expression allocation by passing \"target\" to \"OnUpdate\"\nTween.To(target, obj =\u003e obj.foo, (obj, x) =\u003e obj.foo = x, endValue, duration)\n    .OnUpdate(target, obj =\u003e Debug.Log(obj.foo));\n```\n\n## DelayedCall / Empty\n\nYou can create a tween that performs a specified action after a certain delay using `Tween.DelayedCall()`.\n\n```cs\n// Display a log after 3 seconds\nTween.DelayedCall(3f, () =\u003e Debug.Log(\"delayed call\"));\n```\n\nAdditionally, you can create an empty tween using `Tween.Empty()`.\n\n```cs\n// A tween that completes after 3 seconds\nTween.Empty(3f);\n\n// DelayedCall() internally calls the following code\nTween.Empty(3f)\n    .OnStepComplete(() =\u003e Debug.Log(\"delayed call\"))\n    .OnComplete(() =\u003e Debug.Log(\"delayed call\"));\n```\n\n## Sequence\n\nA Sequence is a feature used to group multiple tweens together. By using Sequences, you can easily create complex animations by combining multiple tweens.\n\n### Creating a Sequence\n\nYou can obtain a new Sequence from `Sequence.Create()`:\n\n```cs\n// Create a new Sequence\nSequence sequence = Sequence.Create();\n```\n\n### Adding Tweens\n\nNext, you add the tweens you want to include in the Sequence. There are various methods available to add tweens to a Sequence. By using these methods, you can combine tweens and build complex animations.\n\nSequences can be nested regardless of their hierarchy. Options and callbacks such as `SetDelay` and `SetLoops` will also work for the Sequence after it has been added.\n\n### Append\n\nThe `Append()` method adds tweens to the end of the Sequence. The added tweens will play in sequence when you play the Sequence.\n\n```cs\n// Append a tween to the end\nsequence.Append(transform.TweenPosition(new Vector3(1f, 0f, 0f), 2f))\n    .Append(transform.TweenPosition(new Vector3(1f, 3f, 0f), 2f));\n```\n\nYou can use `AppendInterval()` and `AppendCallback()` to add delays or callbacks:\n\n```cs\n// Append a delay to the end\nsequence.AppendInterval(1f);\n\n// Append a callback to the end\nsequence.AppendCallback(() =\u003e Debug.Log(\"Hello!\"));\n```\n\n### Prepend\n\nIf you want to add tweens to the beginning, you can use `Prepend()`. In this case, the tweens already added will move back by the duration of the new prepend tween.\n\n```cs\n// Prepend a tween to the beginning\nsequence.Prepend(transform.TweenPosition(new Vector3(1f, 0f, 0f), 2f));\n```\n\nYou can also use `PrependInterval()` and `PrependCallback()`:\n\n```cs\n// Prepend a delay to the beginning\nsequence.PrependInterval(1f);\n\n// Prepend a callback to the beginning\nsequence.PrependCallback(() =\u003e Debug.Log(\"Hello!\"));\n```\n\n### Join\n\nTo concatenate a tween with the ones added before it, you can use `Join()`. Tweens added with `Join()` will play concurrently with the previously added tween.\n\n```cs\nsequence.Append(transform.TweenPosition(new Vector3(1f, 0f, 0f), 2f));\n\n// Join with the previous tween\nsequence.Join(transform.TweenPosition(new Vector3(1f, 3f, 0f), 2f));\n```\n\n### Insert\n\nIf you want to insert a tween at an arbitrary point, you can use `Insert()`. The tween added with `Insert()` will operate independently of other tweens and will start playing once it reaches the specified position.\n\n```cs\n// Insert a tween at 1 second from the start\nsequence.Insert(1f, transform.TweenPosition(new Vector3(1f, 0f, 0f), 2f));\n```\n\nYou can also insert callbacks using `InsertCallback()`:\n\n```cs\n// Insert a callback at 1 second from the start\nsequence.InsertCallback(1f, () =\u003e Debug.Log(\"Hello!\"));\n```\n\n### Implicit Conversion to Tween\n\nA `Sequence` can be implicitly converted to a `Tween`, allowing you to assign it directly:\n\n```cs\nSequence sequence = Sequence.Create();\n\n// Can be assigned directly to a Tween variable\nTween tween = sequence;\n```\n\n### Usage Considerations\n\nHere are some important points to keep in mind when using Sequences:\n\n* You cannot add tweens to a Sequence while it is playing.\n* You cannot add tweens with infinite loops to a Sequence.\n* Once a tween is added to a Sequence, it becomes locked, and you cannot access it individually. Be cautious, as you cannot manipulate the individual tweens within a Sequence.\n* You cannot include the same tween in multiple Sequences.\n\n## Waiting for Tweens Using Coroutines\n\nYou can easily wait for tweens by using coroutines. To wait for a tween, you can use the `WaitFor...` methods. This allows you to wait until specific events like `Complete` or `Pause` occur.\n\n```cs\nIEnumerator ExampleCoroutine()\n{\n    // Wait for the completion of the tween\n    yield return Tween.Empty(3f).WaitForComplete();\n\n    // Wait until the end of one loop\n    yield return transform.TweenPosition(Vector3.one, 1f)\n        .SetLoops(3)\n        .WaitForStepComplete();\n}\n```\n\n## Logging\n\nIf you want to perform logging of Tween callbacks and values for debugging purposes, you can easily achieve this using dedicated extension methods. Note that these logs will only be displayed if `MagicTweenSettings`' `LoggingMode` is set to `Full`.\n\n```cs\nusing MagicTween;\nusing MagicTween.Diagnostics; // Enable debug extension methods\n\n// Log specific callback\ntransform.TweenPosition(Vector3.up, 5f)\n    .LogOnUpdate();\n\n// Log all callbacks together\ntransform.TweenEulerAngles(new Vector3(0f, 0f, 90f), 5f)\n    .LogCallbacks();\n\n// You can also assign a name for identification\ntransform.TweenLocalScale(Vector3.one * 2f, 5f)\n    .LogCallbacks(\"Scale\");\n\nfloat foo;\n// You can also log values (current value per frame)\nTween.To(() =\u003e foo, x =\u003e foo = x, 5f, 10f)\n    .LogValue();\n```\n\n## Project Settings\n\nYou can customize Tween's initial settings and logging preferences.\n\n### Creating MagicTweenSettings\n\nCreate a `MagicTweenSettings` asset to store your configuration by navigating to `Assets \u003e Create \u003e Magic Tween \u003e Magic Tween Settings`.\n\n\u003e **Note**\n\u003e The created `MagicTweenSettings` will be automatically added to the project's Preload Assets. If the settings are not being loaded, ensure that `MagicTweenSettings` is included in the Preload Assets.\n\n### Logging Mode\n\nSet whether logging is enabled or not.\n\n| LoggingMode | Behavior |\n| - | - |\n| LoggingMode.Full | Display all logs, including Log-related extension methods, in the Console. |\n| LoggingMode.WarningsAndErrors | Display only warnings and errors in the Console. |\n| LoggingMode.ErrorsOnly | Display only errors in the Console. |\n\n### Capture Exceptions\n\nWhen set to \"On,\" exceptions that occur internally in Tweens will be logged as warnings. When set to \"Off,\" exceptions will be logged as regular exceptions.\n\n### Default Tween Parameters\n\nYou can modify the default settings for Tweens.\n\n### Changing Settings from Script\n\nYou can access these settings from the `MagicTweenSettings` class in your script.\n\n```cs\n// Change Logging Mode from script\nMagicTweenSettings.loggingMode = LoggingMode.ErrorsOnly;\n```\n\n## Accelerating Transform Tweens with Jobs\n\nStarting from v0.2, an option to accelerate Transform tweens using `IJobParallelForTransform` has been added. This option is disabled by default and can be enabled by adding `MAGICTWEEN_ENABLE_TRANSFORM_JOBS` to the `Project Settings \u003e Scripting Define Symbols` section.\n\nOnce added, the acceleration by `IJobParallelForTransform` will be applied by simply manipulating Transforms using the usual extension methods.\n\n\u003cimg src=\"https://github.com/AnnulusGames/MagicTween/blob/main/MagicTween/Assets/MagicTween/Documentation~/benchmark_transform_tween_job.png\" width=\"800\"\u003e\n\nThe performance comparison is shown in the graph. When tweening 50,000 Transforms, there is an acceleration of nearly 1.7x.\n\n## TextMesh Pro\n\nMagic Tween supports TextMesh Pro (TMP) and allows you to tween text characters individually using the `TweenChar` extension methods. Here's how you can use it:\n\n```cs\nTMP_Text tmp;\n\n// GetCharCount retrieves the number of tweenable characters\nfor (int i = 0; i \u003c tmp.GetCharCount(); i++)\n{\n    tmp.TweenCharScale(i, Vector3.zero).SetInvert().SetDelay(i * 0.07f);\n}\n```\n\nYou can stop the tweens associated with TMP_Text and reset the text's decoration to its initial state using `ResetCharTweens()`:\n\n```cs\n// Stop the character tweens and reset the decoration to the initial state\ntmp.ResetCharTweens();\n```\n\nCharacter tweens are powered by the `TMPTweenAnimator` class internally, which you can access using `GetTMPTweenAnimator()`:\n\n```cs\n// Get the internal TMPTweenAnimator\nTMPTweenAnimator tmpAnimator = tmp.GetTMPTweenAnimator();\n\n// Extension methods for TMP_Text use methods from TMPTweenAnimator internally\ntmpAnimator.TweenCharOffset(0, Vector3.up);\n\n// You can directly set parameters for each character using SetChar**\ntmpAnimator.SetCharScale(1, Vector3.one * 2f);\ntmpAnimator.SetCharColor(1, Color.red);\n\n// ResetCharTweens() equivalent\ntmpAnimator.Reset();\n\n// GetCharCount() equivalent\ntmpAnimator.GetCharCount();\n```\n\n## UniRx\n\nBy integrating UniRx, you can convert Tween callbacks and Tween operations into Observables.\n\n### Converting Callbacks to Observables\n\nYou can use methods like `OnUpdateAsObservable()` to convert Tween callbacks into Observables. For example:\n\n```cs\nfloat foo;\n\nTween.To(() =\u003e foo, x =\u003e foo = x, 10f, 10f)\n    .OnUpdateAsObservable()\n    .Subscribe(_ =\u003e\n    {\n        Debug.Log(\"update!\");\n    });\n```\n\n### Converting Tweens to Observables\n\nYou can use `ToObservable()` to transform a Tween into an Observable that emits values each frame. For example:\n\n```cs\nTween.FromTo(0f, 10f, 10f, null)\n    .ToObservable()\n    .Where(x =\u003e x \u003e= 5f)\n    .Subscribe(x =\u003e\n    {\n        Debug.Log(\"current value: \" + x);\n    });\n```\n\n## UniTask\n\nBy integrating UniTask, you can use async/await to handle Tween waiting operations.\n\n```cs\nvar tween = transform.TweenPosition(Vector3.up, 2f);\n\n// You can directly await the Tween (waits until the Tween is killed)\nawait tween;\n```\n\nYou can use `AwaitForKill()` and pass a `CancellationToken` to handle cancellation.\n\n```cs\n// Create a CancellationTokenSource\nvar cts = new CancellationTokenSource();\n\n// Wait until the Tween is killed, passing the CancellationToken\nawait transform.TweenPosition(Vector3.up, 2f)\n    .AwaitForKill(cancellationToken: cts.Token);\n```\n\nYou can also wait for other events like completion using `AwaitForComplete()` or `AwaitForPause()`.\n\n```cs\n// Wait until the Tween completes\nawait transform.TweenPosition(Vector3.up, 2f).AwaitForComplete();\n```\n\nFurthermore, you can specify the `CancelBehaviour` to determine the behavior on cancellation.\n\n```cs\nvar cts = new CancellationTokenSource();\n\n// On cancellation, call Complete and throw OperationCanceledException\nawait transform.TweenPosition(Vector3.up, 2f)\n    .AwaitForComplete(CancelBehaviour.CompleteAndCancelAwait, cts.Token);\n```\n\n| CancelBehaviour | Behavior on Cancellation |\n| - | - |\n| CancelBehaviour.Kill | Calls the Kill method. |\n| CancelBehaviour.Complete | Calls the Complete method. |\n| CancelBehaviour.CompleteAndKill | Calls both Complete and Kill methods. |\n| CancelBehaviour.CancelAwait | Throws an OperationCanceledException without calling Complete or Kill. |\n| CancelBehaviour.KillAndCancelAwait | Default behavior. Calls Kill and throws an OperationCanceledException. |\n| CancelBehaviour.CompleteAndCancelAwait | Calls Complete and throws an OperationCanceledException. |\n| CancelBehaviour.CompleteAndKillAndCancelAwait | Calls both Complete and Kill methods and throws an OperationCanceledException. |\n\n## Creating Custom Tween Plugins\n\nMagic Tween supports most primitive types and Unity.Mathematics types for tweens, and in most cases, you won't need to create extensions. However, there may be situations where you want to extend for finer control.\n\nMagic Tween provides two interfaces, `ICustomTweenPlugin` and `ITweenOptions`, for extending types:\n\n### TweenPlugin\n\nA TweenPlugin is a feature for extending specific types into tweens. Implementing this allows you to pass custom types to tweens.\n\nHere's an example of implementing a TweenPlugin for `double` tweens:\n\n```cs\n// You need to add the TweenPluginAttribute\n// This lets the Source Generator recognize the type and generate the necessary code\n[TweenPlugin]\n// Define a struct implementing ICustomTweenPlugin with type arguments for the tweened value and associated TweenOptions (NoOptions if not needed)\npublic readonly struct DoubleTweenPlugin : ICustomTweenPlugin\u003cdouble, NoOptions\u003e\n{\n    // Write calculation logic inside the Evaluate function\n    public double Evaluate(in double startValue, in double endValue, in NoOptions options, in TweenEvaluationContext context)\n    {\n        // If SetRelative(true) is set, resolve the end value as a relative value\n        var resolvedEndValue = context.IsRelative ? startValue + endValue : endValue;\n\n        // If SetInvert(true) is set, swap start and end values\n        // Calculate the current value based on context.Progress (0 to 1)\n        if (context.IsInverted) return math.lerp(resolvedEndValue, startValue, context.Progress);\n        else return math.lerp(startValue, resolvedEndValue, context.Progress);\n    }\n}\n```\n\nTweenPlugins do not retain state. If you want to hold additional settings, create custom TweenOptions.\n\n### TweenOptions\n\nTo add custom settings to your tween, define a struct implementing `ITweenOptions`. Here's an example of TweenOptions for integer tweens:\n\n```cs\n// Define a struct implementing ITweenOptions\npublic struct IntegerTweenOptions : ITweenOptions\n{\n    public RoundingMode roundingMode;\n}\n\npublic enum RoundingMode : byte\n{\n    ToEven,\n    AwayFromZero,\n    ToZero,\n    ToPositiveInfinity,\n    ToNegativeInfinity\n}\n```\n\nYou can set your custom TweenOptions when defining the TweenPlugin.\n\n### Using Custom TweenPlugins\n\nTo use your custom TweenPlugin in a tween, you can use `Tween.To()` or `Tween.FromTo()`:\n\n```cs\ndouble currentValue = 0.0;\n\n// Create a tween with custom TweenOptions and TweenPlugins\nTween.FromTo\u003cdouble, NoOptions, DoubleTweenPlugin\u003e(x =\u003e currentValue = x, startValue, endValue, duration);\n```\n\nIf you've specified custom TweenOptions, you can modify them using `SetOptions()`. You can also retrieve the currently set TweenOptions values using `GetOptions()`.\n\n```cs\npublic struct CustomOptions : ITweenOptions\n{\n    ...\n}\n\n// Modify custom options for the tween using SetOptions\ntween.SetOptions(new CustomOptions() { ... });\n\n// Retrieve options values using GetOptions\nvar options = tween.GetOptions();\n```\n\n### Built-in TweenPlugins/TweenOptions\n\nMagic Tween includes several built-in TweenPlugins and TweenOptions.\n\nHere's a list of available TweenPlugins and their corresponding TweenOptions (there are additional specialized TweenPlugins/TweenOptions for specific tweens, but they are not meant for external use):\n\n| Type | TweenPlugin | Corresponding TweenOptions |\n| ---- | ----------- | -------------------------- |\n| float | FloatTweenPlugin | NoOptions |\n| float2 | Float2TweenPlugin | NoOptions |\n| float3 | Float3TweenPlugin | NoOptions |\n| float4 | Float4TweenPlugin | NoOptions |\n| double | DoubleTweenPlugin | NoOptions |\n| double2 | Double2TweenPlugin | NoOptions |\n| double3 | Double3TweenPlugin | NoOptions |\n| double4 | Double4TweenPlugin | NoOptions |\n| int | IntTweenPlugin | IntegerTweenOptions |\n| int2 | Int2TweenPlugin | IntegerTweenOptions |\n| int3 | Int3TweenPlugin | IntegerTweenOptions |\n| int4 | Int4TweenPlugin | IntegerTweenOptions |\n| long | LongTweenPlugin | IntegerTweenOptions |\n| quaternion | QuaternionTweenPlugin | NoOptions |\n\n## Implementation for ECS\n\nMagic Tween provides APIs for implementing tweens for ECS, allowing you to create high-performance tweens compared to conventional methods.\n\n### Creating a Translator\n\nWhen tweening values of specific components, you need to create a `Translator` component to apply the current tween value to the target component and a system to execute it.\n\nAs an example, let's create a Translator for tweening the following component:\n\n```cs\npublic struct ExampleComponent : IComponentData\n{\n    public float value;\n}\n```\n\nFirst, define a structure implementing `ITweenTranslator`:\n\n```cs\npublic struct ExampleTranslator : ITweenTranslator\u003cfloat, ExampleComponent\u003e\n{\n    // Apply the value to the component\n    public void Apply(ref ExampleComponent component, in float value)\n    {\n        component.value = value;\n    }\n\n    // Return the current value of the component\n    public float GetValue(ref ExampleComponent component)\n    {\n        return component.value;\n    }\n}\n```\n\nNext, create a system class that inherits from `TweenTranslationSystemBase`. Specify type arguments for the Translator and the TweenPlugin to be used. You can refer to the \"Built-in TweenPlugins/TweenOptions\" table for available TweenPlugins. It's also possible to specify custom TweenPlugins.\n\nThe system class itself doesn't need additional implementation as the core logic is provided in the base class:\n\n```cs\npublic partial class ExampleTweenTranslationSystem : TweenTranslationSystemBase\u003cfloat, NoOptions, FloatTweenPlugins, ExampleComponent, ExampleTranslator\u003e { }\n```\n\nWith this setup, you're ready to tween values.\n\n### Tweening Component Values\n\nTo tween values using the created Translator, use `Tween.Entity.To()` or `Tween.Entity.FromTo()`. Provide the component type and the Translator type as type arguments.\n\n```cs\nvar entity = EntityManager.CreateEntity();\nEntityManager.AddComponent\u003cExampleComponent\u003e(entity);\n\n// Tween the value of ExampleComponent's 'value' to 5 over 10 seconds\nTween.Entity.To\u003cExampleComponent, ExampleTranslator\u003e(entity, 5f, 10f);\n```\n\nJust like regular tweens, you can chain methods to add settings:\n\n```cs\nTween.Entity.FromTo\u003cExampleComponent, ExampleTranslator\u003e(entity, 0f, 5f, 10f)\n    .SetEase(Ease.OutSine)\n    .SetLoops(3, LoopType.Restart)\n    .SetDelay(1f);\n```\n\nYou can also add these tweens to a sequence:\n\n```cs\nvar entity1 = EntityManager.CreateEntity();\nvar entity2 = EntityManager.CreateEntity();\nEntityManager.AddComponent\u003cExampleComponent\u003e(entity1);\nEntityManager.AddComponent\u003cExampleComponent\u003e(entity2);\n\nvar tween1 = Tween.Entity.To\u003cExampleComponent, ExampleTranslator\u003e(entity1, 5f, 10f);\nvar tween2 = Tween.Entity.To\u003cExampleComponent, ExampleTranslator\u003e(entity2, 5f, 10f);\n\nvar sequence = Sequence.Create()\n    .Append(tween1)\n    .Append(tween2);\n```\n\n\u003e **Warning**\n\u003e Avoid applying multiple concurrent Tweens with the same Translator to the same Entity. This may lead to overlapping value modifications and unexpected behavior.\n\n### Built-in Translators\n\nUnder `MagicTween.Translators`, you can find built-in Translators for ECS components.\n\nCurrently, there's a Translator that works with `LocalTransform`.\n\nIf you have the Entities Graphics package installed, you'll find Translators for tweening Material properties.\n\n### Limitations\n\nCreating and manipulating Tweens/Sequences is only supported on the main thread. You cannot create new Tweens or perform operations like Kill or Complete from a Job. To alleviate this limitation, there's ongoing development to introduce functionality for creating/operating Tweens using a dedicated CommandBuffer.\n\n## Other Features\n\n### EaseUtility\n\nThe easing functions used internally by Tween can be accessed via EaseUtility.\n\n```cs\nfloat value1 = EaseUtility.Evaluate(0.5f, Ease.OutQuad);\nfloat value2 = EaseUtility.InOutQuad(0.5f);\n```\n\n## Optimization\n\n### Tween Caching\n\nUsually, the cost of creating Tweens or Sequences is not a significant concern. However, in scenarios where you repeatedly use the same animations, creating them from scratch each time may not be very efficient. Caching Tweens and reusing them can be an effective approach in such cases.\n\n```cs\n// Create a Tween and change settings to manually control play and kill\nTween tween = transform.TweenPosition(Vector3.up, 2f)\n    .SetAutoPlay(false)\n    .SetAutoKill(false);\n\n// Play or Restart the Tween using Play() or Restart()\ntween.Play();\ntween.Restart();\n\n// Manually call Kill() when you're done using the Tween\ntween.Kill();\n\n// Alternatively, you can use SetLink to tie the Tween's lifetime to a GameObject\n// tween.SetLink(transform);\n```\n\nWhen reusing tweens, always make sure to set `SetAutoKill(false)`. If this is set to true, the Tween will be automatically destroyed when it completes playing. Also, if you want to manually manage the play timing, you can set `SetAutoPlay(false)` accordingly.\n\nWhen `SetAutoKill(false)` is set, be sure to call `Kill()` manually when you are done with the Tween. Alternatively, you can use `SetLink()` to associate the tween's lifetime with a GameObject, so it gets destroyed when the GameObject is destroyed.\n\n## Experimental Features\n\nThe `MagicTween.Experimental` namespace contains features that are currently under development. These features are available for use but come with no guarantees, and there may be breaking changes without notice.\n\n## Known Issues\n\n### Performance Drop in the Editor\n\nECS performs numerous checks to enhance safety, which leads to decreased performance within the editor. This performance degradation is particularly noticeable when creating Tweens and, in some cases, can result in processing times several times longer than usual.\n\nIt's important to note that these safety checks are disabled in the build, so performance measurements should always be conducted in the build environment.\n\n### Performance Drop in WebGL\n\nWhile it's possible to use ECS in WebGL, limitations in WebGL's specifications, such as the absence of multi-threading and SIMD, disable optimizations like the Job System and Burst. ECS achieves its high performance through the Job System and Burst, making performance degradation unavoidable in WebGL (hence, there are few advantages to using ECS on WebGL currently).\n\nMagic Tween optimizes the calculation part of Tweens using the Job System and Burst. Therefore, on WebGL, performance suffers for the reasons mentioned above. While these effects are typically not noticeable, please be mindful of this when creating a large number of Tweens.\n\n## Support\n\nForum: https://forum.unity.com/threads/magic-tween-extremely-fast-tween-library-implemented-in-ecs.1490080/\n\n## License\n\n[MIT License](LICENSE)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fannulusgames%2Fmagictween","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fannulusgames%2Fmagictween","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fannulusgames%2Fmagictween/lists"}