64M35 4-2: Sister Topic

I’m not sure if it’s a good idea to have a topic dedicated to all sorts of question I might have while making my practice project, but I do not want to spam for every little question or fill the Dev diary topic either.

If it is in fact not a good idea, I’ll close this topic the next time I have a new type of question


ERROR:GAMEOBJECT: Instance ‘manager:controller#manager’ could not be found when dispatching message ‘load_level’ sent from main:/main_gui#main_gui

and/or

ERROR:SCRIPT: /main/main_menu.gui_script:95: Could not send message ‘load_level’ from ‘main:/main_gui#main_gui’ to ‘manager:controller#manager’.
stack traceback:
[C]:- 1: in function post

I have read THIS topic, which mentions these errors, and while I’m sure I could have missed something, I am also sure that the issues mentioned do not apply to my situation. The collections I want to communicate are both loaded and I used the separate_collection:path/game_object#component url in the msg.post(url,message_id,message) function


27-05-22_manager_collection
how the manager.collection looks like


and how the main.collection looks like

I hope I explained it adequately, if not, feel free to ask.
Today’s post has the entire progress documented, and the entire original topic has the project’s progression logged, as well as an outdated project.zip

If anyone can help, I would greatly appreciate.

PS.: not that it probably matters, but I also tried writing the url as 'manager:/controller#manager' and 'manager/controller#manager'

My guess is that you forgot to set the Name of manager.collection in the outline, as that specific error message seems to only happen when trying to send a message to a collection that doesn’t exist.

4 Likes

Ugh, why is that a thing


It works absolutely as intended now.
Thank you!

I can’t believe I was struggling with that for this long.

I feel you, and I cannot say for sure the original reason for this.

Ideally, I would have it so that the “name” of the collection was empty as a default, and if empty, it would choose the name of the collection file.
Not sure how hard that would be for us to do, but in the long run, some simplification of this would solve a few head scratches.

7 Likes

The trick you need to learn is print(msg.url("#"))

That prints the URL of whatever script you put it in, which is often handy. I still use this technique all the time.

1 Like

Another option would be to show the name instead of “Collection”, to keep it consistent with other components.

1 Like

Instance ‘object’ could not be found when dispatching message ‘message_id’ sent from world:/object#fragment


I’m stuck on a similar note to the last one. It could be an addressing issue, but I cannot be sure.
It is not a typo and I’m farely certain it is not a false name.


The outline of the specific file I’m addressing

level_manager go is native to the collection, it does not exist outside it. This is the only place it is named.

'pause.gui_script'
self.my_parent = msg.url().socket
self.msg_all = msg.url(self.my_parent, "level_manager", "level_manager")
msg.post(self.msg_all, "resume_game")
'starter_.gui_script'
self.collection = msg.url().socket
self.level_manager = msg.url(self.collection, "level_manager", "level_manager")
msg.post(self.level_manager, "resume_game")

These are the only scripts so far that address that object. The reason they’re coded this way is so that I can just throw them into a new collection without having to rewrite the code per-collection.

I thought maybe it’s a hash(s) issue, but this is a userUrl type object anyway, it should be a valid address.

The whole collection gets loaded at once, I don’t think this specific game object is unloaded when the messages are sent.

ERROR:GAMEOBJECT: Instance 'level_manager' could not be found when dispatching message 'pause_game' sent from pong:/pause#pause_gui
ERROR:GAMEOBJECT: Instance 'level_manager' could not be found when dispatching message 'resume_game' sent from pong:/starter#starter_gui
ERROR:GAMEOBJECT: Instance 'level_manager' could not be found when dispatching message 'resume_game' sent from pong:/pause#pause_gui

EDIT: forgot the game object outline

I’m don’t know why that doesn’t work, but I do know that you don’t need to do all that just to send a message to another object in the same collection. It’s as simple as:

msg.post("level_manager#level_manager", "resume_game")

You don’t even need to specify the ID of the script, since a message sent to a game object will automatically be forwarded to all of its components:

msg.post("level_manager", "resume_game")

That much I knew about addressing, but I put it in anyway as a ‘just in case’ because to my understanding it didn’t make a difference…

However, I just changed it to msg.post("level_manager", "resume_game") and the errors went away. I checked to see if it was a fluke, and level_manager.script received all the messages no problem, which confused me more than why it didn’t work before.

