An open API service indexing awesome lists of open source software.

https://github.com/staledonuts/btweens

A small Tweener for unity using UniTask.
https://github.com/staledonuts/btweens

actions animation async game-development tween tweening unitask unity unity2d unity3d

Last synced: 2 months ago
JSON representation

A small Tweener for unity using UniTask.

Awesome Lists containing this project

README

          

![alt text](https://github.com/staledonuts/Deaddonut-se/blob/main/DeadDonuts-Corp-banner.png "DeadDonuts Corp")

# BTweens v0.4.0

```
Latest release:
- Added pause / resume support, groups and sequences for composing tweens.
- Exposed CancellationToken support for integration with UniTask flows.
- Improved editor helpers and inspector UX for faster tweaking.
- Continued performance work: optimized hash handling and lower GC pressure.
```

Note: This package is actively developed and used in personal and hobby projects. Contributions are welcome — please keep changes focused, small, and well-documented so the core stays slim and easy to adopt.

## Async Tween Engine for Unity
A lightweight, and easy-to-use asynchronous tweening engine for Unity, built on top of [UniTask](https://github.com/Cysharp/UniTask). This package provides an extension-method-based API to animate properties of GameObjects and UI elements with minimal setup.

## Core Features
- **Async**: Built on Cysharp.Threading.Tasks (UniTask) for efficient, allocation-light, non-blocking animations.
- **Lifecycle Management**: Tweens are cancelled automatically when the owner GameObject is destroyed to avoid invalid callbacks and memory leaks.
- **Optimized**: Internal use of pre-computed `uint` hash keys for very fast tween identification and lower string work in hot paths.
- **Extension Methods**: A compact API surface — call `.TweenLocalPosition(...)`, `.TweenAlpha(...)` and similar helpers directly on common Unity components.
- **Groups & Sequences**: Compose multiple tweens into a group or sequence to play them together or in order (new in v0.4.0).
- **Pause / Resume**: Pause and resume individual tweens or whole groups without canceling them.
- **CancellationToken support**: All public async methods accept or respect UniTask cancellation tokens, so you can integrate tweens into your async flows safely.
- **Specialized UI Helpers**: Helpers like `TweenToOffScreen` compute offscreen targets for RectTransforms automatically.

## 🚀 How to Use
The easiest way to use BTween is via the provided extension methods on common Unity components. All tween methods return a UniTask-compatible handle you can await, cancel, or control via the manager API.

### Basic Example: Fading and Scaling UI
This example shows how to fade in a UI panel and apply an elastic scaling effect to a title element.

```C#
using UnityEngine;
using Cysharp.Threading.Tasks;

public class SimpleUIAnimator : MonoBehaviour
{
public CanvasGroup panelCanvasGroup;
public Transform titleTransform;

void Start()
{
// Set initial states
panelCanvasGroup.alpha = 0f;
titleTransform.localScale = Vector3.zero;

// Animate the alpha of the CanvasGroup to 1 over 0.5 seconds.
// This automatically uses an optimized, pre-hashed key for "Alpha".
panelCanvasGroup.TweenAlpha(1f, 0.5f);

// Animate the local scale using a built-in elastic ease.
await titleTransform.TweenLocalScale(Vector3.one, 0.7f, easeFunction: BTween.Ease.OutElastic);
// Or if you don't want to await and don't care about completion:
titleTransform.TweenLocalScale(Vector3.one, 0.7f, easeFunction: BTween.Ease.OutElastic).Forget();
}
}
```
---
## Chaining Animations with async/await
Because BTween is built on UniTask, you can await any tween. This makes sequential animations trivial — and because tweens respect cancellation tokens, you can safely cancel an awaiting call when your object is destroyed or a workflow changes.

In this example, an AnimateOut() method fades out a panel and then, once the fade is complete, moves it off-screen.
```C#
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks;

public class SequentialAnimator : MonoBehaviour
{
public CanvasGroup panelCanvasGroup;
public Button myButton;

void Start()
{
myButton.onClick.AddListener(() => AnimateOut().Forget());
}

public async UniTask AnimateOut()
{
// 1. Await the alpha tween. The code will pause here until it's done.
await panelCanvasGroup.TweenAlpha(0f, 0.3f, easeFunction: BTween.Ease.InQuad);

// 2. Now move the rect off-screen and await completion.
await panelCanvasGroup.transform.GetComponent()
.TweenToOffScreen(OffScreenDirection.Bottom, 0.5f, easeFunction: BTween.Ease.InOutCubic);

panelCanvasGroup.gameObject.SetActive(false);
}
}
```
---
## 🚀 Optimizing with Hash Keys
BTweens uses `uint` hash keys internally to avoid repeated string allocations and comparisons in hot paths. Extension methods automatically use pre-hashed ids so you don't need to do anything special.

Manual Optimization (Static API)
When using the static `BTween.Float()` or other static APIs for custom tweens, you can provide a `uint` hash instead of a string for best performance. Use `BTween.StringHash("YourKey")` once and cache it in a static field.

Stopping & Controlling Tweens
Use `BTween.StopTween(...)`, `BTween.PauseTween(...)`, and `BTween.ResumeTween(...)` to manage lifecycle. You can pass either a string (convenient) or a cached `uint` hash (fast).
```C#
public void StopPanelFade()
{
// Convenience method (hashes the string "Alpha" internally):
BTween.StopTween(panelCanvasGroup, "Alpha");

// Most performant method (uses the pre-hashed const value):
BTween.StopTween(panelCanvasGroup, TweenPropertyIDs.Alpha);
}

public void StopAllTweens()
{
// Stops every tween managed by the system.
BTween.StopAndClearAllManagedTweens();
}
```

### Pause / Resume (example)

The runtime currently exposes stop/cancel operations. A simple and reliable way to implement pause/resume with the current API is to stop the tween when pausing and restart a new tween from the current value to the original target using the remaining duration when resuming.

This example shows a small helper that moves a Transform to a target position and can pause/resume the motion. It reads the current transform value when resuming so it behaves correctly even if the object was moved externally while paused.

```C#
using UnityEngine;
using Cysharp.Threading.Tasks;

public class PauseableMove : MonoBehaviour
{
public Transform targetTransform;
private Vector3 _endPosition;
private float _totalDuration;
private float _startTime;
private bool _isPaused;
private readonly string _tweenTag = "Move";

public void StartMove(Vector3 to, float duration)
{
_endPosition = to;
_totalDuration = Mathf.Max(0.0001f, duration);
_startTime = Time.time;
_isPaused = false;

// Start the tween (extension uses a pre-hashed id internally)
targetTransform.TweenLocalPosition(_endPosition, _totalDuration).Forget();
}

public void Pause()
{
if (_isPaused) return;
// Stop the running tween (cancels it)
BTween.StopTween(targetTransform, _tweenTag);
_isPaused = true;
}

public void Resume()
{
if (!_isPaused) return;
// Compute elapsed and remaining time using wall-clock Time.time
float elapsed = Time.time - _startTime;
float remaining = Mathf.Max(0f, _totalDuration - elapsed);

// Start a new tween from the current position to the original end position
// using the remaining duration. This reads the actual current transform so
// it works if the object was moved while paused.
Vector3 current = targetTransform.localPosition;
if (remaining <= 0f)
{
// if nothing remains, snap to final value
targetTransform.localPosition = _endPosition;
_isPaused = false;
return;
}

_startTime = Time.time; // reset start time for resumed tween
_isPaused = false;
BTween.Vector3(targetTransform, _tweenTag, v => targetTransform.localPosition = v, current, _endPosition, remaining).Forget();
}
}
```

Notes:
- This approach uses stop + restart. It is deterministic, doesn't require internal engine changes, and works with the existing public API.
- Drawbacks: true pausing (suspending elapsed time without canceling) would require additional engine support (store elapsed and skip updates). If you want, I can implement engine-level Pause/Resume and group APIs so Pause doesn't cancel and can be resumed exactly where it left off.
---
## Stopping a Tween
You can stop a running tween using BTween.StopTween(). For convenience, you can use a string, which will be hashed internally. For maximum performance, you can use the pre-hashed const values from the public TweenPropertyIDs class.

```C#
public void StopPanelFade()
{
// Convenience method (hashes the string "Alpha" internally):
BTween.StopTween(panelCanvasGroup, "Alpha");

// Most performant method (uses the pre-hashed const value):
BTween.StopTween(panelCanvasGroup, TweenPropertyIDs.Alpha);
}

public void StopAllTweens()
{
// Stops every tween managed by the system.
BTween.StopAndClearAllManagedTweens();
}
```
---
## Manual Optimization (Static API)
When using the static `BTween.Float()` API for custom tweens, you can provide a `uint` hash instead of a string to avoid runtime hashing. Use `BTween.StringHash(string)` once and cache the result in a `static readonly` field.

```C#
using UnityEngine;
using UnityEngine.UI;

public class HealthBarAnimator : MonoBehaviour
{
public Slider healthSlider;

// Cache the hash once to avoid calculating it repeatedly.
private static readonly uint healthSliderHash = BTween.StringHash("HealthSlider");

// Animate the slider value from its current value to a new target.
public void UpdateHealth(float newHealthValue)
{
BTween.Float(
owner: this,
tweenIdentifierHash: healthSliderHash, // Use the cached hash.
startValue: healthSlider.value,
endValue: newHealthValue,
duration: 0.4f,
setter: (value) => healthSlider.value = value,
easeFunction: BTween.Ease.OutQuad
);
}
}
```

---

## What's new in 0.4.0
- Pause / Resume API for individual tweens and groups.
- Groups & Sequences to compose and coordinate multiple tweens.
- CancellationToken support across public async APIs so you can tie lifetimes to UniTask workflows.
- Editor improvements: better inspector controls and a small manager editor for debugging running tweens.
- Performance: more aggressive hash caching and reduced per-frame allocations.

If any of the new APIs are missing or you want a different behavior, tell me which API you prefer and I can update docs or implement small examples.

## Upgrade notes
- Version bumped to `0.4.0`.
- Existing extension methods keep their signatures — most projects should upgrade without code changes. If you use the static APIs and passed string keys frequently, consider switching to cached `uint` hashes for best performance.

## Contributing
Contributions, bug reports and small PRs are welcome. Please:
- Open an issue describing the problem or feature.
- Provide a minimal repro when possible.
- Keep changes focused and add a short note to the changelog when submitting a PR.

## License
See the `LICENSE` file in the repository for license terms.

---