Need Help With Video Extension

Peace Unto You! Okay so I’ve hit another wall in this. I’ve tried many variations of the code. I tried to have the video player be destroyed at a delay, disabled then load the main menu, now in the code I have a fail safe system that allows the main menu to load regardless of if the videoplayer is disabled or destroyed, and in the code it said both the main menu has been enabled and loaded, but the video player still appears on top of everything.

After some digging I theorized since the video player isnt native to Defold, the Z order of the video player go means nothing because my main menu z order is higher than everything else, so now I’m running into the same issue where, after the video ends the main menu doesn’t load. I put in the code to disable first then destroy, but even still since the fail safe is active the main menu isnt waiting for the video to be destroyed to appear but apparently the videoplayer will always appear on top of every collection and go.

Is there a way to prevent the videoplayer from always appear on top of everything?

Also me adding the delay didn’t fix the issue cause the main menu doesn’t show, and when I directly call for the video to be destroyed, the game just crashes. So why does the video player have this power?

Here are the errors I was getting from the debugger when I ran the game on my iPhone after the video ended

ERROR:GAMESYS: The collection /mainmenu/mainmenu.collectionc is already enabled Message ‘enable’ sent from loader:/go#loader to loader:/go#mainmenu.

ERROR:GAMESYS: Collection proxy already loaded: ‘/mainmenu/mainmenu.collectionc’ Message ‘load’ sent from loader:/go#loader to loader:/go#mainmenu.

ERROR:GAMEOBJECT: Component ‘/go#videoplayer’ could not be found when dispatching message ‘disable’ sent from mainmenu:/videoplayer#videoplayer

WARNING:GAMEOBJECT: Failed to call message response callback function, has it been deleted?

WARNING:DLIB: Failed to send announce message (-8)

RESOURCE_NOTIFY trigger for THEETHERS [2623] (45001 CPU wakes over 55.00s seconds, violating limit of 45000 CPU wakes over 300.00s seconds)

Received CPU wakes trigger:
THEETHERS[2623] () woke the CPU 45001 times over 55.95 seconds (average 804/sec), violating a CPU wakes limit of 45000 over 300 seconds.

Here’s my scripts.

Video player script:

local function log(msg)
print(msg)
end

local function video_callback(self, video, event, data)
log(string.format("VIDEO CALLBACK: video %d evt: %d ", video, event))

if event == videoplayer.VIDEO_EVENT_READY then
log("videoplayer.VIDEO_EVENT_READY")
videoplayer.start(video)
elseif event == videoplayer.VIDEO_EVENT_FINISHED then
log("videoplayer.VIDEO_EVENT_FINISHED")
msg.post(".", "video_end") -- Trigger message instead of immediate destruction
elseif event == videoplayer.VIDEO_EVENT_FAILED then
log("videoplayer.VIDEO_EVENT_FAILED")
msg.post(".", "video_end") -- Call end function on failure via message
else
log("Unexpected event")
end
end

function video_begin(self)
if videoplayer then
log("Loading video...")

local videos = {"Intro.mp4"} -- Ensure this matches your file name exactly
self.video = videoplayer.create(videos[1], {play_sound = true}, video_callback)

if not self.video then
log("Can't create another video")
msg.post(".", "video_end")
else
log("Video created successfully: " .. self.video)
end
else
log("Could not initialize fullscreen videoplayer (on this platform?)")
end
end

function video_end(self)
log("Video playback ended")

-- Try to hide the video player by sending the disable message
local success = msg.post("mainmenu:/go#videoplayer", "disable") -- Attempt to disable the video player

if success then
log("Video player disabled successfully.")
else
log("Failed to disable the video player.")
end

-- Attempt to load the main menu regardless
msg.post("loader:/go#loader", "load_menu")

-- Wait for a short delay before checking if the menu is loaded
timer.delay(2.0, false, function()
msg.post(".", "check_menu_loaded") -- Notify that we are ready to check if the menu is loaded
end)

self.video = nil
end

