godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.8k stars 21.13k forks source link

When I release my app on Google Play Console, current scene does NOT switch to next scene. #89724

Open mattsunkun opened 7 months ago

mattsunkun commented 7 months ago

Tested versions

Godot Engine v4.2.1.stable.official [b09f793f5]

System information

macOS Sonoma v14.1.2

Issue description

I'm not sure that this is a bug or my coding error, but I couldn't get what happened to me. When I release my app on Google Play Console, current scene does NOT switch to next scene. I used get_tree().change_scene_to_file("res://Src/Start/Start.tscn") to switch scene. First time to load some scene had no problem, but the second time to load the same scene does NOT work.

Steps to reproduce

Note: My app contains some ads. If it is not nice, please let me know and I will fix it to stop ads temporarily.

  1. Clone my app from my GitHub repository. Export android .apk file and install it to local Android evice.

  2. Download the app from Google Play

  3. Play each game(by tapping the button "Beginner" to start) to the scene shown on the picture below.

    image
  4. Tap any enabled button

  5. App from .apk worked, however app from Google Play does Not work.

Minimal reproduction project (MRP)

My Working GitHub Repository

huwpascoe commented 7 months ago

The code is okay and the presentation is good.

But "result.gd" is really bad. It's just been copy-pasted together with no understanding, there are many errors. Delete it all, verify that change_scene_to_file() works and then start again, do it properly.

# 書き直してください

extends Node2D
var interstitial_ad : InterstitialAd
var interstitial_ad_load_callback := InterstitialAdLoadCallback.new()
var full_screen_content_callback := FullScreenContentCallback.new()

func _ready():
    pass

func _on_button_pressed():
    if interstitial_ad:
        interstitial_ad.destroy()
        interstitial_ad = null
    get_tree().change_scene_to_file("res://Src/Start/Start.tscn")
mattsunkun commented 7 months ago

Thank you so much for your comment!! I tried the method destroy() but it doesn't work. When I was researching my error, I found my error occurs when I export my app WITHOUT debug mode. So I wondered what is happening WITH debug mode. I watched my console with Android Studio WITH debug mode my app, and came up with the error

USER ERROR: Condition "!is_inside_tree()" is true. Returning: false
2024-03-28 02:15:10.209 13483-13588 godot                   com.mygame.android.mathing           E     at: can_process (scene/main/node.cpp:762)
image

With searching the error above, I found the issue( https://github.com/godotengine/godot/issues/48607 ) like this problem. But I couldn't understand how to solve it. If you know anything else about this problem, I would appreciate your idea.

P.S. I tried some solutions(such as [call_deferred("remove_child", "res:/Src/Result/Result.tscn")], [moving audio stream player node to the top of the scene tree]) shown on the issue I mentioned above. However, I even don't understand why my code works on [Home.gd, Start.gd, and Stage.gd], but doesn't work on [Result.gd]. I really appreciate your help.

huwpascoe commented 7 months ago

I don't have access to the errors but what I do know is the app is freezing when those buttons are pressed.

Most likely the advert library is blocking, which is why result.gd needs to be rewritten.

See the manual page: https://poing-studios.github.io/godot-admob-plugin/ad_formats/interstitial/

extends Node2D

var _interstitial_ad : InterstitialAd

func _ready() -> void:
    #The initializate needs to be done only once, ideally at app launch.
    MobileAds.initialize()

func _on_load_pressed():
    #free memory
    if _interstitial_ad:
        #always call this method on all AdFormats to free memory on Android/iOS
        _interstitial_ad.destroy()
        _interstitial_ad = null

    var unit_id : String
    if OS.get_name() == "Android":
        unit_id = "ca-app-pub-3940256099942544/1033173712"
    elif OS.get_name() == "iOS":
        unit_id = "ca-app-pub-3940256099942544/4411468910"

    var interstitial_ad_load_callback := InterstitialAdLoadCallback.new()
    interstitial_ad_load_callback.on_ad_failed_to_load = func(adError : LoadAdError) -> void:
        print(adError.message)

    interstitial_ad_load_callback.on_ad_loaded = func(interstitial_ad : InterstitialAd) -> void:
        print("interstitial ad loaded" + str(interstitial_ad._uid))
        _interstitial_ad = interstitial_ad

    InterstitialAdLoader.new().load(unit_id, AdRequest.new(), interstitial_ad_load_callback)

It's very important to follow the documentation. Unlike game logic, you're connecting to a service, one where money is involved. You need to learn what these function calls are doing and why.

MobileAds.initialize() was never called, there's no reference to the admob test strings "ca-app-pub-...", the destroy() methods are never called. All these steps need to be followed correctly 100%.