Unity/Csharp/DoTween
目次
- 1 dotweenとは
- 2 インストール
- 3 サンプル
- 4 Xだけ動かす
- 4.1 繰り返し
- 4.2 遅延動作
- 4.3 Easeの動き
- 4.4 動きを止める(キャンセル)
- 4.5 絶対座標
- 4.6 ローカル座標
- 4.7 回転
- 4.8 回転2D
- 4.9 色変更
- 4.10 徐々に透明へ
- 4.11 透明から表示
- 4.12 徐々に透明3Dオブジェクト
- 4.13 拡大縮小
- 4.14 振動
- 4.15 指定座標の上を移動する
- 4.16 曲線でつなぐ
- 4.17 幅を伸ばす
- 4.18 完了したら関数実行
- 4.19 コールバック一覧
- 4.20 複数動作をつなげる
- 4.21 複数同時実行をつなげる
- 4.22 sequenceで待機する
- 4.23 テキストカウントアップ
- 4.24 スライダーアニメーション
- 4.25 DOTweenのキャンセル
- 4.26 数秒遅延
- 4.27 完了するまで処理を待機する
- 4.28 元シーン削除でTweenを削除する方法
- 5 自作テンプレモーション
- 6 サンプルモーション
- 7 外部サイトサンプルモーション
- 8 The type 'TweenerCore<,,>' is definedエラーが出る場合
dotweenとは
アニメーションライブラリ
参考:https://qiita.com/broken55/items/df152c061da759ad1471
インストール
UnityAssets
- unityassetsからdotweenを検索して、
- dotweenのfree ( https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676 ) をダウンロード
- installし、
- importする
- OpenDoTweenUtilityPanelを開き
- SetupDotweenボタンを押して、Applyを押す。
PackageManager(MyAssets)
- PackageManagerで、DoTweenを検索
- DoTweenを選択してInstall。
- Plugins/Demigiant/DOTween があることを確認。
PackageManager(openupm)
- npm install -g openupm-cli
- openupm search dotween
- openupm add com.demigiant.dotween
なくなってる・・・
サンプル
x=2、y=3のrootから見た座標に1秒後に移動する。
using DG.Tweening; using UnityEngine; public class SampleScene : MonoBehaviour { void Start() { GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f); } }
Xだけ動かす
GameObject.Find("Image").transform.DOLocalMoveX(2f, 1f);
繰り返し
無限繰り返し
GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f) .SetLoops(-1, LoopType.Restart);
2回指定
GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f) .SetLoops(2, LoopType.Restart);
4回指定で、2往復となる。
.SetLoops(4, LoopType.Yoyo)
遅延動作
5秒待ってから動作
.SetDelay(5f);
Easeの動き
.SetEase(Ease.Linear); // 線形 .SetEase(Ease.OutSine); // 最初速く後ゆっくり .SetEase(Ease.InExpo); // 最初ゆっくり後速く
https://github.com/Nightonke/WoWoViewPager/blob/master/Pictures/ease.png
動きを止める(キャンセル)
オブジェクト指定
DOTween.Kill(this.transform);
tweenインスタンスを作って止める
Tween tween = GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f); tween.Kill();
参考:https://qiita.com/broken55/items/df152c061da759ad1471
絶対座標
DOMoveとする
GameObject.Find("Image").transform.DOMove(new Vector3(2f, 3f, 0f), 1f);
ローカル座標
DOLocalMoveとする
GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f);
回転
5秒で、x方向に90度回転
.DORotate(Vector3.right * 90f, 5f, RotateMode.LocalAxisAdd)
5秒で、y方向に90度回転
.DORotate(Vector3.up * 90f, 5f, RotateMode.LocalAxisAdd)
5秒で、z方向に90度回転
.DORotate(Vector3.forward * 90f, 5f, RotateMode.LocalAxisAdd)
5秒で、z方向に90度回転を、ループで、速度均等に
.DORotate(Vector3.forward * 360f, 5f, RotateMode.LocalAxisAdd).SetLoops(-1, LoopType.Restart).SetEase(Ease.Linear);
参考:https://qiita.com/BEATnonanka/items/b4cca6471e77466cec74
全方向回転
transform.DORotate(new Vector3(0,0,360), 1, RotateMode.Fast);
参考:https://qiita.com/BEATnonanka/items/b4cca6471e77466cec74
回転2D
30秒で一回転で、左回り
.DOLocalRotate(new Vector3(0, 0, 360f), 30f, RotateMode.FastBeyond360) .SetEase(Ease.Linear) .SetLoops(-1, LoopType.Restart);
右回り
imgRenew.transform.DOLocalRotate(new Vector3(0, 0, -360f), 30f, RotateMode.FastBeyond360) .SetEase(Ease.Linear) .SetLoops(-1, LoopType.Restart);
色変更
5秒で青へ
Image image = GameObject.Find("Image").GetComponent<Image>(); image.DOColor(Color.blue, 5f).SetEase(Ease.Linear);
マテリアルを1秒で赤へ
GameObject cubeObj; cubeObj.GetComponent<MeshRenderer>().material.DOColor(Color.red, 1f);
SpriteRendererの色を点滅
Color color = new Color(0.7f, 0.7f, 0.7f, 1f); objCanvas.GetComponent<SpriteRenderer>().DOColor(color, 0.5f).SetEase(Ease.Linear).SetLoops(-1, LoopType.Yoyo);
徐々に透明へ
透明度を10秒で0%へ
image.DOFade(endValue: 0f, duration: 10f);
透明から表示
Image image = hogeImage.GetComponent<Image>(); image.color = new Color(image.color.r, image.color.g, image.color.b, 0f); // 透明へ image.DOFade(endValue: 1f, duration: 0.5f); // 透明から表示へ
徐々に透明3Dオブジェクト
unity/3d/透明 [ショートカット]
void TransparentAllUnderObject(GameObject obj) { if (obj.GetComponent<SkinnedMeshRenderer>() != null) { Material[] materials = obj.GetComponent<SkinnedMeshRenderer>().materials; if (materials.Length > 0) { materials[0].shader = Shader.Find("Custom/SemiTransparent"); obj.GetComponent<SkinnedMeshRenderer>().materials[0].DOFade(endValue: 0f, duration: 1f); } } if (obj.GetComponent<MeshRenderer>() != null) { Material[] materials = obj.GetComponent<MeshRenderer>().materials; if (materials.Length > 0) { materials[0].shader = Shader.Find("Custom/SemiTransparent"); obj.GetComponent<SkinnedMeshRenderer>().materials[0].DOFade(endValue: 0f, duration: 1f); } } Transform transforms = obj.GetComponentInChildren<Transform>(); if (transforms.childCount > 0) { foreach (Transform transform in transforms) { TransparentAllUnderObject(transform.gameObject); // 再帰処理 } } }
参考:https://nn-hokuson.hatenablog.com/entry/2018/01/23/202530
拡大縮小
obj.transform.DOScale(new Vector3(1f, 1f, 0f), 1.0f); obj.transform.DOScaleX(1f, 1.0f); obj.transform.DOScaleY(1f, 1.0f);
振動
1秒間、強さ5で震える
obj.transform.DOShakePosition(duration: 1f, strength: 5);
1秒間に震える(オプション付き)
obj.transform.DOShakePosition(duration: 1, strength: 5, vibrato: 30, fadeOut: false)
敵にやられたときなど
obj.transform.DOShakePosition(duration: 0.3f, strength: 0.25f, vibrato:30, randomness:1, snapping:false, fadeOut:true);
引数上から順番に
- 振動時間
- 振動する強さ
- 振動数
- 手ブレ値
- スナップフラグ
- フェードアウト
iTweenのShakePositionからの移植の場合は、10倍ぐらいの強さにすればよいかも。
指定座標の上を移動する
- 2Dの場合は、PathMode.Sidescroller2Dを追加する。
- SetLookAtは、傾きが変わるx秒前に正面の向きを変える
Vector3[] movepath = { new Vector3(0f,0f,0f), new Vector3(0f,100f,0f), new Vector3(100f,100f,0f), new Vector3(100f,0f,0f), new Vector3(0f,0f,0f) }; GameObject.Find("Image").transform.DOLocalPath(movepath, 5f, PathType.Linear, PathMode.Sidescroller2D) .SetLookAt(0.1f) .SetLoops(-1, LoopType.Restart);
曲線でつなぐ
Vector3[] movepath = { new Vector3(0f,0f,0f), new Vector3(200f,-100f,0f), new Vector3(400f,-300f,0f), }; GameObject.Find("Image").transform.DOLocalPath(movepath, 0.5f, PathType.CatmullRom, PathMode.Sidescroller2D) .SetEase(Ease.Linear) .SetLookAt(0.1f) .SetLoops(-1, LoopType.Restart);
幅を伸ばす
RectTransform rectTransform = underLineObj.GetComponent<RectTransform>(); rectTransform.sizeDelta = new Vector2(0, rectTransform.sizeDelta.y); rectTransform.DOSizeDelta(new Vector2(800, rectTransform.sizeDelta.y), 1);
完了したら関数実行
パターン1
GameObject.Find("Image").transform.DOPath(movepath, 5f, PathType.Linear, PathMode.Sidescroller2D).OnComplete(CallbackComplete); } void CallbackComplete() { Debug.Log("CallbackComplete"); }
パターン2
GameObject.Find("Image").transform.DOPath(movepath, 5f, PathType.Linear, PathMode.Sidescroller2D).OnComplete(() => { Debug.Log("CallbackComplete"); });
コールバック一覧
.OnComplete(Callback); .OnStart(Callback); .OnUpdate(Callback); .OnKill(Callback);
複数動作をつなげる
var sequence = DOTween.Sequence(); sequence.Append(this.transform.DOMove(new Vector3(1f, 3f, 0f), 1f)); sequence.Append(this.transform.DOMove(new Vector3(2f, 4f, 0f), 1f)); sequence.Play();
複数同時実行をつなげる
var sequence = DOTween.Sequence(); sequence.Append(this.transform.DOMove(new Vector3(1f, 3f, 0f), 1f)); sequence.Append(this.transform.DOMove(new Vector3(2f, 4f, 0f), 1f)); sequence.Join(this.transform.DOScale(Vector3.one * 3f, 1f)); // 1つ前と同時に実行 sequence.Join(this.transform.DORotate(new Vector3(0, 0, 360f), 1f, RotateMode.FastBeyond360)); // 1つ前と同時に実行 sequence.Play();
移動しながら、徐々に表示されるように
hogeText.color = new Vector4(hogeText.color.r, hogeText.color.g, hogeText.color.b, 0f); var sequence = DOTween.Sequence(); sequence.Append(hogeObj.transform.DOLocalMoveY(10, 0.1f)); sequence.Join(hogeText.DOFade(endValue: 1f, duration: 0.15f)); sequence.Play();
上に移動しながら、文字が消える
TextMeshPro textPro = hogeObj.GetComponent<TextMeshPro>(); textPro.color = new Color(textPro.color.r, textPro.color.g, textPro.color.b, 1); Color color = new Color(textPro.color.r, textPro.color.g, textPro.color.b, 0f); sequence = DOTween.Sequence(); sequence.Append(hogeObj.transform.DOLocalMoveY(4f, 1f)); sequence.Join(textPro.DOColor(color, 1f)); sequence.Play();
or
Text text = obj.GetComponent<Text>(); Color color = new Color(1f, 1f, 1f, 0f); Sequence sequence = DOTween.Sequence(); sequence.Append(obj.transform.DOLocalMoveY(obj.transform.localPosition.y + 200f, 0.5f)); sequence.Join(DOTween.ToAlpha( () => text.color, color => text.color = color, 0f, 0.5f ).SetEase(Ease.InCubic)); sequence.Play();
sequenceで待機する
sequence.AppendInterval(0.5f); // 待機
テキストカウントアップ
int now = 10; int end = 1000; int sec = 1; DOTween.To(() => now, (n) => now = n, end, sec) .SetEase(Ease.Linear) // 線形 .OnUpdate(() => text.text = now.ToString("f2")); // 小数第2位まで
参考:http://halcyonsystemblog.jp/blog-entry-524.html
スライダーアニメーション
float now = 0; float end = 1; float sec = 1; DOTween.To(() => now, (n) => now = n, end, sec) .SetEase(Ease.Linear) // 線形 .OnUpdate(() => { enemyBossHpSlider.value = now; }) .OnComplete(() => { Debug.Log("complete"); });
DOTweenのキャンセル
float now = 0; float end = 1; float sec = 1; Tween tween = DOTween.To(() => now, (n) => now = n, end, sec) .SetEase(Ease.Linear) // 線形 .OnUpdate(() => { enemyBossHpSlider.value = now; }) .OnComplete(() => { Debug.Log("complete"); }); tween.Kill(); // キャンセル
数秒遅延
DOVirtual.DelayedCall(2f, () => { // 2秒後実行 });
完了するまで処理を待機する
UniTaskなどを使ってasyncを使う。
async void BasicAsync() { await GameObject.Find("Image").transform.DOMove(new Vector3(3f, 3f, 0f), 2f) // .SetEase(Ease.InExpo) .SetEase(Ease.Linear) .AsyncWaitForCompletion(); Debug.Log("完了"); }
sequenceの場合
await sequence.AsyncWaitForCompletion();
元シーン削除でTweenを削除する方法
transform .DOMoveX(2, 2) .SetLink(gameObject);
参考:https://baba-s.hatenablog.com/entry/2020/03/02/151500
自作テンプレモーション
テレビのように開く
this.transform.localScale = new Vector3(0f, 0f, 0f); var sequence = DOTween.Sequence(); sequence.Append(this.transform.DOScale(new Vector3(1f, 0.005f, 1f), 0.2f).SetEase(Ease.InOutCubic)); sequence.Append(this.transform.DOScale(new Vector3(1f, 1f, 1f), 0.2f).SetEase(Ease.InOutCubic)); sequence.Play();
テレビのように閉じる
this.transform.localScale = new Vector3(1f, 1f, 1f); var sequence = DOTween.Sequence(); sequence.Append(this.transform.DOScale(new Vector3(1f, 0.005f, 1f), 0.2f).SetEase(Ease.InOutCubic)); sequence.Append(this.transform.DOScale(new Vector3(0f, 0f, 0f), 0.2f).SetEase(Ease.InOutCubic)); sequence.Play();
星型に移動する
- root座標のときは、DOPathを使う。
Vector3[] movepath = new Vector3[6]; movepath[0].Set(0f, 1f, 0f); // 1 movepath[1].Set(0.5878f, -0.8090f, 0f); // 5 movepath[2].Set(-0.9511f, 0.3090f, 0f); // 9 movepath[3].Set(0.9511f , 0.3090f, 0f); // 3 movepath[4].Set(-0.5878f, -0.8090f, 0f); // 7 movepath[5].Set(0f, 1f, 0f); // 1 // 星型頂点 https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10137274530 GameObject.Find("Image").transform.DOPath(movepath, 5f, PathType.Linear, PathMode.Sidescroller2D) .SetLookAt(0.01f) .SetLoops(-1, LoopType.Restart);
ローカル値を使う場合は、DOLocalPathを使う
参考:https://qiita.com/BEATnonanka/items/50cacac803f88f5074dd
敵にダメージを与えたときにランダムに振動
enemyTransform.DOShakePosition(duration: 0.1f, strength: 0.1f, vibrato: 1, randomness: 1, snapping: false, fadeOut: false);
敵にダメージを与えたときにランダムに振動
float knockbackDistance = 0.5f; // ノックバックの距離 // プレイヤーの方向を計算 Vector3 directionToPlayer = playerObj.transform.position - enemy.transform.position; directionToPlayer.Normalize(); // ベクトルの正規化 // ノックバックの方向を計算(プレイヤーの方向とは逆) Vector3 knockbackDirection = -directionToPlayer; // ノックバック後の座標を計算 Vector3 knockbackPosition = enemy.transform.position + knockbackDirection * knockbackDistance; // ノックバック後の座標のY成分が今よりも下にいかないように(床貫通対策) if (knockbackPosition.y < enemyObj.transform.position.y) { knockbackPosition.y = Mathf.Max(knockbackPosition.y, enemy.transform.position.y); } enemyTransform.DOMove(knockbackPosition, 0.04f) .SetLoops(2, LoopType.Yoyo).SetEase(Ease.OutQuad);
ゼンゼロっぽく。すぐに元の位置に戻す。
力を加える場合は、DotweenじゃなくRigidbodyを使う
float knockbackDistance = 3.5f; // ノックバックの距離 // プレイヤーの方向を計算 Vector3 directionToPlayer = playerObj.transform.position - enemyObj.transform.position; directionToPlayer.Normalize(); // ベクトルの正規化 // ノックバックの方向を計算(プレイヤーの方向とは逆) Vector3 knockbackDirection = -directionToPlayer; // Rigidbodyコンポーネントを取得 Rigidbody rb = enemyObj.GetComponent<Rigidbody>(); // ノックバックの方向を力として加える rb.AddForce(knockbackDirection * knockbackDistance, ForceMode.Impulse);
縮小してきて震える
messageObj.transform.localScale = new Vector3(20f, 20f, messageObj.transform.localScale.z); Vector3 initPosition = messageObj.transform.localPosition; var sequence = DOTween.Sequence(); sequence.Append(messageObj.transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutBack)); sequence.Append(messageObj.transform.DOShakePosition(duration: 0.2f, strength: 50f, vibrato: 30, fadeOut: false).SetDelay(0.2f)); sequence.Play().OnComplete(() => { messageObj.transform.localPosition = initPosition; });
ffっぽいダメージ
var sequence = DOTween.Sequence(); sequence.Append(imageObj.transform.DOLocalMoveY(100f, 0.1f).SetEase(Ease.OutSine)); sequence.Append(imageObj.transform.DOLocalMoveY(0f, 0.1f).SetEase(Ease.InSine)); sequence.Append(imageObj.transform.DOLocalMoveY(60f, 0.1f).SetEase(Ease.OutSine)); sequence.Append(imageObj.transform.DOLocalMoveY(0f, 0.2f).SetEase(Ease.OutBounce)); sequence.Play();
スタンプを押してる感じ
clearImageObj.transform.localScale = Vector3.one * 5f; var sequenceClear = DOTween.Sequence(); sequenceClear.Append(clearImageObj.transform.DOScale(Vector3.one, 0.2f).SetEase(Ease.OutBack)); sequenceClear.Join(clearImageObj.transform.DOShakePosition(duration: 0.2f, strength: 50f, vibrato: 30, fadeOut: false)); sequenceClear.Play();
全体文字をx秒で1文字ずつ表示する
totalDuration = 2f; // 全体を2秒で表示 textMeshPro.text = ""; // 初期化 float timePerChar = totalDuration / text.Length; // 各文字にかける時間を計算 Sequence sequence = DOTween.Sequence(); for (int i = 0; i < text.Length; i++) { int index = i; // クロージャ内でのiを保持 sequence.AppendCallback(() => { textMeshPro.text = text.Substring(0, index + 1); }).AppendInterval(timePerChar); } sequence.Play();
サンプルモーション
ボタンフェードイン表示
obj.transform.localScale = Vector3.zero; obj.transform.DOScale(1f, 1f).SetEase(Ease.OutBounce);
参考:https://unity-yuji.xyz/dotween-good-game-ui/
上下移動サンプル
obj.transform .DOMoveY(obj.transform.position.y - 0.1f, duration: 1f) .SetEase(Ease.Linear) .SetLoops(-1, LoopType.Yoyo) .Play();
参考:https://qiita.com/azumagoro/items/d97a07cff212a664461b
外部サイトサンプルモーション
DOTweenで作成したモーション17個を含むプロジェクトを公開 https://game-ui.net/?p=975
The type 'TweenerCore<,,>' is definedエラーが出る場合
詳しいエラーは以下の通り
The type 'TweenerCore<,,>' is defined in an assembly that is not referenced. You must add a reference to assembly 'DOTween, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
PCを再起動で直った。