- Home /
Problem with interfaces and Unity Networking Attributes
Alright, so there is either a great flaw in my understanding of interface implementation regarding attributes in general (which is most likely), or there is a bug within UNet, and I am seeking some clarification on that.
What I want to do is to be able to have an interface called IDamageable describe general functionality between objects that can be damaged. This would contain not only players themselves, but some props in the scene as well.
I went on to achieve this with polymorphism / deriving classes after I encountered this problem of mine, but it's probably pretty clear why an interface would be a better option (ie. player is not a table, table is not a car, but all of them can be damaged).
So, here are some simplified bits of the attack mechanics for demonstration:
//Attack something, call this from mouse-click, animation event etc.
[Client]
void Attack()
{
if (isLocalPlayer)
{
Ray ray = new Ray(cam.position, cam.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, attackRange, hitBoxMask))
{
CmdCheckHit(hit.transform.root.name, ray, damage);
}
}
}
Then there is the command:
//Process this on the server
[Command]
void CmdCheckHit(string id, Ray r, int damage)
{
//This is inefficient, but just to demonstrate
IDamageable entity = GameObject.Find(id).GetComponent<IDamageable>();
entity.RpcTakeDamage(r, damage);
}
Everything is fine at this point, command gets sent and processed in the server, we find the component that implements IDamageable and call the implemented function. Now that brings up the problem:
//This should run not on the server, but on all the clients
[ClientRpc]
public void RpcTakeDamage(Ray r, int damage)
{
Debug.Log(transform.name + " was hit for " + damage + " damage, from position " + r.origin + " and direction " + r.direction);
}
This is a function implemented from the interface IDamageable. Regardless of whether or not I have "using UnityEngine.Networking" and the attribute [ClientRpc] in the interface itself (which both, in my understanding, would not be required there anyway), this will run only on the server (or the host client) and not on the remote clients. That means it does not recognize the attribute.
This may happen because the interface is not a NetworkBehaviour (which it of course cannot be), although I don't really know why that would mean anything because it is an interface, not a class.
Just to be clear, the interface would be quite simply just like this:
public interface IDamageable {
void RpcTakeDamage(Ray r, int damage);
}
So the question is: is this behaviour intended? If it is, I'd like to understand the reasoning behind it. Or is something amiss? Also, hearing possible workarounds other than my current one (I have a NetworkEntity class that everything damageable derives from, which is not necessarily ideal) would be very welcome .
EDIT: I'll add that while a simple health reduction etc. could be done via a SyncVar change (at which point all this fuss would be insignificant), the problem at hand involves being able to process the reaction of getting hit on the clients themselves for advanced, unique outcomes (such as physics calculations and such).
Your answer
