ãã®è¨äºã¯UnityAdventCalendar 2024ã·ãªã¼ãº3ã®è¨äºã§ãã
è¨äºãæ¸ãä½è£ãåºãã®ã¨æ ã空ãã¦ãã®ã§åå ãã¾ããã
Â
Â
12/30 æ´æ°
Unity6ã¨Unity2022å¾æãã¼ã¸ã§ã³ã§åããªãã£ãã®ã§ã¹ã¯ãªããã«ä¿®æ£ãå ¥ãã¾ãã
Â
Â
- ãããã¨
- éçºç°å¢
- UIã®ä½æï¼åä½ç¢ºèªç¨ï¼
- å¿ è¦ãªã³ã³ãã¼ãã³ãã®è¿½å
- ã¹ã¯ãªããã®ä½æï¼ã·ã³ãã«ãªãã¤ï¼
- ã¹ã¯ãªããã®ä½æï¼UniTask + DOTWeenï¼
- ãã¾ã
- Unity 6ç¨ã®ä¿®æ£ï¼12/30ï¼
- éå»ã®Unity ã¢ããã³ãã«ã¬ã³ãã¼è¨äº
- åèè³æ
Â
ãããã¨
表示ç¯å²ãããªã¼ãã¼ããã¼ãã¦ãããã¹ããã¹ã¯ãã¼ã«ãã¦ã«ã¼ã表示ããä»çµã¿ãä½æãã¾ãã
ã½ã¼ã¹ã³ã¼ãããã®ã¾ã¾ã³ããããã ãã§åãã¾ãã
Â
Â
éçºç°å¢
Unity 2022.3.14f1
TextMeshPro ver3.0.9
Â
Â
UIã®ä½æï¼åä½ç¢ºèªç¨ï¼
åä½ç¢ºèªç¨ã®UIãä½æãã¾ãã
Canvasã¨Imageã®ä½æ
ã·ã¼ã³ã«Canvasãä½æï¼CanvasScalerã¯ã好ã¿ã§ï¼
ãã®åã«Imageãä½æã大ããã調æ´ãã¾ãããããæåã®è¡¨ç¤ºç¯å²ã«ãªãã¾ãã
Â
Imageã®è²ã¯æåãè¦ãããããã«åéæã®é»ã«ãã¦ããã¾ã
Â
Â
Text(TMP)ã®ä½æ
Imageã®åã«Text(TMP)ãä½æã
Â
ä½ç½ãå°ã欲ããã®ã§PosXã50ã«ã
AnchorãLeft-Middleã«ãPivotã®Xã0ã«ãAlignmentãLeft-Middleã«è¨å®ãã¾ãã
Â
Â
Â
å¿ è¦ãªã³ã³ãã¼ãã³ãã®è¿½å
RectMask2D
Imageã«RectMask2Dã³ã³ãã¼ãã³ããã¢ã¿ãã
Â
ããã§Imageã®ç¯å²å¤ã«åºãTextããã¹ã¯ãããããã«ãªãã¾ã
Â
Â
ContentSizeFitter
Text(TMP)ã«ContentSizeFitterã³ã³ãã¼ãã³ããã¢ã¿ãã
HorizontalFitãPreferredSizeã«å¤æ´
ããã§Text(TMP)ã®Widthãæåæ°ã«å¿ãã¦èªå調æ´ãããããã«ãªãã¾ã
Â
Â
Â
ã¹ã¯ãªããã®ä½æï¼ã·ã³ãã«ãªãã¤ï¼
ããããæ¬é¡ãæåã¯ã·ã³ãã«ãªã¹ã¯ãªããã§ããã¾ãã
Â
UniTaskãªã©ã®ã©ã¤ãã©ãªãã¢ã»ããã使ã£ã¦ããªãã·ã³ãã«ãªãã¤ãªã®ã§ã
ãã®ã¾ã¾ã³ããããã°ã©ã®ããã¸ã§ã¯ãã§ãåä½ãã¾ãï¼ãã¶ãï¼
Â
以ä¸ã®TextScroller.csãä½æãText(TMP)ã«ã¢ã¿ãããã¾ãã
Â
using System.Collections; using UnityEngine; using UnityEngine.UI; using TMPro; /// <summary> /// ããã¹ãã®ã¹ã¯ãã¼ã« /// TMP_Textã«ã¢ã¿ãããã¦ãã ãã /// </summary> [RequireComponent(typeof(CanvasGroup))] public class TextScroller : MonoBehaviour { [SerializeField] private float scrollSpeed = 100f; // ã¹ã¯ãã¼ã«é度 [SerializeField] private float scrollFinishLineAddValue = 50; // ã¹ã¯ãã¼ã«çµäºå¤å®ã¾ã§ã®ãã¼ã¸ã³ã0ã ã¨å ¨ã¦è¡¨ç¤ºãããæç¹ã§çµäºãã [SerializeField] private float waitTimeBeforeScroll = 2f; // ã¹ã¯ãã¼ã«éå§åã®å¾ æ©æé [SerializeField] private float waitTimeAfterScroll = 2f; // ã¹ã¯ãã¼ã«å®äºå¾ããã§ã¼ãã¢ã¦ãããã¾ã§ã®å¾ æ©æé [SerializeField] private float fadeDuration = 0.4f; // ããã¹ãã®ãã§ã¼ãã¤ã³ã¢ã¦ãæé [SerializeField] private float waitTimeFade = 0.2f; // ãã§ã¼ãã¢ã¦ããã¦ãããã§ã¼ãã¤ã³ããã¾ã§ã®å¾ æ©æé private CanvasGroup canvasGroup; private RectTransform textRectTransform; private RectTransform parentRectTransform; private Vector3 startPosition; // ã¹ã¿ã¼ãä½ç½® private float scrollValue; // ã¹ã¯ãã¼ã«å¤ private float finishLineValue; // ã¹ã¯ãã¼ã«ãåæ¢ããä½ç½®ãscrollValueããã®å¤ãè¶ ãããåæ¢ãã private float textWidth; private float parentWidth; private bool isScrolling = false; private void Start() { Initialize(); } private void Update() { if (!isScrolling) return; // åæ¢ä½ç½®ã¾ã§ã¹ã¯ãã¼ã«ãã if (scrollValue + parentWidth >= finishLineValue) { isScrolling = false; StartCoroutine(Fade(0, waitTimeAfterScroll)); Invoke(nameof(ResetScrollPosition), waitTimeAfterScroll + fadeDuration + waitTimeFade); } else { scrollValue += scrollSpeed * Time.deltaTime; textRectTransform.anchoredPosition = new Vector3(startPosition.x - scrollValue, startPosition.y, startPosition.z); } } /// <summary> /// ã¹ã¯ãã¼ã«ã®åæè¨å® /// </summary> private void Initialize() { if (!TryGetComponent<TMP_Text>(out var textComponent)) { Debug.LogWarning("TMP_Textãã¢ã¿ããããã¦ããªãã®ã§ã¹ã¯ãã¼ã«ã¯æ©è½ãã¾ãã"); return; } // ContentSizeFitteræåæ´æ° var contentSizeFitter = GetComponent<ContentSizeFitter>(); contentSizeFitter.SetLayoutHorizontal(); contentSizeFitter.SetLayoutVertical(); LayoutRebuilder.ForceRebuildLayoutImmediate(contentSizeFitter.GetComponent<RectTransform>()); canvasGroup = GetComponent<CanvasGroup>(); textRectTransform = textComponent.GetComponent<RectTransform>(); parentRectTransform = textComponent.transform.parent.GetComponent<RectTransform>(); textWidth = textRectTransform.rect.width; parentWidth = parentRectTransform.rect.width; startPosition = textRectTransform.anchoredPosition; finishLineValue = textWidth + startPosition.x + scrollFinishLineAddValue; if (textWidth + startPosition.x > parentWidth) { Invoke(nameof(StartScrolling), waitTimeBeforeScroll); } } /// <summary> /// ã¹ã¯ãã¼ã«éå§ /// </summary> private void StartScrolling() { scrollValue = 0; isScrolling = true; } /// <summary> /// ã¹ã¯ãã¼ã«ãªã»ãã /// </summary> private void ResetScrollPosition() { textRectTransform.anchoredPosition = startPosition; StartCoroutine(Fade(1, 0)); Invoke(nameof(StartScrolling), waitTimeBeforeScroll + fadeDuration); } /// <summary> /// ãã§ã¼ãå¦çã³ã«ã¼ãã³ /// </summary> private IEnumerator Fade(float targetAlpha, float delayTime) { var elapsedTime = 0f; var startAlpha = canvasGroup.alpha; yield return new WaitForSeconds(delayTime); while (elapsedTime < fadeDuration) { elapsedTime += Time.deltaTime; canvasGroup.alpha = Mathf.Lerp(startAlpha, targetAlpha, elapsedTime / fadeDuration); yield return null; } canvasGroup.alpha = targetAlpha; } }
Â
Text(TMP)ã«ã¢ã¿ããããã¨ãèªåçã«CanvasGroupãã¢ã¿ããããã¾ãã
ï¼ãã©ã¡ã¼ã¿ã®è©³ç´°ã¯ã½ã¼ã¹ã³ã¼ãã®ã³ã¡ã³ãããï¼
Â
Â
ãã®ç¶æ ã§ã²ã¼ã ãå®è¡ããã¨ãããªæãã
ããã©ã«ãã®ãã©ã¡ã¼ã¿ã ã¨ãå®è¡å¾2ç§å¾ã«é度100ã§ã¹ã¯ãã¼ã«ãã
ä¸çªæå¾ã®æåã®ä½ç½®+50ã¾ã§ã¹ã¯ãã¼ã«ãããåæ¢ãåæ¢ãã¦ãã2ç§å¾ã0.4ç§ããã¦ãã§ã¼ãã¢ã¦ããã
ãã§ã¼ãã¢ã¦ãããã£ã¦ãã0.2ç§å¾ã«ä½ç½®ããªã»ããããç¶æ
ã§0.4ç§ããã¦ãã§ã¼ãã¤ã³ã
以éç¹°ãè¿ã....
Â
Â
Â
ã¹ã¯ãªããã®ä½æï¼UniTask + DOTWeenï¼
次ã¯UniTaskã¨DOTweenãå ¥ã£ã¦ããããã¸ã§ã¯ãç¨ã®ã¹ã¯ãªããã§ãã
ProjectSettingsã®è¨å®
DOTweenã®å¦çãawaitãããã®ã§ãProjectSettingsãéãã
Player/ScriptCompilationã®ScriptingDefineSymbolsã«ãUNITASK_DOTWEEN_SUPPORTã追å ã
Â
Â
ã¹ã¯ãªãã
以ä¸ã®TextScroller_UniTask.csãä½æãText(TMP)ã«ã¢ã¿ãããã¾ãã
using System; using System.Threading; using UnityEngine; using UnityEngine.UI; using TMPro; using Cysharp.Threading.Tasks; using DG.Tweening; /// <summary> /// ããã¹ãã®ã¹ã¯ãã¼ã« /// TMP_Textã«ã¢ã¿ãããã¦ãã ãã /// </summary> [RequireComponent(typeof(CanvasGroup))] public class TextScroller_UniTask : MonoBehaviour { [SerializeField] private float scrollSpeed = 100f; // ã¹ã¯ãã¼ã«é度 [SerializeField] private float scrollFinishLineAddValue = 50; // ã¹ã¯ãã¼ã«çµäºå¤å®ã¾ã§ã®ãã¼ã¸ã³ã0ã ã¨å ¨ã¦è¡¨ç¤ºãããæç¹ã§çµäºãã [SerializeField] private float waitTimeBeforeScroll = 2f; // ã¹ã¯ãã¼ã«éå§åã®å¾ æ©æé [SerializeField] private float waitTimeAfterScroll = 2f; // ã¹ã¯ãã¼ã«å®äºå¾ããã§ã¼ãã¢ã¦ãããã¾ã§ã®å¾ æ©æé [SerializeField] private float fadeDuration = 0.4f; // ããã¹ãã®ãã§ã¼ãã¤ã³ã¢ã¦ãæé [SerializeField] private float waitTimeFade = 0.2f; // ãã§ã¼ãã¢ã¦ããã¦ãããã§ã¼ãã¤ã³ããã¾ã§ã®å¾ æ©æé private CanvasGroup canvasGroup; private RectTransform textRectTransform; private Vector3 startPosition; // ã¹ã¿ã¼ãä½ç½® private float finishLineValue; // ã¹ã¯ãã¼ã«ãåæ¢ããä½ç½®ãscrollValueããã®å¤ãè¶ ãããåæ¢ãã private void Start() { if (!TryGetComponent<TMP_Text>(out var textComponent)) { Debug.LogWarning("TMP_Textãã¢ã¿ããããã¦ããªãã®ã§ã¹ã¯ãã¼ã«ã¯æ©è½ãã¾ãã"); return; } // ContentSizeFitteræåæ´æ° var contentSizeFitter = GetComponent<ContentSizeFitter>(); contentSizeFitter.SetLayoutHorizontal(); contentSizeFitter.SetLayoutVertical(); LayoutRebuilder.ForceRebuildLayoutImmediate(contentSizeFitter.GetComponent<RectTransform>()); canvasGroup = GetComponent<CanvasGroup>(); textRectTransform = textComponent.GetComponent<RectTransform>(); var textWidth = textRectTransform.rect.width; var parentWidth = textComponent.transform.parent.GetComponent<RectTransform>().rect.width; startPosition = textRectTransform.anchoredPosition; finishLineValue = startPosition.x - (textWidth + startPosition.x + scrollFinishLineAddValue - parentWidth); if (textWidth + startPosition.x > parentWidth) { Scroll(this.GetCancellationTokenOnDestroy()).Forget(); } } /// <summary> /// ã¹ã¯ãã¼ã«å¦ç /// </summary> private async UniTaskVoid Scroll(CancellationToken token) { while (true) { await UniTask.Delay(TimeSpan.FromSeconds(waitTimeBeforeScroll), cancellationToken: token); await textRectTransform.DOAnchorPosX(finishLineValue, scrollSpeed).SetSpeedBased().SetEase(Ease.Linear).ToUniTask(cancellationToken: token); // ãã§ã¼ãã¤ã³ãã§ã¼ãã¢ã¦ã await UniTask.Delay(TimeSpan.FromSeconds(waitTimeAfterScroll), cancellationToken: token); await canvasGroup.DOFade(0, fadeDuration).SetEase(Ease.Linear); textRectTransform.anchoredPosition = startPosition; await UniTask.Delay(TimeSpan.FromSeconds(waitTimeFade), cancellationToken: token); await canvasGroup.DOFade(1, fadeDuration).SetEase(Ease.Linear).ToUniTask(cancellationToken: token); } } }
Â
åä½ãªã©ã¯TextScroller.csã¨å ¨ãåãã§ãããã£ã¡ã®æ¹ãç°¡æ½ããã
Â
Â
ãã¾ã
ãã£ã¨ããæãã«ããã人åã
èæ¯ãã°ã©ãã¼ã·ã§ã³ç»åã«ãMaskã®å¢ç®ã調æ´
Imageã®ç»åããããªæãã®ã°ã©ãã¼ã·ã§ã³ç»åã«å¤æ´
Â
RectMask2Dã®Softnessã®å¤ã調æ´
Â
ããã§ã表示ç¯å²ã¨ã®å¢çç·ã§æåããã§ã¼ãããã®ã§è¦æ ããã¡ãã£ã¨è¯ããªãã¾ã
Â
Â
TextMeshProã«RectMask2Dã®Softnessãåæ ãããªãæ(Unity2022ç¨ã®è¿½å 対å¿)
â»Unity6ã ã¨å¿ è¦ããã¾ãã
Â
Unity2022ãå³å¯ã«ã¯TextMeshProã®ver3.0.9ï¼Unity2022ã®ææ°ãã¼ã¸ã§ã³ï¼ã ã¨ã
RectMask2Dã®Softnessãåæ ããã¾ããã
ãã¡ãã®è¨äºã«å¾ããTextMeshProãæ´æ°ããã°åæ ããã¾ã
Â
Â
èæ¯ã¨è¡¨ç¤ºç¯å²ãåãã
確èªç¨UIã§ã¯ãImageã«RectMask2Dãã¤ãã¦ãã¾ããããããåãã¾ãã
ããã¯å¾ãå´ã®ä½ç½ããã¡ãã¨åãããæã«æå¹ã§ãã
Â
ã¾ãImageã®RectMask2Dãåé¤ã
Imageã®åã«ã空ã®GameObjectãä½æãååããMaskãã«å¤æ´ã
ãã®Maskã«RectMask2Dã³ã³ãã¼ãã³ããã¢ã¿ãããã¾ãã
Â
Â
Â
Â
Â
Â
Unity 6ç¨ã®ä¿®æ£ï¼12/30ï¼
Unity6ãããã³2022ã®å¾æãã¼ã¸ã§ã³ã ã¨çºçããåé¡ãããã¾ããã
ãããã§ã¯ãContentSizeFitterã®ãµã¤ãºèª¿æ´ãå³åº§ã«è¡ãããã
1ãã¬ã¼ã å¾
ããªãã¨æ£å¸¸ãªWidthã®å¤ãåããªãç¶æ
ã§ããã
Â
ããã§ä¸è¨ã®ã¹ã¯ãªããã«ä»¥ä¸ã®ã³ã¼ããå
¥ãã¦å¯¾å¿ãã¾ããã
ãããå¼ã³åºãã¨å³åº§ã«ãµã¤ãºãæ´æ°ããã¾ãã
using UnityEngine.UI; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ContentSizeFitteræåæ´æ° var contentSizeFitter = GetComponent<ContentSizeFitter>(); contentSizeFitter.SetLayoutHorizontal(); contentSizeFitter.SetLayoutVertical(); LayoutRebuilder.ForceRebuildLayoutImmediate(contentSizeFitter.GetComponent<RectTransform>());
Â
Â
Â
éå»ã®Unity ã¢ããã³ãã«ã¬ã³ãã¼è¨äº
Â
Â
åèè³æ
Â
Â
Â
Â
以ä¸ã§ã