public static InternalAsyncEmojiRect New <T, U>(T parentTextElement, Char[] chars) where T : LTAsyncElement, ILayoutableText where U : IMissingSpriteCache, new()
        {
            var emojiOrMarkStr = new string(chars);

            var go = parentTextElement.GenerateGO(emojiOrMarkStr);

            // TMProのレイアウトをするためには、ここでCanvasに乗っている親要素の上に載せるしかない。
            go.transform.SetParent(parentTextElement.transform, false);


            var emojiRect = go.AddComponent <InternalAsyncEmojiRect>();

            // 文字をセットする場所としてRectTransformを取得、レイアウトのために高さに無限値をセット
            var rectTrans = go.GetComponent <RectTransform>();
            // フォント情報を取得するためにT型をセットし、そこからTMProのcomponentを取り出す。そこに絵文字をセットし、絵文字画像を得る。
            var textComponent = go.GetComponent <TextMeshProUGUI>();

            textComponent.enableWordWrapping = true;
            textComponent.text  = emojiOrMarkStr;
            rectTrans.sizeDelta = Vector2.positiveInfinity;
            var textInfos = textComponent.GetTextInfo(emojiOrMarkStr);

            textComponent.enableWordWrapping = false;

            var lines = textInfos.lineCount;

            if (lines != 1)
            {
                throw new Exception("unsupported emoji/mark pattern.");
            }

            var lineInfo   = textInfos.lineInfo[0];
            var lineWidth  = lineInfo.length;
            var lineHeight = lineInfo.lineHeight;

            // サイズの更新
            var size = new Vector2(lineWidth, lineHeight);

            // 絵文字/記号部分を左上アンカーにすると、高さがNanにならずに絵文字/記号スプライトが表示される。
            if (0 < rectTrans.childCount)
            {
                var emojiRectTrans = rectTrans.GetChild(0).GetComponent <RectTransform>();
                emojiRectTrans.pivot            = new Vector2(0, 1);
                emojiRectTrans.anchorMin        = new Vector2(0, 1);
                emojiRectTrans.anchorMax        = new Vector2(0, 1);
                emojiRectTrans.anchoredPosition = Vector2.zero;
            }

            // この文字オブジェクト自体の位置、サイズを規定する
            rectTrans.anchoredPosition = Vector2.zero;
            rectTrans.sizeDelta        = size;

            // サイズを一旦TMProの情報をもとに決定する
            emojiRect.Size = size;

            var(isExist, codePoint) = TextLayoutDefinitions.TMPro_ChechIfEmojiOrMarkExist(emojiOrMarkStr);
            if (isExist)
            {
                // 最低一つ要素が作られているはずなので、そのSptiteの位置情報をレイアウト後に合致するように調整する。
                if (rectTrans.childCount == 1)
                {
                    var emojiRectTrans = rectTrans.GetChild(0).GetComponent <RectTransform>();
                    emojiRectTrans.pivot            = new Vector2(0, 1);
                    emojiRectTrans.anchorMin        = new Vector2(0, 1);
                    emojiRectTrans.anchorMax        = new Vector2(0, 1);
                    emojiRectTrans.anchoredPosition = Vector2.zero;
                }
                else
                {
                    Debug.LogWarning("絵文字かマークがある状態だが、このcodePointの文字を示すspriteがロードされない codePoint:" + codePoint);
                }
            }
            else
            {
                // ローディングフラグを立てる
                emojiRect.IsLoading = true;

                /*
                 *  ポイント数
                 *  フォント名
                 *  表示幅
                 *  表示高さ
                 *  コードポイント
                 */
                var fontName      = textComponent.font.name;
                var fontSize      = textComponent.fontSize;
                var requestWidth  = size.x;
                var requestHeight = size.y;

                var cacheInstance = InternalCachePool.Get <U>();

                cacheInstance.LoadMissingEmoji(
                    fontName,
                    fontSize,
                    requestWidth,
                    requestHeight,
                    codePoint,
                    cor =>
                {
                    emojiRect.StartCoroutine(cor);
                },
                    data =>
                {
                    emojiRect.IsLoading = false;

                    var spr = Sprite.Create(data, new Rect(0, 0, data.width, data.height), Vector2.zero);

                    // サイズを更新
                    rectTrans.sizeDelta = new Vector2(data.width, data.height);

                    // tmProのコンポーネントを排除する(子供があるとそれを描画しようとしてエラーが出る)
                    GameObject.Destroy(textComponent);

                    if (0 < rectTrans.childCount)
                    {
                        // TMProの文字(カラ)が置いてあるコンポーネントを削除する
                        var emojiChild = rectTrans.GetChild(0);
                        GameObject.Destroy(emojiChild.gameObject);
                    }

                    // スプライトを作って入れる
                    var spriteObject    = new GameObject("sprite");
                    var spriteComponent = spriteObject.AddComponent <Image>();

                    var childRectTrans       = spriteComponent.GetComponent <RectTransform>();
                    childRectTrans.pivot     = new Vector2(0, 1);
                    childRectTrans.anchorMin = new Vector2(0, 1);
                    childRectTrans.anchorMax = new Vector2(0, 1);
                    spriteComponent.transform.SetParent(rectTrans, false);

                    spriteComponent.sprite = spr;
                    spriteComponent.SetNativeSize();

                    // 決定後のサイズを入力する
                    emojiRect.Size = rectTrans.sizeDelta;
                },
                    () =>
                {
                    emojiRect.IsLoading = false;
                }
                    );
            }

            return(emojiRect);
        }
        public static InternalAsyncMissingTextRect New <T, U>(T parentTextElement, string text) where T : LTAsyncElement, ILayoutableText where U : IMissingSpriteCache, new()
        {
            var go = parentTextElement.GenerateGO(text);

            // TMProのレイアウトをするためには、ここでCanvasに乗っている親要素の上に載せるしかない。
            go.transform.SetParent(parentTextElement.transform, false);

            var missingTextRect = go.AddComponent <InternalAsyncMissingTextRect>();

            // 文字をセットする場所としてRectTransformを取得、レイアウトのために高さに無限値をセット
            var rectTrans = go.GetComponent <RectTransform>();
            // フォント情報を取得するためにT型をセットし、そこからTMProのcomponentを取り出す。そこに絵文字をセットし、絵文字画像を得る。
            var textComponent = go.GetComponent <TextMeshProUGUI>();

            textComponent.enableWordWrapping = true;
            textComponent.text  = text;
            rectTrans.sizeDelta = Vector2.positiveInfinity;
            var textInfos = textComponent.GetTextInfo(text);

            textComponent.enableWordWrapping = false;

            var lines = textInfos.lineCount;

            if (lines != 1)
            {
                throw new Exception("unsupported emoji/mark pattern.");
            }

            var lineInfo   = textInfos.lineInfo[0];
            var lineWidth  = lineInfo.length;
            var lineHeight = lineInfo.lineHeight;

            // サイズの更新
            var size = new Vector2(lineWidth, lineHeight);

            // この文字オブジェクト自体の位置、サイズを規定する
            rectTrans.anchoredPosition = Vector2.zero;
            rectTrans.sizeDelta        = size;

            // サイズを一旦TMProの情報をもとに決定する
            missingTextRect.Size = size;

            // ローディングフラグを立てる
            missingTextRect.IsLoading = true;

            /*
             *  フォント名
             *  ポイント数
             *  表示幅
             *  表示高さ
             *  文字
             */
            var fontName      = textComponent.font.name;
            var fontSize      = textComponent.fontSize;
            var requestWidth  = size.x;
            var requestHeight = size.y;

            var cacheInstance = InternalCachePool.Get <U>();

            cacheInstance.LoadMissingText(
                fontName,
                fontSize,
                requestWidth,
                requestHeight,
                text,
                cor =>
            {
                missingTextRect.StartCoroutine(cor);
            },
                data =>
            {
                missingTextRect.IsLoading = false;

                var spr = Sprite.Create(data, new Rect(0, 0, data.width, data.height), Vector2.zero);

                // サイズを更新
                rectTrans.sizeDelta = new Vector2(data.width, data.height);

                // tmProのコンポーネントを排除する(子供があるとそれを描画しようとしてエラーが出る)
                GameObject.Destroy(textComponent);

                if (0 < rectTrans.childCount)
                {
                    // TMProの文字(カラ)が置いてあるコンポーネントを削除する
                    var emojiChild = rectTrans.GetChild(0);
                    GameObject.Destroy(emojiChild.gameObject);
                }

                // スプライトを作って入れる
                var spriteObject    = new GameObject("sprite");
                var spriteComponent = spriteObject.AddComponent <Image>();

                var childRectTrans       = spriteComponent.GetComponent <RectTransform>();
                childRectTrans.pivot     = new Vector2(0, 1);
                childRectTrans.anchorMin = new Vector2(0, 1);
                childRectTrans.anchorMax = new Vector2(0, 1);
                spriteComponent.transform.SetParent(rectTrans, false);

                spriteComponent.sprite = spr;
                spriteComponent.SetNativeSize();

                // 決定後のサイズを入力する
                missingTextRect.Size = rectTrans.sizeDelta;
            },
                () =>
            {
                missingTextRect.IsLoading = false;
            }
                );

            return(missingTextRect);
        }