Is there a reason why link strings (<link=“abc” >) have a maximum length of ~120 characters before they don’t get processed as a link and instead dumped as normal text? Can this be increased?
Increasing the length impacts performance when parsing the text.
The format of the link tag is <link=“ID”>Some text description. This ID simply represents a unique key for the link itself. Ie. the link ID could be “01” which in a dictionary would be associated with a value / link that is 250 characters long.
In the code that handles what to do with a given link, a simply lookup of the link ID would enable you to use a link value of any number of characters without impacting parsing performance.
Is there a reason you need the link ID to be able to be longer than 120 characters?
I’m aware of all that but 120 is a very small number and could be a lot larger without ramifications to performance. More importantly it should be user configurable. It’s only convenience that I need that many characters, but that should be my choice if I want to “hang myself”.
Again given the ID is simply an identifier for whatever that real link is going to be, why do you need the ID to be more than 120 characters?
I am just looking to get a better understanding of the use case here.
As I stated, <link=“ID01”>Some text can be associated with a link of any length where this ID is the key into a dictionary where you can easily retrieve the link value which could be of any length.
I have the same issue, I totally get you Ziplock9000. If max limitation affects performance, that’s ok, but let us increase that max length if we want to, that should be our choice. The thing is Stephan_B that you’re talking about mapping static URLs with IDs, but what about the case when you have some retrieved URLs from server? That’s my case for instance and 120 character limitation killing me! Can we somehow increase that?
Even in the case of the URL coming from some external source or server, you would add this new URL to a List or Dictionary and use the List index or Dictionary key as the unique link ID.
Here is an example script that contains most of the glue code to handle all of this. Add this script to a normal TMP text object.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class DynamicLinkHelper : MonoBehaviour
{
private string m_UrlFromServer = " https://discussions.unity.com/t/749791/4 ";
private TMP_Text m_TextComponent;
private bool m_isHoveringObject;
private int m_SelectedLink;
private static Dictionary<int, string> m_UrlLookup = new Dictionary<int, string>();
private void Awake()
{
m_TextComponent = GetComponent<TMP_Text>();
// Some block of code would exist here to get a URL from some sever
// Url would then be added to our dictionary
int linkID = AddURL(m_UrlFromServer);
m_TextComponent.text = "Simple <style=\"link\"><link=\"" + linkID + "\">Dynamic Link</link></style> Example.";
}
void Update()
{
m_isHoveringObject = false;
if (TMP_TextUtilities.IsIntersectingRectTransform(m_TextComponent.rectTransform, Input.mousePosition, Camera.main))
m_isHoveringObject = true;
// Check if mouse intersects with any links.
int linkIndex = TMP_TextUtilities.FindIntersectingLink(m_TextComponent, Input.mousePosition, Camera.main);
// Clear previous link selection if one existed.
if ((linkIndex == -1 && m_SelectedLink != -1) || linkIndex != m_SelectedLink)
m_SelectedLink = -1;
// Handle new Link selection.
if (linkIndex != -1 && linkIndex != m_SelectedLink)
{
m_SelectedLink = linkIndex;
TMP_LinkInfo linkInfo = m_TextComponent.textInfo.linkInfo[linkIndex];
string linkIDString = linkInfo.GetLinkID();
// The following provides an example of how to access the link properties.
Debug.Log("Link ID: \"" + linkIDString + "\" Link Text: \"" + linkInfo.GetLinkText() + "\"" + "\nLink URL: [" + GetLinkURL(linkIDString)); // Example of how to retrieve the Link ID and Link Text.
}
}
static int AddURL(string url)
{
// Compute a hashcode for the given URL. This hashcode will become our unique link ID.
int hashCode = TMP_TextUtilities.GetSimpleHashCode(url);
if (!m_UrlLookup.ContainsKey(hashCode))
m_UrlLookup.Add(hashCode, url);
return hashCode;
}
static int GetLinkID(string url)
{
// Compute a hashcode for the given URL. This hashcode will become our unique link ID.
int hashCode = TMP_TextUtilities.GetSimpleHashCode(url);
if (m_UrlLookup.ContainsKey(hashCode))
return hashCode;
return -1;
}
static string GetLinkURL(int id)
{
return m_UrlLookup.ContainsKey(id) ? m_UrlLookup[id] : string.Empty;
}
static string GetLinkURL(string stringID)
{
int id = Int32.Parse(stringID);
return m_UrlLookup.ContainsKey(id) ? m_UrlLookup[id] : string.Empty;
}
}
In this above example, the URL is hardcoded but this URL could come from anywhere.
Since we are trying to get away from using long link IDs, using the URL as the dictionary key would defeat this purpose so instead we compute a unique hashcode for this URL which we use as the key. We use a custom hashcode function because we need this hashcode to be persistent (ie. always the same given the same URL).
The AddURL() function handles computing our unique hashcode for each url which is used as our unique link ID and key for our dictionary.
In Awake() we add our URL to our dictionary and then compose some text string for this url with unique link id.
The GetLinkURL() function allows us to easily retrieve the URL using our Link ID / dictionary key.
In the Update function, we simply check if the mouse if over the text object. If we are, we then check if we intersect with a link. If we do, we get the linkInfo which allows us to easily get our linkID, link text and link URL.
The above is a quick example of how we can use a dictionary to store unique integer based link IDs thus allowing us to get around the linkID length limitation and without any performance impact.
In summary, getting around this length limitation for linkID basically comes down to computing a hashcode for the url which is used as the unique linkID and key in our dictionary to track it.
We have a game editor where one person can create dialogs for the game. Logic is inserted inside the Text and then interpreted in a parser, for example, we want a text to be replaced by a variable in the game “you win [amount] gold” where [amount] is a but the link has a formula inside it. The problem with using stored logic is that we want the editor to be able to copy the [amount] text and logic from one dialog to another without worrying about the logic, so the best option is to store the logic inside the tag.
The logic can look like this:
{“PID”:“cfb31b54-6a85-4b56-ba86-96ca9ca2ed3a”,“L”:[{“PID”:“cb124772-0794-40c9-9dde-e3118f962120”,“T”:0,“C”:[ ],“O”:[{“T1”:61,“V1”:103,“RV1”:0,“T2”:0,“V2”:74,“VD2”:“600”,“RV2”:0,“C”:0,}]}]}
Were you thinking of using this “logic” as the link ID?
The text parser would have no idea how to handle this as quotes are used as delimiters.
I just figured that out, but we can make it work without quotes
But you were thinking of using that as the link ID. Right?
Yes
Yeah, I know, thanks for the script, I end up doing the pretty much same thing. I was just sad that it’s not just a 1 click setup, and if you guys want to avoid long links, that’s fine, I got it. Thanks for the answer!
Please, add a new parameter for the link itself like this:
<link=“ID” url=“http://…”>Link text…
Hi @Stephan_B
In my case, we are developing an educational app where users can send textual messages
and to keep things simple for our end users, we need to avoid character limit or dictionary usage etc
It should be as simple as <link=“long link” or something like above
Bad idea. You only need the ID and then you can not only look up the URL but any number of data items you need. Putting that all in the string would be inefficient.
Hey @Stephan_B
Just ran into this issue as well.
I’ve built a “router” system that uses HttpUtility.ParseQueryString and just hit a brick wall when finding this limitation.
I’m using links like this:
<link=“run:attempt-objective?objective-id=1eeae13f-a27d-4a67-9941-083b207d5007&quest-instance-id=48e81f43-b727-4acb-a2fd-ffe29367b0b9”>
This makes me sad because I have been using this link / router system quite extensively in my app. Would be really nice if there was a workaround.