function on_message(self, message_id, message)
    pprint(message_id)
    ...
end
-->hash: ["resume_game"]

So thank you! :smiley:

Edit:
I changed it to msg.post(msg.url("level_manager"), "message")

SCRIPT DOESN’T EXECUTE AS INTENDED USING GUI.ANIMATE()

No errors today to use in the heading.

This is going to be something stupid, I know it.
I’ve written a game object to display instructions and controls at the beginning of every level via a series of sprites and animations. It may be skipped as well as accessed through the pause menu.

It doesn’t work. It pauses the game while nothing happens until you pause and unpause it yourself.

There is a sequencing I’ve had in mind when designing it:

  1. proxy_manager loads the level
  2. all game objects initiate
  3. level_manager sends a "pause" message to everything and a "start" message to the intro gui (called starter_gui)
  4. the starter_gui runs through 5 animation functions and a countdown timer or until being skipped and sends a resume message to the level_manager
  5. the game proceeds as intended

Using debugging pprint() functions, the desired log ought to look a bit like:

Desired log
INFO:DLIB: SSDP: Started on address xxx.xxx.x.xxx
DEBUG:SCRIPT: Loaded 	url: [manager:/controller#PRXY_intro]
DEBUG:SCRIPT: Unloaded 	url: [manager:/controller#PRXY_intro]
DEBUG:SCRIPT: Loaded 	url: [manager:/controller#PRXY_main]
DEBUG:SCRIPT: Unloaded 	url: [manager:/controller#PRXY_main]
DEBUG:SCRIPT: Loaded 	url: [manager:/controller#PRXY_pong]
DEBUG:SCRIPT: Updated all objects in P0N6 with pause_game
DEBUG:SCRIPT: Told starter in P0N6 to initiate starter procedure
DEBUG:SCRIPT: TEXTURES SET
DEBUG:SCRIPT: STARTER ANIMATION 1
DEBUG:SCRIPT: STARTER ANIMATION 2
DEBUG:SCRIPT: STARTER ANIMATION 3
DEBUG:SCRIPT: STARTER ANIMATION 4
DEBUG:SCRIPT: STARTER ANIMATION 5
DEBUG:SCRIPT: STARTER COUNTDOWN FINISHED
DEBUG:SCRIPT: STARTER COMPLETE
DEBUG:SCRIPT: Updated all objects in P0N6 with hash: [resume_game]
INFO:DLIB: SSDP: Done on address xxx.xxx.x.xxx
Instead I get this
INFO:DLIB: SSDP: Started on address xxx.xxx.x.xxx
DEBUG:SCRIPT: Loaded 	url: [manager:/controller#PRXY_intro]
DEBUG:SCRIPT: Unloaded 	url: [manager:/controller#PRXY_intro]
DEBUG:SCRIPT: Loaded 	url: [manager:/controller#PRXY_main]
DEBUG:SCRIPT: Unloaded 	url: [manager:/controller#PRXY_main]
DEBUG:SCRIPT: Loaded 	url: [manager:/controller#PRXY_pong]
DEBUG:SCRIPT: Updated all objects in P0N6 with pause_game
DEBUG:SCRIPT: Told starter in P0N6 to initiate starter procedure
DEBUG:SCRIPT: TEXTURES SET
DEBUG:SCRIPT: STARTER ANIMATION 1
-- the logs stop here until I press 'Escape'
DEBUG:SCRIPT: STARTER COMPLETE
DEBUG:SCRIPT: STARTER COUNTDOWN FINISHED
DEBUG:SCRIPT: STARTER SKIPPED SUCCESSFULLY
DEBUG:SCRIPT: Updated all objects in P0N6 with hash: [resume_game] --> pressing escape skips the intro and so resumes the game
DEBUG:SCRIPT: Updated all objects in P0N6 with hash: [pause_game] --> pressing escape also pauses the game, which will be a future bug when stuff actually works
INFO:DLIB: SSDP: Done on address xxx.xxx.x.xxx

Normally I’d currate the code to be readable on the blog, but honestly I have no idea what messes up, and I’ve been banging my head at this for a few days so…

The entire `starter_.gui_script`
local hide_all
local set_textures

local anim1
local anim2
local anim3
local anim4
local anim5
local skip_explanation
local countdown
local finish_it

--[[
TO DO:

* make a messaging system to define textures                  -- CHECK
* make mock/final textures at least for debugging purposes    -- CHECK
* make a countdown function,    -- CHECK
* make a function that displays the gui and hides it appropriately    -- CHECK
* make all the animation and skip functionality    -- CHECK
* add pause menu "show hints" button that brings the gui back up.    -- CHECK
* make it work
]]--

function init(self)
	msg.post(".", "acquire_input_focus")

	-- this makes coding the rest easier-ish
	self.nodes = {
		TIPS = gui.get_node("tips"),
		TIPS_CHILD = {gui.get_node("explanation"), gui.get_node("controls")},
		CONTROLS = {gui.get_node("p1_controls"), gui.get_node("p2_controls")},
		CNTDWN = gui.get_node("countdown"),
		CNTDWN_TXT = gui.get_node("countdown_txt"),
		SKIP = gui.get_node("skip_prompt"),
		SKIP_TXT = gui.get_node("skip_prompt_txt"),
	}
	-- this list will make displaying the correct items easy per level
	self.textures = {
		CONTROLS = {},
		EXAMPLES = {},
	}
	self.collection = msg.url().socket --> first message ought to define the current level collection.
	self.level_manager = msg.url("level_manager") --> the full url returns an error for some reason???

	hide_all(self)
end

function on_message(self, message_id, message, sender)
	if message_id == hash("start") then
		--self.collection = sender.socket
		set_textures(self)
		hide_all(self)
		--now do some actual stuff
		anim1(self)
	end
end

function on_input(self, action_id, action)
	if action.released then
		if action_id == hash("lefCtrl") 
		or action_id == hash("riCtrl") 
		or action_id == hash("ctrX") 
		or action_id == hash("enter") 
		or action_id == hash("pause") then
			skip_explanation(self)
		end
	end
end

function hide_all(self)
	for i, n in pairs(self.nodes) do 
		if type(n) == "table" then 
			for ii, nn in pairs(n) do 
				gui.set_enabled(nn, false)
			end
		else
			gui.set_enabled(n, false)
		end
	end
end

function set_textures(self, cllction, ctrl_p1, ctrl_p2)
	cllction = cllction or "default"
	ctrl_p1 = ctrl_p1 or "default_controls"
	ctrl_p2 = ctrl_p2 or "default_controls"
	--get textures
	self.textures.EXAMPLES = {
		cllction .. "_starter",
		cllction .. "_anim"
	}
	self.textures.CONTROLS = {
		ctrl_p1, 
		ctrl_p2
	}
	--set textures.
	-- gui.set_texture --> set the atlas
	-- gui.play_flipbook --> set specific sprite or animation 
	gui.play_flipbook(self.nodes.TIPS_CHILD[1], self.textures.EXAMPLES[1])
	gui.play_flipbook(self.nodes.CONTROLS[1], self.textures.CONTROLS[1])
	gui.play_flipbook(self.nodes.CONTROLS[2], self.textures.CONTROLS[2])
	pprint("TEXTURES SET")
end

--animation time 
function anim1(self) 
	local node = self.nodes.TIPS_CHILD[1]
	local now_colour = gui.get_color(node)
	now_colour.w = 0
	local to_colour = now_colour
	to_colour.w = 1
	
	gui.set_enabled(node, true)
	gui.set_color(node, now_colour)
	gui.animate(node, gui.PROP_COLOR, to_colour, gui.EASING_LINEAR, 2.5, 0, anim2, gui.PLAYBACK_ONCE_FORWARD)
	pprint("STARTER ANIMATION 1")
end
function anim2(self)
	pprint("STARTER ANIMATION 2 - beginning")
	local node = self.nodes.TIPS_CHILD[1]

	gui.set_enabled(node, true)
	gui.play_flipbook(node, self.textures.EXAMPLES[2], anim3)
	pprint("STARTER ANIMATION 2 - end")
end
function anim3(self)
	local node = self.nodes.TIPS_CHILD[1]
	local now_colour = gui.get_color(node)
	now_colour.w = 1
	local to_colour = now_colour
	to_colour.w = 0

	gui.set_enabled(node, true)
	gui.set_color(node, now_colour)
	gui.animate(node, gui.PROP_COLOR, to_colour, gui.EASING_LINEAR, 2.5, 0, anim4, gui.PLAYBACK_ONCE_FORWARD)
	pprint("STARTER ANIMATION 3")
end
function anim4(self)
	gui.set_enabled(self.nodes.TIPS_CHILD[1], false)
	local node = self.nodes.TIPS_CHILD[2]
	gui.set_enabled(node, true)
	local now_colour = gui.get_color(node)
	now_colour.w = 0
	gui.set_color(node, now_colour)
	local to_colour = now_colour
	to_colour.w = 1
	
	gui.animate(node, gui.PROP_COLOR, to_colour, gui.EASING_LINEAR, 2.5, 0, anim5, gui.PLAYBACK_ONCE_FORWARD)
	pprint("STARTER ANIMATION 4")
end
function anim5(self)
	gui.set_enabled(self.nodes.TIPS_CHILD[1], false)
	local node = self.nodes.TIPS_CHILD[2]
	gui.set_enabled(node, true)
	local now_colour = gui.get_color(node)
	now_colour.w = 1
	gui.set_color(node, now_colour)
	local to_colour = now_colour
	to_colour.w = 2

	gui.animate(node, gui.PROP_COLOR, to_colour, gui.EASING_LINEAR, 2.5, 5, countdown, gui.PLAYBACK_ONCE_FORWARD)
	pprint("STARTER ANIMATION 5")
end
--skip first part 
function skip_explanation(self)
	local anmtbls = {
		self.nodes.TIPS_CHILD[1],
		self.nodes.TIPS_CHILD[2],
	}
	for ind, node in pairs(anmtbls) do
		gui.cancel_animation(node, gui.PROP_COLOR)
	end	
	gui.cancel_flipbook(anmtbls[2])
	countdown(self)
	pprint("STARTER SKIPPED SUCCESSFULLY")
end
-- countdown time 
function countdown(self)
	-- countdown duration
	local tmr = 3 --seconds
	local node = self.nodes.CNTDWN
	local node_txt = self.nodes.CNTDWN_TXT

	gui.set_enabled(node, true)
	gui.set_enabled(node_txt, true)

	gui.set_text(self.nodes.CNTDWN_TXT, tostring(tmr))
	for i = tmr, 0, -1 do
		timer.delay(1, false, function (obj, handle, elapsed) 
			--print("Executed timer from: " .. tostring(obj) .. ", with handle: " .. tostring(handle) .. " after: " .. tostring(elapsed) .. "s") 
		end)
		gui.set_text(node_txt, tostring(i))
	end
	finish_it(self)
	pprint("STARTER COUNTDOWN FINISHED")
end
-- and end 
function finish_it(self)
	msg.post(self.level_manager, "resume_game")
	hide_all(self)
	pprint("STARTER COMPLETE")
end
The entire `level_manager.script`
local update_all 
local get_positions 
local reset_positions 
local restart_game 

function init(self)
	msg.post(".", "acquire_input_focus")
	
	self.objects = {
		"/ball",
		"/player1",
		"/player2",
	}
	self.positions = get_positions(self)

	msg.post(".", "show_hints")
end

function on_message(self, message_id, message)
	if message_id == hash("pause_game") then 
		update_all(self, message_id)
	elseif message_id == hash("resume_game") then 
		update_all(self, message_id)
	elseif message_id == hash("show_hints") then 
		update_all(self, "pause_game")
		local receiver  = msg.url("starter")
		msg.post(receiver, "start")
		print("Told starter in P0N6 to initiate starter procedure")
		--pprint(receiver)
	elseif message_id == hash("restart_game") then 
		restart_game(self)
	else
		-- nothing
	end
end

function update_all(self, message_id)
	for i, t in pairs(self.objects) do 
		msg.post(t, message_id)
		pprint("Updated all objects in P0N6 with " .. tostring(message_id))
	end
end

function get_positions(self) 
	local positions = {}

	for i, t in pairs(self.objects) do 
		local pos = go.get_position(t)
		positions[i] = pos 
	end

	return positions
end

function reset_positions(self)
	for i, t in pairs(self.positions) do
		go.set_position(t, self.objects[i])
	end
	print("Reset all objects' positions in P0N6")
end

function restart_game(self)
	reset_positions(self)
	msg.post("ball", "restart_game", {time = 3})
	print("Told ball in P0N6 to reset.")
end

while we’re at it, the level_manager also fails to reset positions of game objects in the function reset_positions(self) and I do not understand why. Is there any limitations or quirks on manipulating other objects’ positions?

function reset_positions(self)
	for i, t in pairs(self.positions) do
		go.set_position(t, self.objects[i])
	end
	print("Reset all objects' positions in P0N6")
end

If anyone has the time, will and ability to check the code for why it doesn’t work (other than poor coding practices and ‘it’s bad’) I would greatly appreciate. This is I thikn the last task I want to complete before moving on to building new world collections and mini-games.

Hi!

You are calling a function before you define it:

gui.animate(node, gui.PROP_COLOR, to_colour, gui.EASING_LINEAR, 2.5, 0, anim2, gui.PLAYBACK_ONCE_FORWARD)

You have this line which calls a function called anim2, but anim2 isn’t described until later on, so it won’t run.Try reversing the order of those 5 functions in the code and see if it works.

1 Like

http://www.lua.org/pil/6.2.html

See here.

    local jingle(self)
    	Print("this will print!")
    end 

    function init(self)
    	jingle(self)
    	jangle(self)
    end 

    local jangle(self)
    	Print("this will not print because jangle was called before it was declared.")
    end

In this example, you’d have to include a line that “forward declares” the functions at the top of the script. It would look like this:

local jingle, jangle

In your example, it would be something like (haven’t checked your whole script but you should try adding this at the top of your script):

local anim1, anim2, anim3, anim4, anim5

Oops. Didn’t spot that. Well, try using this as your anim1 function. Pay attention to the local node line. I think you had a mistake there, but it’s hard to tell on my phone because your system for storing node names is a little complicated.

Local function anim1(self) 
	local node = gui.get_node("tips")
	local new_color = 1
	gui.set_enabled(node, true)
	gui.set_color(node, now_colour)
	gui.animate(node, "color.w", new_color, gui.EASING_LINEAR, 2.5, 0, anim2, gui.PLAYBACK_ONCE_FORWARD)
	pprint("STARTER ANIMATION 1")
end

You can animate RGB and Alpha values independently- if you’re only animating alpha (to make something more or less transparent) you can use “color.w”.

Haven’t checked this code- give it a try and see what it says. I think the main issue was that

local node = self.nodes.TIPS_CHILD[1]

Should have been

local node = self.nodes.TIPS_CHILD

local node = self.nodes.TIPS_CHILD[1]
--correlates to the appropriate list:
self.nodes = {
		...,
		TIPS_CHILD = {gui.get_node("explanation"),...)},
        ...
}

I did try to call gui.get_node([id]) directly in the function, but it did not change anything. I disabled the gui.set_color([node], [vmath4]) and gui.animate(...) functions to see whether the node is visible at all or if the anim1(self) function even somewhat works. The node did not show up. I’m using the same exact system to bring up the pause menu gui and it still works fine.

I thought maybe it was a draw order issue, so I messed with the Z values in the collection. I changed the background sprite to a gui object to have it auto zoom, which drew over the player sprites.

I completely removed the background and the node still didn’t show up. Which leads me to believe that the hide_all() function works and the issue is indeed the animations.

function hide_all(self)
	for i, n in pairs(self.nodes) do 
		if type(n) == "table" then 
			for ii, nn in pairs(n) do 
				gui.set_enabled(nn, false)
			end
		else
			gui.set_enabled(n, false)
		end
	end
end
--[[
hide_all(self) which iterates over the convoluted self.nodes list
works perfectly fine]]
function anim1(self) 
	local node = self.nodes.TIPS_CHILD[1]
--or local node = gui.get_node("explanation")
	local now_colour = gui.get_color(node)
	now_colour.w = 0 --> set current colour to transparent
	local to_colour = now_colour
	to_colour.w = 1 --> and animate it to opaque
	
	gui.set_enabled(node, true)
	--gui.set_color(node, now_colour)
	--gui.animate(node, gui.PROP_COLOR, to_colour, gui.EASING_LINEAR, 2.5, 0, anim2, gui.PLAYBACK_ONCE_FORWARD)
	pprint("STARTER ANIMATION 1")
end
--[[
the animation does not even successfully enable 
the node in question

I am stumped. :confused: