Found no receiver for incoming ClientRpc on Player(Clone), the server and client should have the same NetworkBehaviour instances [netId=9] - unity3d

I am using Mirror SDK to implement multiplayer
when I test locally, one instance of build and one instance in unity editor, it works fine.
but If I test by running two builds on separate machines, it gives me this error.
I searched alot, haven't found any solution yet.
any help will be appreciated.
below is my code to use Client RPC
public void CmdSpawn(Vector3 position)
{
ComponentInstance = Instantiate(prefabToSpawn ,position,Quaternion.identity);
NetworkServer.Spawn(ComponentInstance,connectionToClient);
RpcAssignRefrence(ComponentInstance);
}
[ClientRpc]
public void RpcAssignRefrence(GameObject spawnedObject)
{
m_tempObject = spawnedObject.transform;
}

Related

How to re-register refit handlers in MAUI

In my MAUI, I register custom auth handlers using the following code snippet.
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCompatibility()
.UseMauiCommunityToolkit()
.RegisterRefitClients()
return builder.Build();
}
}
And my RegisterRefitClients extension method looks like this.
public static MauiAppBuilder RegisterRefitClients(this MauiAppBuilder mauiAppBuilder)
{
mauiAppBuilder.Services.AddRefitClient<IMyApiService>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri(Configuration.BASE_URL))
.AddHttpMessageHandler<AuthHeaderHandler>();
return mauiAppBuilder;
}
Here, the thing is, Configuration.BASE_URL can change at run time. By default, it always points to our production server. But the testers can change it to staging/dev server at run time. I want to invoke this method at run time, in order to set custom auth handler for the newly changed staging server.
But I cannot get the MauiAppBuilder instance anywhere in the app once it is initiated.
How do I call the RegisterRefitClients at run time?
RegisterRefitClients can not be called when the program start running. .NET MAUI enables apps to be initialized from a single location. The MauiProgram class is the entry point to the application, setting up configuration and wiring up services the application will use. Once the program starts, you can not change the MauiProgram.

Unity Netcode's ClientRpc is not being sent across the network

I copy and pasted Unity Netcode's example code from https://docs-multiplayer.unity3d.com/docs/advanced-topics/message-system/clientrpc to test it out. This is my exact code:
public class Test : MonoBehaviour
{
public TMP_Text text;
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
PongClientRpc(Time.frameCount, "hello, world"); // Server -> Client
}
}
[ClientRpc]
void PongClientRpc(int somenumber, string sometext)
{
text.text = $"{somenumber} : {sometext}";
Debug.Log(text.text);
}
}
What I've found is that the function just acts as a normal function whether it's called on the host application or client application, and it is never transmitted across the network. My expectation is that when it is called on the host application, the RPC would be transmitted to the client application and executed there as well, thus reflecting a change in the TMP_Text object, but clearly this is not the case.
Just to check all the boxes, this script is attached to a GameObject that also has a NetworkObject component. For good measure, I tested the TMP_Text object both with and without a NetworkObject component attached. In all cases, any object with a NetworkObject component was properly added to the NetworkManager's network prefabs list.
I'm starting to question if I even understand what an RPC is or how it's supposed to work. Any insights would be greatly appreciated!
This class needs to be derived from NetworkBehavior not MonoBehaviour else it won't be networked.
Make sure to add using Unity.Netcode; at the top of the class.

Missing something important with ClientRpc (Unity Mirror)

