Network Client use wrong input devices when using Unity.Netcode with Starter Asset Controller (New input system) - unity3d

The server is always using Keyboard and Mouse just fine.
The client however always use "xbox controller" instead of Keyboard & Mouse:
The following is the inspector view as a client:
The Start Asset input action are unchanged,
This is what I tried but client is still being assigned to controller:
private void Start()
{
if (!IsOwner)
{
Destroy(GetComponent<PlayerInput>());
}
}
How could I fix this? Other than hard coding (PlayerInput)map.SwitchCurrentControlScheme("KeyboardAndMouse");?

This issue is fixed by disabling Player Input script.
And only enable it on Network Spawn.
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
if (IsOwner)
{
_playerInput = GetComponent<PlayerInput>();
_playerInput.enabled = true;
}
}

Related

Unity - Mirror Networking : Player client disconnect after scene changed

I'm currently using Mirror Networking to make a multiplayer game. I have a scene when players are all connected, they can choose their characters and set the ready. If all players are ready, I change current scene to arena scene using MyNetworkManager.ServerChangeScene(arenaSceneName). This method sets all player clients as not ready. But After the scene was loaded, my player client is no longer connected to my host and I don't know why.
Can you help me please ?
Thanks a lot for answers.
Clients that connect to this server will automatically switch to this scene. This is called automatically if onlineScene or offlineScene are set, but it can be called from user code to switch scenes again while the game is in progress. This automatically sets clients to be not-ready. The clients must call NetworkClient.Ready again to participate in the new scene."
if its not solve problem can you give more information about your project
Are you using MatchInterestManager ? This can be lead some problems like yours
Edit 1 -
Maybe the problem was host
can you run your code on server not host
Edit 2 -
i belive your command function runs on client not server because you miss "Cmd" prefix on your command function change it CmdOnAllPlayersReady()
public class ReadyPlayerChecker : NetworkBehaviour
{
public List<PlayerBehaviour> activePlayers;
public List<PlayerBehaviour> GetActivePlayers()
{
return activePlayers;
}
// Start is called before the first frame update
void Start()
{
activePlayers = new List<PlayerBehaviour>();
}
// Update is called once per frame
void Update()
{
foreach (PlayerBehaviour player in FindObjectsOfType<PlayerBehaviour>
(true))
{
if(!activePlayers.Contains(player))
{
activePlayers.Add(player);
}
}
bool allPlayersReady = true;
foreach (PlayerBehaviour player in activePlayers)
{
if (!player.IsReady())
{
allPlayersReady = false;
}
}
if (allPlayersReady && activePlayers.Count > 0)
{
OnAllPLayersReady();
}
}
[Command]
public void OnAllPLayersReady()
{
GameObject.Find("SceneManager").GetComponent<SceneChanger>
().LoadScene("SimpleArena");
}
}
This is my Network Manager settings :
I succeed to make the playerclient connected when the scene change. Now, the player prefab for my client is in host view but not in the corresponding client view. Do someone can tell me why ?

How do I make the Scoreboard on the side not be visible when the Debug HUD is open?

I'm working on a 1.16.5 Minecraft client-side mod and I am trying to get the scoreboard to be invisible when the Debug HUD is visible. I have a basic mixin to the scoreboard's rendering function but I need to be able to check for whether the DebugHud is visible or not.
Code:
#Mixin(InGameHud.class)
public class MScoreboardHUD {
#Inject(at = #At("HEAD"), method = "renderScoreboardSidebar")
private void init(CallbackInfo info) {
// soon
}
}
Answer
Using MinecraftClient.options.debugEnabled will tell you whether the F3 menu is active.
Final Code
This uses client as the MinecraftClient object, and info.cancel() to cancel the scoreboard render
#Mixin(InGameHud.class)
public class MScoreboardHUD {
#Inject(at = #At("HEAD"), method = "renderScoreboardSidebar")
private void init(CallbackInfo info) {
if (client.options.debugEnabled) {
info.cancel();
}
}
}

Unet Syncing animator layer weight Unity 3D

