Unity Ninja Battle Tutorial - "Failed initializing runtime modules","error":"TypeError: matchSignal not found"

Hi,
I am working through the Unity Ninja Battle Tutorial (and have copied all the TS files across to the Nakama folder in my c drive) and I am getting an error on the Docker for container “nakama_nakama_1” where it exits a few seconds after pressing play. The error I can see in the logs are as per below. If container “nakama_cockroachdb_1” is not playing, “nakama_nakama_1” will play fine, otherwise, it exits instantly. If I remove the “index” java script file from the “modules” folder, “nakama_nakama_1” will play. Any advice on what steps to take to try solve this problem?

Many thanks.

"Failed initializing runtime modules","error":"TypeError: matchSignal not found

:tv: Media:

The bundled index.js file committed to the project repository seems to be outdated, we’ll make sure to update it.

In the meantime, please run npm i && tsc from within the ninja-battle-nakama/Nakama folder, and copy the rebuilt modules/index.js file to the nakama modules folder, this is the bundled js file and the only one that you need.

Hope this helps.

1 Like

Did what you said and it works now. Thanks for your help!

Just one more thing. I’m going through the TS files and it looks like I don’t need all of them. All I want is to be able to find/join a match and send match states. I had this setup and working before, but it was client relayed rather than server authorative. Am I correct to say I only really need the enums, main & rpc TS files? Looks like I will still have to modify these nonetheless. Unless there is a basic typescript template to cover the joining of matches and sending match states…

I will continue watch tutorials anyway, but any help would be appreciated. Thanks!

I’m not completely familiar with that game’s code, but if you’re only planning on using client relayed you shouldn’t need anything related to the match handlers registration.

Would the match handlers registration be required so the games can stay open between players when they log off?

Sorry, but I’m new to this. Correct me if I’m wrong, but basically, I send match states in the game with NakamaManager.Instance.Socket.SendMatchStateAsync(match.Id, (long)code, json). I understand this should be received by the server. Do I just set a function in the server script to broadcast out this received match state - sending with it the same op code and data received (depending on the op code received, it will trigger a function locally for the players)? Will the server retain all the match states sent even after players disconnect so that players can rejoin at another time and continue where they left off?

Thanks in advance!

Yes, you’ll need authoritative match handlers for that.

You can write some simple server code to do what you mention - just relay the messages to the connected players, but you’ll also need to handle reading the match state from the messages so that it is kept by the match. Mind that an authoritative match will run forever unless it is explicitly terminated (unless Nakama: Configuration | Heroic Labs Documentation is set to != 0).

Opcodes are just numerical values you can arbitrarily attribute to the messages to identify or hint at their content before you decode them. It’s up to you to implement how you handle the messages in the client based on the received opcode.

Maybe it’s easier to backtrack a little bit, could you elaborate on what are you trying to achieve? Meanwhile, you can see another authoritative example here:

Thanks for the assistance, I’ll rewind a bit here to explain what my goal is.
Basically, my game is a bit like chess. It’s a 2 player game where each player takes a turn to move a unit, cast abilities etc. The way my code is setup is, for example, if player 1 moves a unit, it will do so locally on his/her device. At the same time, to synchronise player 2’s game board, it sends a match state to player 2 which will contain the opCode for “MoveUnit” along with location data (Vector3 converted to a Json string) of the unit that is to be moved and the tile it is to move to. Player2 receives the match state (OnReceivedMatchState), identifies the opCode is for “MoveUnit” and calls the MoveUnit function on his/her device (using the Vector3 Json strings to identify which Unit to move and to which tile). So, the only information being sent over the network are the opCodes along with any required data for the receiving player to perform the same function on his/her device. The functions are called on the players devices themselves. I had this setup and working fine, but it wasn’t an authorative match.

I want the game to be persistent, just like 2 player games on Android/IOS such as Word With Friends. I would like to be able to jump into a match, move some units, cast abilities etc. and then exit the game. The other player will be notified I have made my move and will be able to log into the game when they are ready and perform moves themselves…which then I will receive notification it is now my turn to make moves. Only way to completely quit the game is hitting the “surrender” button or if it’s been a certain number of days without any response from the player and hence will automatically forfeit the game. Otherwise, the match will stay open.

Does this make sense?

(Meanwhile, I will have a look at the link you shared!)

Ok got it, yes it makes sense and I think the linked template is a good place to start :slight_smile:. It’s an example implementation of authoritative match handlers for tic-tac-toe. In this template, the matches terminate after inactivity and have a set amount of time to finish (with a normal and fast game modes), but it should be easy enough to serve as a basis for what you’re trying to achieve.
The template also exemplifies how to handle reconnects.

