Accessing internal state (self) of another game object? (SOLVED)

Hi, is it possible to access the internal state (variables defined in “self”) of another game object provided I have it’s URL?

Say, if I have a game object “enemy” with a script component that has variable “self.velocity” (added in the init() function), doing one of the following just gives me the error " ‘(null)’ does not have any property called ‘velocity’ ":

go.get(“enemy”, “velocity”)
go.get(“enemy#script”, “velocity”)

Using go.get(…) to access values defined using go.property(…) works fine. What’s the difference?

Cheers
Robin

go.property is a way to declare properties with a lot more features than self.x:

  • Being overridden when exposed in game objects, collections
  • Supporting go.get/go.set/go.animate

Being more complex, they also have a different cost and effect on the system. This is why we don’t do it for everything you put in the self-tables, as they also will typically contain purely internal state.

1 Like

So how would one go about having a variable that can be accessed from the outside of the game object without it being visible and editable from the properties panel in the editor?

I’m still trying to grasp not being able to use objected oriented concepts (not being able to have get/set methods to call on the object). I guess one could send a message asking for the value and the receiver would send another message back with the value but that seems weird? Also I need the value in a module and I don’t think modules can receive messages?

You can create a Lua module, include it in whatever you want to be able to access the values.

Could you give an example of such a property?

A vehicle which has a velocity (self.velocity) that is updated every frame (shouldn’t be seen an editable in properties). If another vehicle is chasing a vehicle and uses a “pursuit” steering behavior it needs access to the velocity of the vehicle it’s chasing so that it can predict where it’s going, as to be able to travel towards it’s future position instead of the current position.

This is if the vehicle is Kinematic and only updated through my own physics calculations.

Ah, ok, so personally I’d put velocity as a go.property() simply because of the convenience of go.get(), but you could also create a Lua module that can be used to look up values based on a key. Something like: https://github.com/britzl/publicexamples/blob/master/modules/lookup.lua

Another option would be to use messages to at some interval ask for the velocity of the other game object, but that will be less elegant thanks to it’s asynchronous behaviour (although you could get around that by wrapping in a coroutine and writing a small Lua module).

1 Like

The lookup module seems like a nice solution. But as you say, just turning the velocity into a property is more convenient so I’ll probably go for that instead. Thanks for your suggestions!

I facing the same issue as Robin. I tried to do go.propety() method but I didn’t success.
When I call go.get(hash("/instace0"), “health”) from my factory script, console tells me: '[/instance0]’ does not have any property called ‘health’.
And when I call go.get(hash("/instace0"), “position.x”) I get the proper value.

Is there any way to pass parameter from instances to other gameobjects apart from using messaging?

P.D. The link which britzl has suggested as another solution it’s broken.

Hi Playtypus.
You will need to adress the specific script and not the whole gameobject.
go.get("/instance#script",“health”)

To pass data between gameobjects and over the project I usually use this small module which I call gop.lua (GameObjectProperties)

local M = {}

local gop_tables = {}

function M.get(url)
	url = url or msg.url(".")
	if type(url) == "string" then url = msg.url(url) end
	if gop_tables[url.path] == nil then gop_tables[url.path] = {} end
	return gop_tables[url.path]
end

function M.final(url)
	url = url or msg.url(".")
	if type(url) == "string" then url = msg.url(url) end
	gop_tables[url.path] = nil
end

return M

In a go.script I can then do like this:

self.gop = gop.get()
self.gop.health = 20

Now, in another gameobject I can retrieve the same table by getting gop by url:

local data = gop.get("/gameobjects_url")
print(data.health)

Now, I, most of the time only use this to be able to share data between several scripts on the same gameobject. Then I don’t have to pass in any url as it defaults to the gameobject url.
Hope that helps?

11 Likes

Thanks a lot. The module works perfectly and the first solution too. Now I understand more how the whole topic of url works. Thanks man

2 Likes

This should be in the documentation IMHO

4 Likes

Yes, making a note about updating the script properties manual.

3 Likes