I'm currently working on a multiplayer fps to learn UNET and Unity. in this project I'm using Network Animator Component to sync my animations.
I have one layer that runs the normal states like walking and jumping and another that just controls the upper body for scoping. This layer gets activated when scoping.
The parameters a syncing fine but not the layer weight.
The script that controls the layer weight gets disabled on the remote player as it is part of the same script that takes care of shooting and we don't want to shoot from the remote player.
So I placed that code on a different script and made Layerweight a Syncvar, still no results.
this is the snippet that sets the weight and fades it back out.
if (isScoped)
{
animator.SetLayerWeight(1, 1);
layerWeight = 1;
}
else
{
layerWeight = Mathf.Lerp(layerWeight, 0, 0.1f);
animator.SetLayerWeight(1, layerWeight);
}
animator.SetBool("Scoped", isScoped);
how can I sync a variable that is updated on a disabled script?
And what are the different custom attributes like [Command] and [ClientRpc] I should use to get this working?
I have read the documentation and manuals of UNET, but struggle at this relatively easy task as I'm having a hard time understanding the difference of these calls.
In general the main problem with [SyncVar] is that they are
synchronized from the server to clients
so not the other way round!
Then
[Command] is a method that is called by any client but only executed on the server
[ClientRpc] is kind of the opposite, it is called by the server and then executed on all clients
so what I would do is have a setter method for the layerweight like
private void SetLayerWeight(float value)
{
// only player with authority may do so
if(!isLocalPlayer) return;
// Tell the server to update the value
CmdSetLayerWeight(value);
}
[Command]
private void CmdSetLayerWeight(float value)
{
// Server may now tell it to all clients
RpcSetLayerWeight(value);
}
[ClientRpc]
private void RpcSetLayerWeight(float value)
{
// called on all clients including server
layerweight = value;
animator.SetLayerWeight(1, layerweight);
}
and call it like
if (isScoped)
{
SetLayerWeight(1);
}
else
{
SetLayerWeight(Mathf.Lerp(layerWeight, 0, 0.1f));
}
Note though that passing this forth and back between server and client will cause some uncanny lag!
You would probably be better syncing the isScoped bool instead and assign the value directly on the calling client:
private void SetScoped(bool value)
{
// only player with authority may do so
if(!isLocalPlayer) return;
// for yourself already apply the value directly so you don't have
// to wait until it comes back from the server
scoped = value;
// Tell the server to update the value and who you are
CmdSetLayerWeight(value);
}
// Executed only on the server
[Command]
private void CmdSetLayerWeight(bool value)
{
// Server may now tell it to all clients
RpcSetLayerWeight(value);
}
// Executed on all clients
[ClientRpc]
private void RpcSetLayerWeight(bool value)
{
// called on all clients including server
// since setting a bool is not expensive it doesn't matter
// if this is done again also on the client who originally initialized this
scoped = value;
}

Loader during Unity IAP Callback

I want to put loader in between dialog boxes come up for the purchase. What is the way for this?
Because when game player press Buy button, he should require to wait for 5 to 10 second depends on internet speed and server response and this process happed 2 to 3 times because multiple dialogs come up within screen.
So in this case, may be player can leave the screen. I want to put the loader so that game player realise that some processing is running in background, he required to wait for some time.
At present I was following completely this code for Unity IAP setup.
Integrating Unity IAP In Your Game
I assume this is for mobile platform but even if its not still the following can be considered:
Simple solution is to create a full screen Image (UI/Panel) object in your UI to block clicks. I would use Animator component (with triggers) to display this panel in front of other UI when there is a background process running.
public class Loader : MonoBehaviour
{
public static Loader Instance;
Animator m_Animator;
public bool Loading {get; private set;}
void Awake()
{
Instance = this; // However make sure there is only one object containing this script in the scene all time.
}
void Start()
{
//This gets the Animator, which should be attached to the GameObject you are intending to animate.
m_Animator = gameObject.GetComponent<Animator>();
Loading = false;
}
public void Show()
{
Loading = true;
m_Animator.SetBool("Loading", Loading); // this will show the panel.
}
public void Hide()
{
Loading = false;
m_Animator.SetBool("Loading", Loading); // this will hide the panel.
}
}
Then in any script which manipulates UI:
public void BuyButtonClicked()
{
Loader.Instance.Show();
// process time taking stuff
Loader.Instance.Hide();
}
You can also create any kind of loading animation as child of panel object using simple images and animation tool inside Unity (for example rotating animation (use fidget spinner, its cool)).
And in case of Android where user have option to leave screen by pressing OS back button you can prevent going back by checking if any loading is in progress by following example:
// code for back button
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
BackButtonPressed();
}
}
void BackButtonPressed()
{
if(Loader.Instance.Loading)
return;
// use back button event. (For example to leave screen)
}
Hope this helps ;)

JavaFx set volume on MediaPlayer not working

This question has been asked before but to date there is no answer. I have just struck the same problem. I traced into the mediaplayer source and all is well until I get to gstSetVolume in GSTMediaPlayer for which I don't have the source.
At that point the volume value is still correct.
After setting the volume System.out.println(player.getVolume()); reports the correct value (0.0 - 1.0) BUT the volume has not changed. If the slider is set to 0, the audio is muted. Any other value is full volume.
Platform is Netbeans 8.1 on Windows 7 with JavaFX-8 and JDK-8 and the media source is a standard mp4 which works on all tested players (Windows, VLC etc).
Here is the code attached to a MediaView (which works well):
Runnable videoLoop;
PlayListViewController playListViewController;
// Videos are looped here
public void startVideoLoop() {
playerIndex = 0;
videoLoop = () -> {
// Previous player MUST be stopped otherwise it is left
// in the PLAYING state and the next video will not PLAY
if (player != null) {
player.stop();
}
// Point to the next player
if (++playerIndex == videoPlayersList.size()) {
playerIndex = 0;
}
playVideoSequence();
};
playVideoSequence();
}
public void playVideoSequence() {
// If the video options are shown we can update the listview
if (playListViewController != null) {
playListViewController.setListViewItem(playerIndex);
}
player = videoPlayersList.get(playerIndex);
mediaView.setMediaPlayer(player);
player.setOnEndOfMedia(videoLoop);
player.play();
}
A right mouse button press then invokes a 'settings' option. This is a View Controller which is attached to an FXML view. The controller receives a reference to the videoField when it is invoked. Here is the relevant snippet:
private void setHandlers() {
idVolumeSlider.valueProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue arg0, Object arg1, Object arg2) {
// videoField is a separate class
videoField.setVolume(idVolumeSlider.getValue());
}
});
I'm sorry I cannot supply a 'cut and paste' example, because that would mean a lot of pruning and simplifying of classes to achieve that with the risk of introducing additional problems.