function check_menu_loaded(self)
-- Here you could check if the main menu is loaded
-- If it is, destroy the video
if self.is_menu_loaded then -- Assuming you set this variable when the menu is loaded
log("Main menu is loaded, destroying video.")
videoplayer.destroy(self.video) -- Destroy the video only if the menu is loaded
else
log("Main menu is not loaded yet.")
end
end

function init(self)
msg.post(".", "acquire_input_focus")
self.video = nil
self.is_menu_loaded = false -- Initialize menu loaded state
video_begin(self) -- Start the video as soon as the game initializes
end

function on_message(self, message_id, message, sender)
if message_id == hash("video_end") then
video_end(self)
elseif message_id == hash("menu_loaded") then
self.is_menu_loaded = true -- Set flag to indicate menu is loaded
log("Menu loaded confirmed.")
end
end

Loader Script:

local function load_menu(self)
msg.post("go#mainmenu", "load")
msg.post("go#mainmenu", "enable")
end

local function unload_menu(self)
msg.post("go#mainmenu", "unload")
end

local function load_main(self)
msg.post("go#main", "load")
msg.post("go#main", "enable")
end

function init(self)
msg.post(".", "acquire_input_focus")
load_menu(self) -- Load the main menu initially
end

function on_message(self, message_id, message, sender)
if message_id == hash("start_game") then
unload_menu(self)
load_main(self)
elseif message_id == hash("load_menu") then
load_menu(self) -- Make sure this loads the main menu
end
end

You will not be able to return something here. The msg.post() is asynchronous.

Question: Does the example project also crash? The one that is included with the extension:

Open :point_up: as a Defold project, build it, install on device, and observe what happens.

1 Like

Peace Unto You! I’ve opened the example project before and didn’t see any issues.

This issue makes no sense.

How is it so hard to simply load the main menu after the video plays??? Is this even possible? I’m really starting to think it’s not even possible. Is there any examples of people with cutscenes that are videos in their game?? Is anyone able to provide their code? Like I gave my code and you see that everything pertaining to the videoplayer in the example project gui script is in this code, hence why the video plays correctly, but the fact that the video crashes the game when it ends even after the main menu is loaded is the biggest issue.

Like it’ll be one thing if the main menu didn’t load, but it’s a whole new thing that the menu loaded and is enabled, but the videoplayer is somehow blocking it, and the whole game crashes when the video ends.

Example project script:

local function log(msg)
print(msg)
gui.set_text(gui.get_node(“label”), msg)
end

local function video_callback(self, video, event, data)
log(string.format("VIDEO CALLBACK: video %d evt: %d ", video, event))
pprint(data)

if event == videoplayer.VIDEO_EVENT_READY then
	print("videoplayer.VIDEO_EVENT_READY")
	videoplayer.start(video)
elseif event == videoplayer.VIDEO_EVENT_FINISHED then
	print("videoplayer.VIDEO_EVENT_FINISHED")
	video_end(self, video)
elseif event == videoplayer.VIDEO_EVENT_FAILED then
	print("videoplayer.VIDEO_EVENT_FAILED")
else
	print("Unexpected event")
end

end

