【问题标题】:Detect if I clicked on a certain part of text检测我是否点击了文本的某个部分
【发布时间】:2020-01-01 14:20:31
【问题描述】:

我正在使用 Unity 创建一个 Android/IOS 应用程序。

在包含段落的页面中,我想知道我是否点击了文本的最后一句话。 (例如“单击此处了解更多详细信息”)。 点击这句话后我想打开一个新页面。

我知道我可以放置 2 个文本元素并将这句话添加到第二个元素,然后重置到第一个元素并在第二个元素上添加 onClick 事件。

这是问题的解决方案,但在我的情况下,它无法解决问题,因为我正在动态获取文本,并且它的大小会不时改变,所以第二个文本元素不会从同一个开始第一个元素结束后的行。

我需要一个用代码完成的解决方案。

我看到了same question,但它适用于 HTML 和 JavaScript,而不适用于 Unity。

我将发布一个答案的代码 sn-p,它与我想要的行为相同。

const clickables = document.querySelectorAll('.clickable')
clickables.forEach(el => new Clickable(el))

function Clickable (el) {
  const _handleClick = ({target}) => console.log(target.innerHTML)
  const texts = el.textContent.split(/\s/)
  
  el.innerHTML = ''
  
  texts.forEach(t => {
    const span = document.createElement('span')
    span.innerHTML = `${t} `
    span.addEventListener('click', _handleClick)
    el.appendChild(span)
  })
}
<h1 class="clickable">Some text</h1>

<h2 class="clickable">Some! more! text2</h1>

【问题讨论】:

  • 可以通过TextMeshPro实现
  • @derHugo 显然现在每种材料都有多个网格textInfo.meshInfo[textInfo.characterInfo[currentCharacter].materialReferenceIndex].vertices
  • @Iggy 是的,只是注意到这并不重要.. 不需要只是获得悬停的单词

标签: c# unity3d text


【解决方案1】:

可以使用TextMeshProTextMeshProUGUI 代替Text。然后你可以使用TMP_TextUtilities 做很多花哨的事情。

实际上,有很多非常好的理由值得转而使用 TMP 而不是 Text - 到目前为止,我还没有找到任何更好的理由来更喜欢 Text 而不是 TMP。

链接的TMP_TextUtilities tutorial 展示了更多奇特的用例。

public class Example : MonoBehaviour
{
    public TextMeshProUGUI text;

    public string LastClickedWord;

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            var wordIndex = TMP_TextUtilities.FindIntersectingWord(text, Input.mousePosition, null);

            if (wordIndex != -1)
            {
                LastClickedWord = text.textInfo.wordInfo[wordIndex].GetWord();

                Debug.Log("Clicked on " + LastClickedWord);
            }
        }
    }
}

只需将Text 组件替换为对象和脚本中的TextMeshProUGUI 组件即可。设置text的用法完全一样。

我想知道我是否点击了文本的最后一句话。 ("点击这里了解更多详情"

您也可以使用FindIntersectingLine 代替FindIntersectingWord,然后检查索引以仅触发最后一个事件。

if(lineIndex == text.lineCount - 1)

请注意,此处的行表示实际显示的行 - 不一定是换行符

或者你可以例如计算并定义最后一句中的单词数量并使用

if(wordIndex > text.textInfo.wordCount - LastSentenceLength)

或者..您也可以直接使用Link,然后您可以使用FindIntersectingLink,并检查您是否点击了最后一个。


注意:确保传入与Canvas 相同的相机。我使用了null,因为我使用了ScreenSpace-Overlay 画布而没有引用某个Camera。如果您正在使用例如WorldSpace你必须

  • Canvas 中引用Camera &rightarrow; Event Camera
  • 将相同的Camera 传递给FindIntersectingXXX

【讨论】:

  • 我使用了Text Mesh Pro UGUI。我总是得到 charIndex -1
  • 确保传入与Canvas 相同的Camera。我使用了null,因为我使用了ScreenSpace-Overlay 画布而没有引用某个Camera
  • 最后一个问题:如果我想检查我是否点击了一个句子而不是一个词怎么办。因为也许这句话中的一个词在另一个句子中
  • 在这种情况下,我猜你必须按索引。你可以例如计算单词并使用最后一个可点击句子的长度范围。然后你可以做if(wordIndex &gt; text.textInfo.wordInfo.Length - LastSentenceLength - 1)
【解决方案2】:

此视频描述了一个类似的概念,只是它检测点击和悬停在特定字符上。 https://www.youtube.com/watch?v=wg9WAwd8TKM

要使其符合您的想法,您只需检查按下的字符的索引,然后检查它是否在文本末尾的特定范围内。

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多