How to declare properties that have string value

Been wondering why its not possible to define a string property
like the one below

go.property(“name”, noname))
I always get this error “Only these types are available: number, hash, msg.url, vmath.vector3, vmath.vector4, vmath.quat…” are allowed

Instead i have to write it as go.property(“name”, hash(“noname”))
Id like to be able to pass string properties without have to figure out how to cast a hash back to a string.

1 Like

I’m a bit confused as to what are you trying to do with this? There is probably another way.

@Pkeod
I’m trying to pass a table of values to a factory to initialize the objects
My understanding is that the object getting initialized captures the values through properties.

Factory code below:
local id = factory.create("#commodityfactory", pos, null, { position = vmath.vector3(), name = “corn” }
)

CommodityFactory creates a commodity object.
There i figured that the values i passed get mapped to the properties

go.property(“position”, vmath.vector3())
go.property(“name”, “noname”)
Note: this code doesnt work, because it needs to be a hash. Is there any other clean way to do this besides passing in a message? I’d like to cleanly initialize the objects and have the values automatically accessible through “self”.

See my reply in the post above.

What’s wrong with using a hash? You can compare it elsewhere

if name == hash(“name”) then

i intend on just using the value. Not for comparison. More like assigning the value to in a gui.set_text(node, value) scenario.

I wanted to be able to pass a value from an external service and display it in a text element

1 Like

Yeah, you have to pass that as a message or perhaps keep the value you received from the external service in a look-up table and pass the index/id/key into that lookup table in factory.create() and look it up in the created object using the provided key.

3 Likes

Ic. Thats interesting. I certainly can use a global variable for this.
Is this a limitation that will be improved on in future iteration?

1 Like

Even better, store the values in a module and require that module. Something like in this example:

https://github.com/britzl/defoldexamples/blob/master/examples/factory_and_properties/factory.script

In the factory.script I add a string value to a lookup table and use a hash as a key. I then pass the key to the created game object and in the init() function of the created game object I lookup the string value again using the provided key.

6 Likes

There are no plans on providing that currently. @Ragnar_Svensson can perhaps explain the thoughts behind the design.

We steer away from strings in the runtime at all times since they are so problematic. A single string has no real impact on anything, but since they are so convenient for us humans they tend to rapidly populate the memory. In the worst case, you can end up with the most problematic of perf issues; when a lot of things take a little time each, summing up to a problem. It takes a really long time to fix issues like that. This is why we deliberately don’t support strings, to guide users towards working with hashes which are free from these issues.
The exception is obviously as you stated, when you want to display information to the player. The information comes from two sources, static (which often becomes localised and fits well in a string library) or dynamic from web services or other players. In the dynamic situation it still makes sense to keep these things in a separate data store and the thing to display stuff has a key into that store (like @britzl’s example). You might want to be able to supply place holder info in the absense of responses, etc.

9 Likes

This looks perfect and cleaner.

I understand what you mean. I’m unsure if these will always cover the scenarios though. Unfortunately this indirection doesn’t provide a smooth flow for a developer to transition to using defold. It seems developer would normally gravitate and expect to be able to do certain things and restricting this by design seems odd and should frankly be handled some fluid way (maybe define a custom string implementation that gives you the benefits of both worlds). But i appreciate the help.

Suppose I’m making a tutorial for my game, placing dozens of “info” signs near various tutorial levels and objects. They all look the same, but display different text when clicked. In Unity/UE4 you would just place the same prefab dozens of times, and then edit the property of each individual info sign, which is a string! Same for other game objects that look alike but display/say different texts, like NPCs with one-liners and unique names. How can I achieve this in Defold without creating a mess, like setting an int instead of a string, and then looking the actual string up from the int?

I’d use a hash as property and use that to lookup a string from a dictionary (table). This is really the way to go, especially if you plan to translate the text in your game.

4 Likes

I’m creating a lot of texts, infos, names, etc in the way guys are describing here :wink: it is very convenient, when you want to change some text or in translating. You can create a Lua module that would store every usage combination like:

M.TOUCH = 1
M[1] = hash("touch")
M.string[M.TOUCH] = "touch detected"

Then you don’t need to remember the correct number, proper string or hash, but only a mnemonic name and use it anywhere.

if action_id == btn[btn.TOUCH] then
    print(btn.string[btn.TOUCH])
end

if k == btn.TOUCH then... end 
for i =1,2 do print(btn.string[i]) end

Or in localisation:

M.string[M.touch].eng = "touch the screen" 
M.string[M.touch].pol = "dotknij ekranu"

I would even make M.eng and M.pol a number to use it like this:

curr_lang = btn.eng
print(btn.string[btn.TOUCH][curr_lang])
9 Likes

This is good to know. I’m using strings all over the place. Looks like I have another “rewrite everything” deal ahead of me.

2 Likes

Unfortunately, the link no longer works. Can you or anybody else provide an explanation of how to do this that won’t suffer from link decay?

Have a look here: https://www.github.com/britzl/defoldexamples/tree/master/examples%2Ffactory_and_properties

Sorry to dredge up an old discussion, but this has me a little puzzled. The string implementation is not applied because of performance? But all strings in Lua are hashed. Even when you concat a string, it is hashed - there are no direct string manipulation ops on just maintaining strings. If people want to run gsubs, or matches, then thats a functional issue, not a resource one.

This leaves me wondering why this feature would be skipped - seems to be a nice-to-have. In my case, being able to have simple get/set props on certain go’s would be very useful without a msg merry-go-round (which is actually far less performant btw - having to wait for update for completion).

Could someone explain this better. I feel like maybe Im missing something obvious. Do strings get sent up the SDK API? Because that would then make a little more sense, but kinda not :slight_smile: … since ‘why’ comes to mind :slight_smile:

To explain my thinking a little. There is care about performance of strings, but much of the SDK uses Lua api calls (vmath a classic example) where if you call alot of vmath functions you will create the same “string” styled issue. If you use a Lua based one, the perf probs go away (I have a lua verlet physics test that does exactly this). And so, I think (personally) it might be a valuable feature to have string properties (I think it makes it also a little more consistent).

End Dave Rant. :slight_smile:

[ additional q ] What would be the appropriate method for “getting” text associated with a game object that has been generated in the game object (not for display btw - for data reasons). How would you attempt this via a message? ( req → resp? )

2 Likes