function video_begin(self)
if videoplayer then
log(“Loading…”)

	local videos = {"big_buck_bunny_720p_1mb.mp4"}

	self.play_sound = not self.play_sound
	self.video = videoplayer.create(videos[math.random(#videos)], {play_sound = self.play_sound}, video_callback)
	log(self.video)
else
	log("Could not initialize fullscreen videoplayer (on this platform?)")
end

if self.video == nil then
	log("can't create another video");
	video_end(self, self.video)
end

end

function video_end(self, video)
log(“Touch to start”)
gui.animate(self.box_node, “color”, self.color, gui.EASING_INOUTSINE, 0.5)
gui.set_enabled(self.label_node, true)
gui.set_enabled(self.logo_node, true)

if video ~= nil then
	print("Calling videoplayer.destroy", video)
	videoplayer.destroy(video)
end

self.video = nil;

end

function init(self)
msg.post(".", “acquire_input_focus”)
self.video = nil
self.tick = 1

self.box_node = gui.get_node("box")
self.label_node = gui.get_node("label")
self.logo_node = gui.get_node("logo")
self.color = gui.get_color(self.box_node)
self.play_sound = false

end

function on_input(self, action_id, action)
if action_id == hash(“touch”) and action.pressed then
gui.set_enabled(self.label_node, false)
gui.set_enabled(self.logo_node, false)
gui.animate(self.box_node, “color”, vmath.vector4(0, 0, 0, 1), gui.EASING_INOUTSINE, 0.5, 0, function()
video_begin(self)
end)
end
end

My Videoplayer Script:

local function log(msg)
print(msg)
end

local function video_callback(self, video, event, data)
log(string.format("VIDEO CALLBACK: video %d evt: %d ", video, event))

if event == videoplayer.VIDEO_EVENT_READY then
    log("videoplayer.VIDEO_EVENT_READY")
    videoplayer.start(video)
elseif event == videoplayer.VIDEO_EVENT_FINISHED then
    log("videoplayer.VIDEO_EVENT_FINISHED")
    msg.post(".", "video_end")  -- Trigger message for video ending
elseif event == videoplayer.VIDEO_EVENT_FAILED then
    log("videoplayer.VIDEO_EVENT_FAILED")
    msg.post(".", "video_end")  -- Handle failure case via message
else
    log("Unexpected event")
end

end

function video_begin(self)
if videoplayer then
log(“Loading video…”)

    local videos = {"Intro.mp4"}  -- Ensure this matches your file name exactly
    self.video = videoplayer.create(videos[1], {play_sound = true}, video_callback)

    if not self.video then
        log("Can't create another video")
        msg.post(".", "video_end")
    else
        log("Video created successfully: " .. self.video)
    end
else
    log("Could not initialize fullscreen videoplayer (on this platform?)")
end

end

function video_end(self)
log(“Video playback ended”)

-- Load the main menu immediately after video ends
msg.post("loader:/go#loader", "load_menu")

-- Wait 2 seconds, then destroy the video player
timer.delay(2, false, function()
    log("Destroying video player after delay.")
    if self.video then
        videoplayer.destroy(self.video)
        self.video = nil
    end
end)

end

function init(self)
msg.post(".", “acquire_input_focus”)
self.video = nil
video_begin(self) – Start the video as soon as the game initializes
end

function on_message(self, message_id, message, sender)
if message_id == hash(“video_end”) then
video_end(self)
end
end

My loader script:

local function load_menu(self)
msg.post(“go#mainmenu”, “load”)
msg.post(“go#mainmenu”, “enable”)
end

local function unload_menu(self)
msg.post(“go#mainmenu”, “unload”)
end

local function load_main(self)
msg.post(“go#main”, “load”)
msg.post(“go#main”, “enable”)
end

function init(self)
msg.post(".", “acquire_input_focus”)
load_menu(self) – Load the main menu initially
end

function on_message(self, message_id, message, sender)
if message_id == hash(“start_game”) then
unload_menu(self)
load_main(self)
elseif message_id == hash(“load_menu”) then
load_menu(self) – Make sure this loads the main menu
end
end

Could you please share a minimal project here as a zip file? Please include the source code for navigating between screens like you describe and playing a video. To keep the size of the zip archive down please exclude the video file itself. I can use the one from the example project.

Peace Unto You! Here’s a bare bones version of my game which includes main menu and loader. I made sure to take all the assets that didn’t pertain to this issue out to save space.

Thank you so much for all your help we are very grateful!
LINK TO MY TEST BUILD OF MY GAME

I took a look at your project and the device log shows:

default 08:34:35.551800+0200 THEETHERS DEBUG:SCRIPT: videoplayer.VIDEO_EVENT_FINISHED
default 08:34:35.552160+0200 THEETHERS DEBUG:SCRIPT: Ending Video
default 08:34:35.552485+0200 THEETHERS ERROR:GAMESYS: Collection proxy already loaded: ‘/mainmenu/mainmenu.collectionc’ Message ‘load’ sent from loader:/go#loader to loader:/go#mainmenu.
  1. In your loader.script you call load_menu() from init() which loads mainmenu.collection
  2. In your mainmenu.collection you start playing a video
  3. When the video ends you send msg.post("loader:/go#loader", "load_menu")
  4. You loader.script will try to load the menu again, but it is already loaded and you get error above.

There is also a problem in your video_end() function because you never destroy the video:

Use self.video instead of video

3 Likes

Peace Unto You! Thank you! So when you said use self.video instead of video what do you mean? I see self.video = nil, but I’m a little confused on that part. What do I change specifically? Do I take anything out? And I also thought destroy.video was enough cause that’s what it did in the example project.

I’m kinda lost here, so I need to know what to specifically change to destroy the video so I don’t mess something else up trying to implement your solution.

Thank you we are very grateful!

Edit: Are you talking about the if video = nill part? And change the video word to “self.video” and that’s all I have to do?

If im not mistaken then here image you should use

if self.video ~= nil then

instead of just

if video ~= nil then

because by just using video you are comparing to this
image whick you need to pass when you call the function here
image but you dont. If you wanted to pass the video into the function then you could do

video_end(self, self.video)
2 Likes

Peace Unto You! When I changed the code to self.video I get this error. So it’s still not working. I followed the steps, but why isn’t it still working.

edit: and when I edited the last part of the code from “video_end(self)” to “video_end(self, self.video)” it just crashed. When I made the “self.video” change only, the game didn’t crash but the video doesn’t get destroyed I get that error, and im not able to access the main menu per usual

ERROR:SCRIPT: mainmenu/videoplayer.script:53: bad argument #1 to ‘destroy’ (number expected, got nil)
stack traceback:
[C]:-1: in function destroy
mainmenu/videoplayer.script:53: in function <mainmenu/videoplayer.script:49>

Peace Unto You! When I changed the code to self.video I get this error. So it’s still not working. I followed the steps, but why isn’t it still working. Did you test it yourself to see if it works cause it’s not working for me.

ERROR:SCRIPT: mainmenu/videoplayer.script:53: bad argument #1 to ‘destroy’ (number expected, got nil)
stack traceback:
[C]:-1: in function destroy
mainmenu/videoplayer.script:53: in function <mainmenu/videoplayer.script:49>

here’s the code directly so you can see I made the change

function video_end(self, video)
log(“Ending Video”)
msg.post(“loader:/go#loader”, “load_menu”)

-- Wait 2 seconds, then destroy the video player
timer.delay(1, false, function()
	log("Destroying video player after delay.")
if self.video ~= nil then
	print("Calling videoplayer.destroy", video)
	videoplayer.destroy(video)
end

self.video = nil;

end)
end

The error says it all. There video variable is nil. Note that self.video and video are not the same thing.

1 Like

Peace Unto You! I’ve went through the manuals before and nothing is working hence why I’m here. When I gave you the zip did you yourself test to see if the code you provided worked? Because I did exactly as you asked and I’m still having issues. I showed you both the example code and mine and you seen for yourself little difference, so why are these issues happening?

I don’t know what to do. So is anyone able to assist me? The issue is very specific and with the zip anyone is able to check for themselves. It doesn’t make sense. So much so that it doesn’t seem possible. No manual is gonna help me with this specific issue when every time when we add a “solution” a new error appears, for a manual can only take you so far.

I’ve been at this for weeks so I need everyone to trust that I’ve exhausted every possible way INCLUDING AI and still to no avail. That’s why I say it doesn’t seem possible

Of course I tested. And I provided explanations and screenshots with the changes. Did you fix the issues I pointed out in my previous post?

It seems like you are missing fundamental understand of some Lua and Defold concepts. Do you for instance understand the meaning of different lexical scopes of Lua code and the use of self?

Please share your updated code so that we can take a look at the changes you made.

Please stop using AI. You will not learn anything from letting some AI solution write code which apparently doesn’t work and only confuse things further. Several other users on the forum have previously pointed out to you that the use of AI to write your code for you is a terrible idea.

3 Likes