There’s also a client side implementation, although it is in PhaserJS and not Unity, but perhaps it could prove useful to you anyway: GitHub - heroiclabs/xoxo-phaserjs.

Thanks again for your help. Will go through the link provided.

Hi again, just something I’m stuck on which I am hoping you can assist me with. I am able to send match states from Unity, the server receives the messages fine and sends back the op code correctly, however, it doesn’t return the data that was attached with the opCode. Instead it always returns “System.Byte”. See codes below:

The following code in Unity works fine.

        public void SendPlayerMsg()
        {
			var values = new Dictionary<string, string>
		{
			{"PlayerMessage",chatWindow.GetComponentInChildren<InputField>().textComponent.text.ToString()}
		};

			long opCode = (long) MultiplayerManager.Code.PlayerMessage;
			string state = values.ToJson();

			MultiplayerManager.Instance.SendMatchState((MultiplayerManager.Code)opCode, state);

            chatWindow.GetComponentInChildren<InputField>().text = "";

        }

        public void SendMatchState(Code code, object data = null)
        {
            if (match == null)
            {
                Debug.Log("No match state sent as match is null");
                return;
            }
            string json = data != null ? data.Serialize() : string.Empty;
            Debug.Log("Match State sending: "+json);
            if (enableLog)
                LogData(SendingDataLog, (long)code, json);

            NakamaManager.Instance.Socket.SendMatchStateAsync(match.Id, (long)code, json);
        }

The code below is what I have in Nakama. I assume the “message.data” is incorrect when broadcasting the message. I just don’t know what the correct reference should be here so that the server returns the json data I sent through with the opCode from Unity.

var matchLoop = function (context, logger, nakama, dispatcher, tick, state, messages) {
    var gameState = state;

    var presencesOnMatch = [];
    for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) {
        var message = messages_1[_i];
        dispatcher.broadcastMessage(message.opCode, message.data);
        logger.info("Sending Code: " + message.opCode + "& Sending Data: " + message.data);
    }
    return gameState.endMatch ? null : { state: gameState };
};

Thanks in advance for any advice you can provide.

What version of Nakama are you using?

I am currently using version 3.4.0.

If it’s version 3.4.0 please upgrade to latest and retry, there were changes made to binary handling in the JS runtime since.

I’ve updated to the latest (3.5.0). Still no luck. I seem to always get back System.Byte for the message.data. I put in a logger.info (logger.info("Sending Code: " + message.opCode + "& Sending Data: " + message.data.toString)) to check in Nakama console itself and it says: “Sending Code: 5& Sending Data: [object ArrayBuffer]”. Should it say [object ArrayBuffer] or should it show the json string that was sent?

Latest is 3.14.0, could you upgrade to this version?

Ah sorry I thought you were referring to the Nakama asset in the Unity Asset Store.

Ok, so just I’ve upgraded the Nakama image in Docker Desktop from 3.13.1 to 3.14.0.

Just sent a match state and still notice the data I send with the OpCode from Unity shows up as “[object ArrayBuffer]” in the Docker Desktop.

This is my simple matchLoop function for the Nakama server in the index.js file.

var matchLoop = function (context, logger, nakama, dispatcher, tick, state, messages) {
    var gameState = state;
    for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) {
        var message = messages_1[_i];
        logger.info("Sending code: " + message.opCode + " Sending data: " +message.data);
        dispatcher.broadcastMessage(message.opCode, message.data, null, message.sender);
    }
    return gameState.endMatch ? null : { state: gameState };
};

And here is a sample of a code in Unity sending out a match state.

        public void Move(Tile targetTile)
        {
            Vector3 unitPos = transform.position;
            Vector3 targetPos = targetTile.transform.position;

            long opCode = (long) MultiplayerManager.Code.MoveUnit;
            string state = GetJsonPositionAndAbilityInd(unitPos, targetPos,0);
        }

        public string GetJsonPositionAndAbilityInd (Vector3 selectedUnit, Vector3 targetTile, int abilityIndex)
        {
            var values = new Dictionary<string, string>
            {
                {"SelectedUnitPos.x", selectedUnit.x.ToString() },
                {"SelectedUnitPos.y", selectedUnit.y.ToString() },
                {"SelectedUnitPos.z", selectedUnit.z.ToString() },
                {"TargetTilePos.x", targetTile.x.ToString() },
                {"TargetTilePos.y", targetTile.y.ToString() },
                {"TargetTilePos.z", targetTile.z.ToString() },
                {"AbilityIndex", abilityIndex.ToString()}
            };

            return values.ToJson();
        }

Any suggestions in what I may be doing wrong?

Thank you.

Are you getting a string back in the client using something like Encoding.UTF8.GetString(<state>) from the received state? Or are you receiving an empty System.Byte[]?