「Unity/Csharp/DoTween」の版間の差分
(→テキストカウントアップ) |
(→全体文字をx秒で1文字ずつ表示する) |
||
(同じ利用者による、間の87版が非表示) | |||
行5: | 行5: | ||
==インストール== | ==インストール== | ||
+ | ===UnityAssets=== | ||
#unityassetsからdotweenを検索して、 | #unityassetsからdotweenを検索して、 | ||
#dotweenのfree ( https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676 ) をダウンロード | #dotweenのfree ( https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676 ) をダウンロード | ||
行11: | 行12: | ||
#OpenDoTweenUtilityPanelを開き | #OpenDoTweenUtilityPanelを開き | ||
#SetupDotweenボタンを押して、Applyを押す。 | #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 | ||
+ | なくなってる・・・ | ||
==サンプル== | ==サンプル== | ||
行21: | 行33: | ||
void Start() | void Start() | ||
{ | { | ||
− | GameObject.Find("Image").transform. | + | GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f); |
} | } | ||
} | } | ||
</pre> | </pre> | ||
+ | ==Xだけ動かす== | ||
+ | <pre> | ||
+ | GameObject.Find("Image").transform.DOLocalMoveX(2f, 1f); | ||
+ | </pre> | ||
===繰り返し=== | ===繰り返し=== | ||
無限繰り返し | 無限繰り返し | ||
<pre> | <pre> | ||
− | GameObject.Find("Image").transform. | + | GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f) |
.SetLoops(-1, LoopType.Restart); | .SetLoops(-1, LoopType.Restart); | ||
</pre> | </pre> | ||
2回指定 | 2回指定 | ||
<pre> | <pre> | ||
− | GameObject.Find("Image").transform. | + | GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f) |
.SetLoops(2, LoopType.Restart); | .SetLoops(2, LoopType.Restart); | ||
</pre> | </pre> | ||
+ | 4回指定で、2往復となる。 | ||
+ | .SetLoops(4, LoopType.Yoyo) | ||
===遅延動作=== | ===遅延動作=== | ||
行49: | 行67: | ||
https://github.com/Nightonke/WoWoViewPager/blob/master/Pictures/ease.png | https://github.com/Nightonke/WoWoViewPager/blob/master/Pictures/ease.png | ||
− | ===動きを止める=== | + | ===動きを止める(キャンセル)=== |
オブジェクト指定 | オブジェクト指定 | ||
DOTween.Kill(this.transform); | DOTween.Kill(this.transform); | ||
tweenインスタンスを作って止める | tweenインスタンスを作って止める | ||
− | Tween tween = GameObject.Find("Image").transform. | + | Tween tween = GameObject.Find("Image").transform.DOLocalMove(new Vector3(2f, 3f, 0f), 1f); |
tween.Kill(); | tween.Kill(); | ||
参考:https://qiita.com/broken55/items/df152c061da759ad1471 | 参考:https://qiita.com/broken55/items/df152c061da759ad1471 | ||
+ | |||
+ | ===絶対座標=== | ||
+ | DOMoveとする | ||
+ | GameObject.Find("Image").transform.DOMove(new Vector3(2f, 3f, 0f), 1f); | ||
===ローカル座標=== | ===ローカル座標=== | ||
行63: | 行85: | ||
===回転=== | ===回転=== | ||
− | + | 5秒で、x方向に90度回転 | |
− | .DORotate(Vector3.up * 90f, 5f) | + | .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秒で一回転で、左回り | ||
+ | <pre> | ||
+ | .DOLocalRotate(new Vector3(0, 0, 360f), 30f, RotateMode.FastBeyond360) | ||
+ | .SetEase(Ease.Linear) | ||
+ | .SetLoops(-1, LoopType.Restart); | ||
+ | </pre> | ||
+ | |||
+ | 右回り | ||
+ | <pre> | ||
+ | imgRenew.transform.DOLocalRotate(new Vector3(0, 0, -360f), 30f, RotateMode.FastBeyond360) | ||
+ | .SetEase(Ease.Linear) | ||
+ | .SetLoops(-1, LoopType.Restart); | ||
+ | </pre> | ||
===色変更=== | ===色変更=== | ||
5秒で青へ | 5秒で青へ | ||
Image image = GameObject.Find("Image").GetComponent<Image>(); | Image image = GameObject.Find("Image").GetComponent<Image>(); | ||
− | image.DOColor(Color. | + | 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%へ | 透明度を10秒で0%へ | ||
image.DOFade(endValue: 0f, duration: 10f); | image.DOFade(endValue: 0f, duration: 10f); | ||
+ | ===透明から表示=== | ||
+ | <pre> | ||
+ | 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); // 透明から表示へ | ||
+ | </pre> | ||
+ | |||
+ | ===徐々に透明3Dオブジェクト=== | ||
+ | [[unity/3d/透明]] [ショートカット] | ||
+ | |||
+ | <pre> | ||
+ | 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); // 再帰処理 | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | 参考:https://nn-hokuson.hatenablog.com/entry/2018/01/23/202530 | ||
===拡大縮小=== | ===拡大縮小=== | ||
行79: | 行180: | ||
obj.transform.DOScaleX(1f, 1.0f); | obj.transform.DOScaleX(1f, 1.0f); | ||
obj.transform.DOScaleY(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倍ぐらいの強さにすればよいかも。 | ||
===指定座標の上を移動する=== | ===指定座標の上を移動する=== | ||
行96: | 行215: | ||
.SetLoops(-1, LoopType.Restart); | .SetLoops(-1, LoopType.Restart); | ||
</pre> | </pre> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
===曲線でつなぐ=== | ===曲線でつなぐ=== | ||
行129: | 行228: | ||
.SetLookAt(0.1f) | .SetLookAt(0.1f) | ||
.SetLoops(-1, LoopType.Restart); | .SetLoops(-1, LoopType.Restart); | ||
+ | </pre> | ||
+ | |||
+ | ===幅を伸ばす=== | ||
+ | <pre> | ||
+ | RectTransform rectTransform = underLineObj.GetComponent<RectTransform>(); | ||
+ | rectTransform.sizeDelta = new Vector2(0, rectTransform.sizeDelta.y); | ||
+ | rectTransform.DOSizeDelta(new Vector2(800, rectTransform.sizeDelta.y), 1); | ||
</pre> | </pre> | ||
行159: | 行265: | ||
<pre> | <pre> | ||
var sequence = DOTween.Sequence(); | var sequence = DOTween.Sequence(); | ||
− | sequence.Append(this.transform.DOMove(new Vector3(1f, 3f, 0f), 1f); | + | sequence.Append(this.transform.DOMove(new Vector3(1f, 3f, 0f), 1f)); |
− | sequence.Append(this.transform.DOMove(new Vector3(2f, 4f, 0f), 1f); | + | sequence.Append(this.transform.DOMove(new Vector3(2f, 4f, 0f), 1f)); |
sequence.Play(); | sequence.Play(); | ||
</pre> | </pre> | ||
行166: | 行272: | ||
<pre> | <pre> | ||
var sequence = DOTween.Sequence(); | var sequence = DOTween.Sequence(); | ||
− | sequence.Append(this.transform.DOMove(new Vector3(1f, 3f, 0f), 1f); | + | sequence.Append(this.transform.DOMove(new Vector3(1f, 3f, 0f), 1f)); |
− | sequence.Append(this.transform.DOMove(new Vector3(2f, 4f, 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.DOScale(Vector3.one * 3f, 1f)); // 1つ前と同時に実行 | ||
+ | sequence.Join(this.transform.DORotate(new Vector3(0, 0, 360f), 1f, RotateMode.FastBeyond360)); // 1つ前と同時に実行 | ||
sequence.Play(); | sequence.Play(); | ||
</pre> | </pre> | ||
+ | |||
+ | 移動しながら、徐々に表示されるように | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | |||
+ | 上に移動しながら、文字が消える | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | |||
+ | or | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | |||
+ | ===sequenceで待機する=== | ||
+ | sequence.AppendInterval(0.5f); // 待機 | ||
===テキストカウントアップ=== | ===テキストカウントアップ=== | ||
<pre> | <pre> | ||
− | int | + | int now = 10; |
int end = 1000; | int end = 1000; | ||
− | DOTween.To(() => | + | int sec = 1; |
− | .OnUpdate(() => text.text = | + | DOTween.To(() => now, (n) => now = n, end, sec) |
+ | .SetEase(Ease.Linear) // 線形 | ||
+ | .OnUpdate(() => text.text = now.ToString("f2")); // 小数第2位まで | ||
</pre> | </pre> | ||
参考:http://halcyonsystemblog.jp/blog-entry-524.html | 参考:http://halcyonsystemblog.jp/blog-entry-524.html | ||
+ | |||
+ | ===スライダーアニメーション=== | ||
+ | <pre> | ||
+ | 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"); | ||
+ | }); | ||
+ | </pre> | ||
+ | |||
+ | ===DOTweenのキャンセル=== | ||
+ | <pre> | ||
+ | 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(); // キャンセル | ||
+ | </pre> | ||
+ | |||
+ | ===数秒遅延=== | ||
+ | <pre> | ||
+ | DOVirtual.DelayedCall(2f, () => | ||
+ | { | ||
+ | // 2秒後実行 | ||
+ | }); | ||
+ | </pre> | ||
+ | |||
+ | ===完了するまで処理を待機する=== | ||
+ | UniTaskなどを使ってasyncを使う。 | ||
+ | <pre> | ||
+ | async void BasicAsync() | ||
+ | { | ||
+ | await GameObject.Find("Image").transform.DOMove(new Vector3(3f, 3f, 0f), 2f) | ||
+ | // .SetEase(Ease.InExpo) | ||
+ | .SetEase(Ease.Linear) | ||
+ | .AsyncWaitForCompletion(); | ||
+ | Debug.Log("完了"); | ||
+ | } | ||
+ | </pre> | ||
+ | ====sequenceの場合==== | ||
+ | await sequence.AsyncWaitForCompletion(); | ||
+ | |||
+ | ===元シーン削除でTweenを削除する方法=== | ||
+ | <pre> | ||
+ | transform | ||
+ | .DOMoveX(2, 2) | ||
+ | .SetLink(gameObject); | ||
+ | </pre> | ||
+ | 参考:https://baba-s.hatenablog.com/entry/2020/03/02/151500 | ||
+ | |||
+ | ==自作テンプレモーション== | ||
+ | |||
+ | ===テレビのように開く=== | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | ===テレビのように閉じる=== | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | |||
+ | ===星型に移動する=== | ||
+ | *root座標のときは、DOPathを使う。 | ||
+ | |||
+ | <pre> | ||
+ | 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); | ||
+ | </pre> | ||
+ | ローカル値を使う場合は、DOLocalPathを使う | ||
+ | |||
+ | 参考:https://qiita.com/BEATnonanka/items/50cacac803f88f5074dd | ||
+ | |||
+ | ===敵にダメージを与えたときにランダムに振動=== | ||
+ | enemyTransform.DOShakePosition(duration: 0.1f, strength: 0.1f, vibrato: 1, randomness: 1, snapping: false, fadeOut: false); | ||
+ | |||
+ | ===敵にダメージを与えたときにランダムに振動=== | ||
+ | <pre> | ||
+ | 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); | ||
+ | </pre> | ||
+ | ゼンゼロっぽく。すぐに元の位置に戻す。 | ||
+ | |||
+ | ===力を加える場合は、DotweenじゃなくRigidbodyを使う=== | ||
+ | <pre> | ||
+ | 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); | ||
+ | </pre> | ||
+ | |||
+ | ===縮小してきて震える=== | ||
+ | <pre> | ||
+ | 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; | ||
+ | }); | ||
+ | </pre> | ||
+ | |||
+ | ===ffっぽいダメージ=== | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | |||
+ | ===スタンプを押してる感じ=== | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | |||
+ | ===全体文字をx秒で1文字ずつ表示する=== | ||
+ | <pre> | ||
+ | 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(); | ||
+ | </pre> | ||
+ | |||
+ | ==サンプルモーション== | ||
+ | ボタンフェードイン表示 | ||
+ | <pre> | ||
+ | obj.transform.localScale = Vector3.zero; | ||
+ | obj.transform.DOScale(1f, 1f).SetEase(Ease.OutBounce); | ||
+ | </pre> | ||
+ | 参考:https://unity-yuji.xyz/dotween-good-game-ui/ | ||
+ | |||
+ | 上下移動サンプル | ||
+ | <pre> | ||
+ | obj.transform | ||
+ | .DOMoveY(obj.transform.position.y - 0.1f, duration: 1f) | ||
+ | .SetEase(Ease.Linear) | ||
+ | .SetLoops(-1, LoopType.Yoyo) | ||
+ | .Play(); | ||
+ | </pre> | ||
+ | 参考: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を再起動で直った。 |
2024年9月22日 (日) 13:44時点における最新版
目次
- 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を再起動で直った。