UIComponent
script.uiEntity.Owner.set(player)
when you want to transfer a UI to the player’s local client. This call can happen inside or outside of the UIComponent
scripts.UIComponent
script will be executed on the player’s local client, which will remove the networking during binding updates and callback response, reducing the binding and callback turnaround time to minimal.binding.set(newValue)
without a player list) will act like player value updates (calling binding.set(newValue, [owner])
), and will only affect the local player.binding.set(newValue)
without a player list) nor player value updates (calling binding.set(newValue, [anotherPlayer])
).UIComponent
script as Local, the UI becomes invisible, until its ownership is transferred to a player, and then be visible to that player only. This is the major difference from Default mode UI which is visible to all players by default.uiEntity.visible.set
and uiEntity.setVisibilityForPlayers
uiEntity.visible.set(false)
. Similarly, a player cannot see a locally owned UI by other player, even if the UI has uiEntity.visible.set(true)
.Default (Non Local Mode) | Local Mode, assigned to player1 | |
---|---|---|
Entity Visibility false (through visible.set ) | To Player1: no To Player2: no | To Player1: no To Player2: no |
Entity Visibility true (through visible.set ) | To Player1: yes To Player2: yes | To Player1: yes To Player2: no |
Entity Visibility true For Player1 (through setVisibilityForPlayers ) | To Player1: yes To Player2: no | To Player1: yes To Player2: no |
Entity Visibility true For Player2 (through setVisibilityForPlayers ) | To Player1: no To Player2: yes | To Player1: no To Player2: no |
player
in the callbacks.uiEntity.setVisibilityForPlayers
.UIComponent
script in the Default Mode first, and only change the gizmo to the Local Mode once it is working in the Default Mode already.MyUI
: example implementation of a normal UIMyUIAdvanced
: example implementation of a UI that contains extra state for transfer purpose. This implementation is optionalMyTrigger
: example script that transfers the ownership// MyUI script, attached to Custom UI gizmo, set to *Local* mode
// component props
type TProps = { ... };
class MyUI extends UIComponent<TProps> {
static propsDefinition: PropsDefinition<KeyDialogProps> = {
...
};
initializeUI() {
return View({
...
});
}
}
// Optional implementation
// MyUIAdvanced script, attached to Custom UI gizmo, set to *Local* mode
// component props
type TProps = { ... };
// optional extra information you want to carry when transfer UI
// from one to another can be any SerializableState
type TState = {
msg: string;
my_num: number;
};
class MyUIAdvanced extends UIComponent<TProps, TState> {
static propsDefinition: PropsDefinition<KeyDialogProps> = {
...
// optional to implement, runs on new owner client who receive the ownership
receiveOwnership(
state: TState \| null,
fromPlayer: Player,
toPlayer: Player,
) {
console.log("this log happens on new owner client, after the transfer", state);
}
// optional to implement, runs on old owner client before transfer away ownership
transferOwnership(fromPlayer: Player, toPlayer: Player): TState {
console.log("this log happens on old owner client, like server, before the transfer");
// returning the data in TState type that's transferred to new owner
return {
msg: "some msg",
my_num: 123
};
}
initializeUI() {
return View({ ... });
}
}
UIComponent.register(MyUIAdvanced);
// MyTrigger script, have an UI object as prop, and set the owner once a
// player enter the trigger. This script stays on *Default* mode
type Props = {ui: Entity};
class MyTrigger extends Component<Props> {
static propsDefinition: PropsDefinition<Props> = {
ui: {type: PropTypes.Entity},
};
start() {
this.connectCodeBlockEvent(
this.entity,
CodeBlockEvents.OnPlayerEnterTrigger,
(player: Player) => {
this.props.ui.owner.set(player);
},
);
}
}
Component.register(MyTrigger);