godot icon indicating copy to clipboard operation
godot copied to clipboard

MultiplayerSynchronizer.add_visibility_filter seems not work

Open dicarne opened this issue 1 year ago • 2 comments

Tested versions

  • Reproduced in 4.3.beta1

System information

Windows11

Issue description

MultiplayerSynchronizer.add_visibility_filter does not seem to change the visibility of the corresponding peer, even though the filter returns true. I thought that if the filter returns true, it means it is visible, but it is not. Is there something wrong with my understanding?

Steps to reproduce

  1. nodes like this: image MultiplayerSynchronizer setting: image

  2. add filter: image

  3. check peer's visibility, I think if the visibility filter returns true, then visibility should be true. image

however, visibility is still false.

image

  1. However, when using set_visibility_for to set visibility directly, it takes effect image

image

code overview

image

Minimal reproduction project (MRP)

add_visibility_filter.zip

dicarne avatar Jun 17 '24 04:06 dicarne

also having similar problems, synchronizer visibility needs better documentation

alpapaydin avatar Jul 04 '24 11:07 alpapaydin

bool MultiplayerSynchronizer::is_visible_to(int p_peer) {
	if (visibility_filters.size()) {
		Variant arg = p_peer;
		const Variant *argv[1] = { &arg };
		for (Callable filter : visibility_filters) {
			Variant ret;
			Callable::CallError err;
			filter.callp(argv, 1, ret, err);
			ERR_FAIL_COND_V(err.error != Callable::CallError::CALL_OK || ret.get_type() != Variant::BOOL, false);
			if (!ret.operator bool()) {
				return false;
			}
		}
	}
	return peer_visibility.has(0) || peer_visibility.has(p_peer);
}

The relevant source code is as above. It seems that if any filter returns false, it is not visible. If it is public or has been explicitly specified as visible to p_peer, then it is visible. That is, it is visible only when:

  1. The node is public and passes all filters.
  2. The node has been specified as visible to a peer, and all filters can allow this peer to be visible.

Therefore: When the node is specified as not public, but the filter allows a peer to be visible, and has not been explicitly specified as visible to this peer through set_visibility_for, this node will not be seen by this peer.

dicarne avatar Jul 06 '24 08:07 dicarne

This genuinely looks like a bug. If the filter returns true, isn't that sufficient to make a decision about the visibility? What's the usefulness of needing to pass the filter AND set the visibility explicitly for the node? Especially if the function is called add_visibility_filter()

voidexp avatar May 10 '25 17:05 voidexp

Based on the code snippet provided by dicarne, it looks like the filter runs ON TOP of the public visibility. So if public visibility is false, and you only use a filter, NO ONE will see your syncs. You have to set public visibility to TRUE (or give a particular peer visibility to the object). Yikes that is not intuitive. I spent 2 days debugging this.

Note I would LOVE if we had "visibility groups", i.e. if you're part of the node visibility group, you get the sync changes, otherwise you don't. This would simplify everything.

Much love Godot devs. +1 to whoever documents this better and +1000 if anyone can add visibility groups 🥹

dginovker avatar Jul 29 '25 06:07 dginovker