Problem with • symbol in strings

I’m trying to make a dialog box that starts with • at the start of each spoken sentence like in earthbound, but whenever it’s alone in a line it defaults to a really weird square symbol thing.
https://gyazo.com/b9819ae3ae13e42d7282ae0384762c8e
Symbol in question unknown
Format of the text : image
Script for the scrolling text: image
i = 3 because it gave me a few of those weird symbols in the beginning and i being 3 skipped over them. Doesn’t help with the ones for the other lines, though.

It is probably related to this
image
on the wiki page for strings. I don’t know how I could pass over it being (I’m not sure how it works but I assume) converted into whatever U+2022 BULLET is when it is alone in a sentence.

I’m stumped, anyone knows how to force it to display as it’s symbol and not it’s “function” when alone?

The vanilla string library doesn’t seem to like unicode characters like that.

Using the utf8 library instead might help.

2 Likes

How would I use it in my case?

From the text variable you could remove the special character and instead do:

for i = 1, string.len(text) do
    if not self.Enabled then return end
    chat.Text.Text = "•"..string.sub(text, 0, i)
    sound:Play()
    wait()
end

And obviously you would edit this code to do this for each line you need.

This was a nightmare to write on mobile :sweat_smile::+1:

Each dropdown line occasionally has one of those dots, depending on if a sentence is started or if it’s just silence (as example above)
This would put a dot in front of the text, but first of all it would be a lone dot, therefore give the error, and 2nd it would only happen at the very start of each line (as in entire textlabel), not sentence.

The error only occurs because the symbol is more than 1 character and your code loads in each character after a wait() which means the symbol isn’t shown.

I am aware that this will only put the dot symbol at the front of your paragraph but my code was for you to use as a guide to write code to handle this.

The issue is that a unicode character can represent multiple bytes in utf8.

print(#"\u{2022}") --> 3

string.sub may only get part of the unicode character

print(string.sub("\u{2022}",1,2)) --> ��

The utf8 library would be useful here.

local RunService = game:GetService"RunService"
local Heartbeat = RunService.Heartbeat
local len = utf8.len(text)
local ToTake = len/30
local Accumulated = 0
local upos = 1
local uChar = 0
chat.Text.Text = ""
while Accumulated < ToTake do
	Accumulated = Accumulated + Heartbeat:Wait()
	if not self.Enabled then return end
	local Char = math.min(math.floor((Accumulated/ToTake)*len),len)
	if Char ~= uChar then
		sound:Play()
		upos = utf8.offset(text,upos,Char-uChar+1)
		chat.Text.Text = string.sub(text,1,upos-1)
		uChar = Char
	end
end
3 Likes

Little something, it’s chat, not char

I couldn’t understand how it worked so I tried just putting it in and it simply errored.
image
Could you explain what your script is trying to do instead of giving me code? It would help me understand and avoid running into problems like this in the future.

1 Like

I mixed up the n and i arguments of utf8.offset
This should work

local RunService = game:GetService"RunService"
local Heartbeat = RunService.Heartbeat
local len = utf8.len(text)
local ToTake = len/30
local Accumulated = 0
local upos = 1
local uChar = 0
chat.Text.Text = ""
while Accumulated < ToTake do
	Accumulated = Accumulated + Heartbeat:Wait()
	local Char = math.min(math.floor((Accumulated/ToTake)*len),len)
	if Char ~= uChar then
		upos = utf8.offset(text,Char-uChar+1,upos)
		chat.Text.Text = string.sub(text,1,upos-1)
		print(chat.Text.Text)
		uChar = Char
	end
end

What it’s doing is moving forward X unicode characters forward (utf8.offset), based on the time which has passed (Accumulated). It then uses that new position of the character, and subtracts 1 to get where the substring ends.

2 Likes

It works, but I still don’t fully understand it.
Sorry if this gets kind of tedious, but could you reformat that code using an incremental for loop? I believe it would help me understand.

1 Like

This is an issue with unicode characters. You can try using * or - instead of •.

An incremental loop wouldn’t be beneficial, since each yield could take varying amounts of time. It checks every frame, if it should add any more characters. Using a incremental loop would mean that characters appear slower when the yields take longer to resume. (more likely with a lower frame rate)

It simply checks every frame, if it should add any more characters, and when the time which has passed is greater than the time it takes for the display all characters, it breaks the loop. I’m not sure how i can make that any simpler.

I assume totake is just supposed to be a catchall for the time it takes for the box to complete based on length, but I don’t understand what char, uchar or upos are supposed to represent nor how they play with math.min / utf8.offset .
I wasn’t looking for an incremental loop to use in my game, but because totake and accumulated are confusing with the Char variable and I don’t understand what it’s supposed to do.
Obvious answer would be “So it can know what to do based on the time” but it still seems strangely formatted in my head.

ToTake is to represent how long it takes for the string to be fully outputted, which is based on the string length. Accumulated - Time passed, ToTake - How much time before the loop breaks
So for a string with 60 characters, it will take 2 seconds to show the string, and Accumulated is how long it has been since it started outputting the characters.

Char is to represent how many chars should be represented currently.
uChar is to represent how many chars are currently represented, so it knows how many characters to move forward.
upos is the byte position of the next character to be added, it gets this so it knows where the final unicode character ends.

I use math.min to make sure that it doesn’t try to represent more characters than there are in the string.
utf8.offset is used to get the byte position of where the next character will be after the new characters are added.

4 Likes