godotengine / godot

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

MultiplayerSynchronizer.add_visibility_filter seems not work #93254

Open dicarne opened 2 months ago

dicarne commented 2 months ago

Tested versions

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

alpapaydin commented 2 months ago

also having similar problems, synchronizer visibility needs better documentation

dicarne commented 2 months ago
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.