- Home /
SyncEvent bug: "Cannot cast from source type to destination type"
Pretty sure this is a bug in Unity, hoping someone has a workaround.
I'm trying to use the new SyncEvents described here: http://docs.unity3d.com/ScriptReference/Networking.SyncEventAttribute.html
Symptom: anything I create with a SyncEvent throws an error like this when I try to use it at runtime:
InvalidCastException: Cannot cast from source type to destination type.
DamageClass.InvokeSyncEventTakeDamageDelegate (UnityEngine.Networking.NetworkBehaviour obj, UnityEngine.Networking.NetworkReader reader)
UnityEngine.Networking.NetworkBehaviour.InvokeSyncEventDelegate (Int32 cmdHash, UnityEngine.Networking.NetworkReader reader) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkBehaviour.cs:349)
This error is showing up in my live project, with exact copies of the sample code shown on the doc page.
So I created a new test project, copied the bare minimum test scenes, classes, and prefabs that I used in the live project. I had to rewire a couple of relationships in the editor. And.... the sample code worked. The event fires with no error.
Trying to figure out why: I copied the meta files for those assets from my live project to the test project. At that point, the sample code failed with the above error.
Looking at the diff... the only difference in those meta files is a new guid.
I can confirm that in the test project, switching out the newly-generated meta files with the live project meta files causes the syncevent to work/notwork appropriately.
Back to the live project... I copy the meta files from the test project to the live project. The sample code now works!
Poking and prodding, one line at a time, in the live project...it continues to work up until the point I add my custom BerzerkerStrategy to the prefab I'm testing with. I remove it. And now the sample code class that was working before (DamageClass) is throwing the exact same error.
It feels like the networking code is not being properly regenerated by the HLAPI? I have no idea where to look next.
I'm not sure what I can post apart from the entire project. The bug is not tied to specific code.
Answer by Sech90 · Nov 27, 2015 at 11:12 AM
I have the same problem, using Unity 5.2.3f1. Here's a sample PlayerHealth code:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class PlayerHealth : NetworkBehaviour {
public delegate void DieCallback();
[SyncEvent]
public event DieCallback EventPlayerDie;
[SerializeField] int InitialHealth = 100;
[SyncVar(hook="OnHealthChange")] int _currentHealth;
void Start(){
EventPlayerDie += () => {
Debug.Log("Player died!");
};
}
override public void OnStartServer (){
_currentHealth = InitialHealth;
}
[Server]
public void TakeDamage(int amount){
_currentHealth = Mathf.Max(_currentHealth-amount, 0);
if(_currentHealth == 0)
EventPlayerDie();
}
[Client]
private void OnHealthChange(int newHealth){
_currentHealth = newHealth;
}
}
When the player's _currentHealth reaches 0, the Server invokes EventPlayerDie() which causes an exception in all the clients:
InvalidCastException: Cannot cast from source type to destination type.
PlayerHealth.InvokeSyncEventDieCallback (UnityEngine.Networking.NetworkBehaviour obj, UnityEngine.Networking.NetworkReader reader)
UnityEngine.Networking.NetworkBehaviour.InvokeSyncEventDelegate (Int32 cmdHash, UnityEngine.Networking.NetworkReader reader) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkBehaviour.cs:349)
UnityEngine.Networking.NetworkBehaviour.InvokeSyncEvent (Int32 cmdHash, UnityEngine.Networking.NetworkReader reader) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkBehaviour.cs:144)
UnityEngine.Networking.NetworkIdentity.HandleSyncEvent (Int32 cmdHash, UnityEngine.Networking.NetworkReader reader) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:437)
UnityEngine.Networking.ClientScene.OnSyncEventMessage (UnityEngine.Networking.NetworkMessage netMsg) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/ClientScene.cs:652)
UnityEngine.Networking.NetworkConnection.HandleReader (UnityEngine.Networking.NetworkReader reader, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:421)
UnityEngine.Networking.NetworkConnection.HandleBytes (System.Byte[] buffer, Int32 receivedSize, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:377)
UnityEngine.Networking.NetworkConnection.TransportRecieve (System.Byte[] bytes, Int32 numBytes, Int32 channelId) (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkConnection.cs:527)
UnityEngine.Networking.NetworkClient.Update () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkClient.cs:560)
UnityEngine.Networking.NetworkClient.UpdateClients () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkClient.cs:774)
UnityEngine.Networking.NetworkIdentity.UNetStaticUpdate () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkIdentity.cs:916)
I got around it by using a ClientRpc call insted of a SyncEvent:
[ClientRpc]
public void RpcPlayerDie(){
Debug.Log("Player died!");
}
[Server]
public void TakeDamage(int amount){
_currentHealth = Mathf.Max(_currentHealth-amount, 0);
if(_currentHealth == 0)
RpcPlayerDie();
}
it's not the same thing but it worked. Hope it helps. I'd really like to know if there's a bug in Unity with SyncEvents or I'm just missing something.