How do I detect if there are multiple windows of my game open?

Godot Version

4.6.3.stable

Question

I’ve seen multiple games where if you open another window of the game when you already have one open, it gives you a message saying you can’t have multiple open, and then that second one closes. How do I achieve this? Or in short: How do I detect if there are multiple windows of my game open?

There are multiple games that I’ve made that would benefit from having this implemented. So thanks in advanced!

There’s no built-in way to do this, but I’ll give you an answer I gave another user:

Every project gets its own per-user persistent storage that scripts can acces using user://-prefixed URLs.
Notice how i said “every project”, not “every instance”. Never tried it myself, but i think two instances of the same project will share the same user:// base directory.
Knowing this, you can keep a resource at user://instances.tres and have the game load it at startup.


class GameInstances extends Resource:
  @export var instances: Array[GameInstanceEntry]
  pass

class GameInstanceEntry extends Resource:
  @export var pid: int
  @export var name: String

  func _init(new_pid, new_name):
    pid = new_pid
    name = new_name
    pass
  pass

Then at game start you make some script check for entries on that resource:

var game_instances = load("user://instances.tres")
if (not game_instances.is_empty()):
  # there is already an instance running
  # bunch of cross-window multiplayer code...
  pass
else:
  # there are no other instances running.
  # single-player init...
  pass
  game_instances.append(GameInstanceEntry.new(OS.get_process_id(), "MY GAME 3: RELOADED RETURNS PLUS ULTRA TURBO"))
  # you can order players by instance spawn order
  set_player_id(game_instances.length())
  game

Based on the posts text, I think OP isn’t looking for a local multiplayer game, and instead, wants to make sure only a single instance of their game runs.

In that case, your code has a flaw which the answer I gave above fixes:
If your game crashes, the residual file will still exist, and at that point, your game can no longer function until your player manually removes the file.

If pid file is used, you could check if the process with given pid still exists, but I guess that would require executing OS specific stuff with OS.execute.

Another way would be creating TCP server. Something like this:

var server: TCPServer

func _ready() -> void:
	server = TCPServer.new()
	var ok = server.listen(12345, "127.0.0.1")
	if ok != OK:
		prints("probably already running another instance")

But this isn’t problem free either. You need to pick a port number than nobody else uses. Unfortunately the port number is only a 16 bit integer, so it is pretty much guaranteed that someone has something else already running on that port.

I could include crash handling and live instance introspection but then a bunch of other stuff would have be be cascaded into the example and the small suggestion would turn into a 400-line cross-instance bus.