I'm having an issue with ClientRpc never being called any client objects. I've trolled the internet for hours, but I can't find any clues as to why my implementation isn't working.
I'm following an order of events like so:
Add players in a lobby
Switch scene to the gameplay scene
Generate random tiles on the server
Send tile data to the clients using Rpc for rendering
However, the rendering function never gets called.
NetworkManager.cs
public override void OnServerReady(NetworkConnection conn)
{
base.OnServerReady(conn);
//Make sure they're all ready
for (int i = RoomPlayers.Count - 1; i >= 0; i--)
{
if (!RoomPlayers[i].IsReady)
{
return;
}
}
//Previously add SpawnTiles to OnServerReadied
OnServerReadied?.Invoke(conn);
}
GameManager.cs
private void SpawnTiles(NetworkConnection conn)
{
//Generate rawTiles beforehand
Debug.Log(conn.isReady);
Debug.Log("Entered spawn tiles");
RpcSpawnTiles(rawTiles);
}
[ClientRpc]
public void RpcSpawnTiles(short[] rawTiles)
{
Debug.Log("Client spawning tiles");
}
And this is my output when run on a host:
True
Entered spawn tiles
It appears to never enter the Rpc function :(
Is there something super obvious that I'm missing? My GameManager does have a NetworkID attached to it
There seemed to be a combination of things that I had to do to get it to work- I'm not entirely sure which one worked, but if you are having these problems, these are some of the things I had to check-
Just basic code. Make sure that the appropriate things are being created on the client, host, or server
Make sure that there aren't any race conditions, especially when working with changing scenes. You can call stuff from OnClientSceneChanged and OnServerSceneChanged
As derHugo pointed out, I was not checking to see if my package could even be sent. It turns out that the maximum size that can be sent is 1200 bytes, while I was trying to send 100x100x4 bytes. This error didn't occur when I was testing on the host, only when there was an external client

Unet, how to sync a counter to check if all players are ready

I'm making a multiplayer bomberman game using Unet. I'm trying to create a ready check to start the game when everyone else is ready.
I tried using a sync var,Command and Rpc calls, but nothing seems to work properly.
When using a Cmd call this way (called when a player pushes the ready button)
[Command]
private void CmdIncreaseReady()
{
IncreaseReady();
RpcIncreaseReady();
}
[ClientRpc]
private void RpcIncreaseReady()
{
IncreaseReady();
}
private void IncreaseReady() {
playersReady++;
//ChechAllReady();
}
When pressed on the client, everyone's counter is 0 (it should be one), and when pressed on the server, the server's counter is 2 and the client 1.
I've tried to call Cmd when !isServer and Rpc when it is, and the result is that stills doesn't update when pressed on the client, but it is updated correctly (the counter is 1 on both), when pressed on the server.
if (!isServer)
{
CmdIncreaseReady();
}
else
{
RpcIncreaseReady();
}
If I delete the IncreaseReady() call on the Cmd, the result is the same than above.
I've tried too to use a [SyncVar] to the counter, with and without a hook, passing 1 on the hook (to increment the counter that amount) and passing the already counter incremented and set variable to that number, nothing seems to work.
I really don't know how to make it work anymore. Could someone help me? I'm really desperate with this. I've searched everywhere.
The script is the game manager, when every client has his version, it has a Netework Identity and has Local player Authority.
I've tried another approach, passing the increased number on the Cmd and Rpc, and inside the functions, just set the playersReady = i. Even that doesn't work.
[UPDATE]:
So, I've found the specific problem that I want to solve, and it's to Sync non-player objects properties.
I've tried to spawn the Game Manager with Client Authority, and now it seems to sync correctly only on the server, the client stills doesn't call the Cmd propety.
Looking at the Debug mode in the inspector, I've been able to see that on the server, hasAutority is true, but is false on the client.
This is a fragment of the code on the player script where I spawn the game manager:
void Update()
{
if (!sceneLoaded)
{
if(isServer & SceneManager.GetActiveScene().name == "Main Scene")
//if (SceneManager.GetActiveScene().name == "Main Scene")
{
if (connectionToClient.isReady)
{
var go = (GameObject)Instantiate(gameManager);
NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
go.transform.SetParent(null);
//go.GetComponent<NetworkIdentity>().AssignClientAuthority(connectionToClient);
globalManager = go.GetComponent<FSM>();
//SetFSM();
sceneLoaded = true;
}
}
}
UNET has a Lobby system which does exactly what I think you want. It has a per-player ready state, so that the game starts when all players are ready.
I would recommend using that, as it saves you having to reimplement things like dropping out, rejoining etc...

Why is my CE app refusing to run?

I've been maintaining a Windows CE app for some time now (over a year) and have produced new versions of it from time to time, copying them to the handheld device[s] and running the new versions there.
Today, though, I created a new Windows CE app for the first time. It is a very simple utility.
To create it in VS 2008, I selected a C# "Smart Device Project" template, added a few controls and a bit of code, and built it.
Here are some of the options I selected:
I copied the .exe produced via building the project to the handheld device's Program Files folder:
...but it won't run. Is it in the wrong location? Does it need some ancillary files copied over? Is there some other sort of setup I need to do to get it to run? Or what?
UPDATE
Since there's not much of it, I'm pasting ALL the code below in case somebody thinks my code could be the problem:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace PrinterCommanderCE
{
public partial class PrinterCommanderForm : Form
{
public PrinterCommanderForm()
{
InitializeComponent();
}
private void btnSendCommands_Click(object sender, EventArgs e)
{
SendPrinterCommands();
}
private void SendPrinterCommands()
{
bool successfulSend = false;
const string quote = "\"";
string keepPrinterOn = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}off{0}", quote);
string shutPrinterOff = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}on{0}", quote);
string advanceToBlackBar = string.Format("! U1 setvar {0}media.sense_mode{0} {0}bar{0}", quote);
string advanceToGap = string.Format("! U1 setvar {0}media.sense_mode{0} {0}gap{0}", quote);
if (radbtnBar.Checked)
{
successfulSend = SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
successfulSend = SendCommandToPrinter(advanceToGap);
}
if (successfulSend)
{
MessageBox.Show("label type command successfully sent");
}
else
{
MessageBox.Show("label type command NOT successfully sent");
}
if (ckbxPreventShutoff.Checked)
{
successfulSend = SendCommandToPrinter(keepPrinterOn);
}
else
{
successfulSend = SendCommandToPrinter(shutPrinterOff);
}
if (successfulSend)
{
MessageBox.Show("print shutoff command successfully sent");
}
else
{
MessageBox.Show("print shutoff command NOT successfully sent");
}
}
private bool SendCommandToPrinter(string cmd)
{
bool success = false;
try
{
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
serialPort.Close();
success = true;
}
catch
{
success = false;
}
return success;
}
}
}
UPDATE 2
Based on this, I added a global exception handler to the app so that Program.cs is now:
namespace PrinterCommanderCE
{
static class Program
{
[MTAThread]
static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
Application.Run(new PrinterCommanderForm());
}
static void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
MessageBox.Show(string.Format("GlobalExceptionHandler caught : {0}", e.Message));
}
}
}
Yet running the new build shows nothing - it just "flashes" momentarily with about as much verbosity as Lee Harvey Oswald after Jack Ruby's friendly visit.
UPDATE 3
Could the problem be related to this, and if so, how to solve it?
The circumstance that both my updated version of an existing app AND this brand new and simple app refuse to run indicate there is something fundamentally flawed somewhere in the coding, building, or deployment process.
UPDATE 4
As this is a minimal utility, the reason it (and my legacy, much more involved) app are not working may have something to do with the project properties, how it's being built, a needed file not being copied over, or...???
NOTE: The desktop icon is "generic" (looks like a blank white form); this perhaps indicates a problem, but is it indicative of something awry or is it a minor (aesthetics-only) problem?
UPDATE 5
In Project > Properties..., Platform is set to "Active (Any CPU)" and Platform target the same ("Active (Any CPU)")
I have read that this is wrong, that it should be "x86", but there is no "x86" option available - Any CPU is the only one...?!?
UPDATE 6
In Project > Properties... > Devices, the "Deploy the latest version of the .NET Compact Framework (including Service Packs)" is checked. Is this as it should be?
UPDATE 7
Okay, here's the really strange part of all this:
I have two CF/CE apps that I need to run on these Motorola/Symbol 3090 and 3190 handheld devices.
One is this simple utility discussed above. I find that it actually does run on one of the devices (the 3190, FWIW). So it runs on one device, but not on the other.
HOWEVER, the other (legacy) .exe is the opposite - it runs on the 3090 (where the utility will not even start up), but not on the 3190.
So the utility's needs are met by the 3190, and the legacy util's needs are met by the 3090. However, the NEW version of the legacy app does not run on either device!
I am baffled; I feel as Casey Stengel must have when speaking once of his three catchers: "I got one that can throw but can't catch, one that can catch but can't throw, and one who can hit but can't do either."
UPDATE 8
The 3190 has a newer version of the CF installed; it seems that both the new and the old apps should run on the new device with the newer CE, but they don't - only the one built against/for the new framework does...
UPDATE 9
Here is what the 3090 looks like:
UPDATE 10
So I have two exes, one that runs on the devices (both of them now), and the other that will run on neither of the devices. The two exesw seem almost identical. I compared them with three tools: Red Gates' .NET Reflector; JetBrains' dotPeek, and Dependency Walker.
Here is what I found:
Dependency Walker
Both seem to have the same errors about missing dependencies (I didn't have them in the same folder with their dependent assemblies is probably the problem there)
.NET Reflector
The nonworking file has this entry that the working file does not:
[assembly: Debuggable(0x107)]
Is this the problem and, if so, how can I change it?
JetBrains dotPeek
The References in the working copy of the exe are all version 1.0.50000.0
The non-working exe has an identical list of References, and the same version number.
There is this difference, though:
For the working .exe, dotPeek says, "1.4.0.15, msil, Pocket PC v3.5"
For the non-working .exe, dotPeek says, "1.4.0.15, msil, .Net Framework v4.5"
Is this the problem and, if so, how can I change the non-working .exe to match the working one?
This last is disconcerting, primarily because I see no place in the non-working (newer) version of the project where a "4.5" string exists. Where could dotPeek be getting that information?
UPDATE 11
I do know now that the problem is somewhere between these two MessageBox.Show()s, because the first one I see, but not the second:
public static int Main(string [] args)
{
try
{
// A home-brewed exception handler (named ExceptionHandler()) is already defined, but I'm adding a global one
// for UNHANDLED exceptions (ExceptionHandler() is explicitly called throughout the code in catch blocks).
MessageBox.Show("made it into Main method"); // TODO: Remove after testing <= this one is seen
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
string name = Assembly.GetExecutingAssembly().GetName().Name;
IntPtr mutexHandle = CreateMutex(IntPtr.Zero, true, name);
long error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
{
ReleaseMutex(mutexHandle);
IntPtr hWnd = FindWindow("#NETCF_AGL_BASE_",null);
if ((int) hWnd > 0)
{
SetForegroundWindow(hWnd);
}
return 0;
}
ReleaseMutex(mutexHandle);
DeviceInfo devIn = DeviceInfo.GetInstance();
Wifi.DisableWifi();
// Instantiate a new instance of Form1.
frmCentral f1 = new frmCentral();
f1.Height = devIn.GetScreenHeight();
f1.Text = DPRU.GetFormTitle("DPRU HHS", "", "");
MessageBox.Show("made it before Application.Run() in Main method"); // TODO: Remove after testing <= this one is NOT seen
Application.Run(f1);
devIn.Close();
Application.Exit();
return 0;
}
catch(Exception ex)
{
DPRU.ExceptionHandler(ex, "Main");
return 0;
}
} // Main() method
UPDATE 12
More specifically, I've got infinite looping going on somehow; By mashing the "Ent" pill on the handheld device (that's what the button looks like - a "lozenge") - it sounds like gerbils tap-dancing (as debugging MessageBox.Show()s in two methods pop up and are dismissed over and over ad infinitum ad (literally) nauseum).
If an application does not start it is mostly missing something. As you compiled for WindowsCE and CF3.5, the Compact Framework 3.5 runimes have to be installed on the WindowsCE device.
Normally Compact Framework is part of Windows CE images, at least version 1.0, but who knows for your test device? If at least one CF is installed, an app requiring a newer CF version will show that on start by a message stating about the missed version. So either no CF is on your device, or something is goind real wrong.
You can run \Windows\cgacutil.exe to check the CF version installed on the device. The tool will show the version of installed CF.
You can debug using a TCP/IP connection or ActiveSync connection. See remote debuggung elsewhere in stackoverflow, I wrote a long aanswer about remote debug via TCP/IP. Or does your device neither have USB and WLAN or ENET?
Update: Here is the answer for remote debug via tcp/ip: VS2008 remotely connect to Win Mobile 6.1 Device This will also enable the remote deployment "In Project > Properties... > Devices, the "Deploy the latest version of the .NET Compact Framework (including Service Packs)" is checked. Is this as it should be?"
Are the earlier apps you wrote also written .NET? Compact framework does not care about the processor architecture, only the CF runtimes have to match the processor. So you do not need an x86 target as if you write a native C/C++ SmartDevice project.
To your comments:
a) CF1.0 is installed on the device.
b) the exe built on the colleagues computer seems to be built for CF1 and therefor runs OK.
c) your exe is built for CF 3.5 and does not run as there is no CF3.5 runtime on the device.
d) most CF exe files are very small as long as they do not include large resources or ...
Conclusion so far: Install the CF3.5 runtime onto the device: http://msdn.microsoft.com/en-us/library/bb788171%28v=vs.90%29.aspx.
To run the legacy app on both devices, the referenced Motorola or other 3rd party runtimes must also be installed. I stringly recommand to setup your environment so you can use ActiveSync/WMDC for development, deployment and debugging of the device. If you are unable look for some more experienced colleague.
Can you try to run it inside the debugger and check where it fails?
Can you place a breakpoint right at the beginning of Program.main and check if it's reached?
Debug output may also give you some interesting hints.