The Bug:
I have a character GameObject with 5 NetworkBehavior Feat (ability/action) scripts.
When I call [Command] CmdUseFeat() for feat #4 on the client, it calls CmdUseFeat() for feat #3 on the server (bugged).
Additional Details:
The bug does not occur on the host, only local clients (I have not tested with remote client).
The 5 feats are attached to a player prefab.
Calling CmdUseFeat #1 on client calls Calling CmdUseFeat #1 on server.
Calling CmdUseFeat #2 on client calls Calling CmdUseFeat #2 on server.
Calling CmdUseFeat #3 on client calls Calling CmdUseFeat #3 on server.
Calling CmdUseFeat #4 on client calls Calling CmdUseFeat #3 on server.
Calling CmdUseFeat #5 on client calls Calling CmdUseFeat #3 on server.
Re-ordering the feats on the prefab hierarchy swaps the problem. For example if I move feat #5 to the #1 position then it works properly, but the new #5 feat now is bugged out.
If I was to guess I would think the bug has something to do with the use inheritance of an Abstract Feat class with the [Command] CmdUseFeat() method… or possibly due to overriding of the [Command] method. But that’s just a guess. I’ll keep working to narrow down the specific setup to replicate. Is anybody else having this bug? Any tricks to fix?
The full code is too long to paste, so I posted some example pseudo code of the bug. DebugDisplayFeatName() will display the feats name… and it shows the Client/Host [Command] index mismatch (see comments below).
protected override void OnKeyDown()
{
DebugDisplayFeatName(); //This will display "FeatFireball" on the client (Feat index #4)
CmdUseFeat();
}
[Command]
protected override void CmdUseFeat ()
{
DebugDisplayFeatName(); //This will display "FeatTeleport" on the server (Feat index #3)
}
I removed the virtual [Command] functions and the bug persists. I did more testing and it seems that when [Commands] are used that are non-unique (i.e. when there is several instances of the same NetworkBehavior script attached to a GameObject, or a parent class with multiple child classes attached to the same GameObject) then incorrectly calls the [Command] on the 1st instance in the hierarchy when called from the localClient regardless of which instance calls the [Command].
To replicate bug place 3 instances of this TestCommand script onto a player object. They will be given unique ID’s of 1, 2, and 3. Pressing keys 1, 2, and 3 calls the [Command] on each respective instance. Results are as follows.
On the host
Pressing key #1 calls [Command] for instance #1
Pressing key #2 calls [Command] for instance #2
Pressing key #3 calls [Command] for instance #3
On the localClient
Pressing key #1 calls [Command] for instance #1
Pressing key #2 calls [Command] for instance #1 (bugged)
Pressing key #3 calls [Command] for instance #1 (bugged)
The debug output shows the bug where calling a command on index 3 calls the [Command] on index 1
OnClient: “Key pressed for uniqueID=3”
OnHost: “CmdTest called for uniqueID=1”
using UnityEngine;
using System.Collections;
using UnityEngine.Networking; //needed for NetworkBehavior
public class TestCommand : NetworkBehaviour
{
private static int IDcounter;
[SyncVar]
public int uniqueID;
private void Awake()
{
IDcounter = 0;
}
private void Start()
{
if(isServer)
{
uniqueID = ++IDcounter;
Debug.Log("uniqueID=" + uniqueID);
}
}
private void Update()
{
if(isLocalPlayer)
{
if(Input.GetKeyDown(keyCode))
{
Debug.Log("Key pressed for uniqueID=" + uniqueID);
CmdTest();
}
}
}
[Command]
private void CmdTest()
{
Debug.Log("CmdTest called for uniqueID=" + uniqueID);
}
private KeyCode keyCode
{
get
{
if(uniqueID == 1)
{
return KeyCode.Alpha1;
}
else if (uniqueID == 2)
{
return KeyCode.Alpha2;
}
else if (uniqueID == 3)
{
return KeyCode.Alpha3;
}
else
{
Debug.Log("ERROR");
return KeyCode.None;
}
}
}
}
Since I can’t use non-unique names (the functionality is built into the parent class… so all scripts will have the same names) I found another work-around.
In case anybody has the same problem the work-around I did was to keep a list<> of all of the Feat child classes added to the GameObject. Instead of using [Command] CmdUseFeat() I call [Command] CmdUseFeat(byte index) with the index of the feat calling the action, then look up this feat on the list when the command is called.
I’m still struggling with this bug as it doesn’t allow UNET to work well with inheritance… which in OOP is just about every object! Seems like a major issue I’m surprised nobody else is having problems. Is there an ETA on the fix?
Just discovered this problem in my project too. I just spent the last 2 days reworking my characters’ skilling system only to discover this problem. This is a very urgent issue to solve, and the craziest thing is that it isn’t even prioritized on the issue tracker.