Can you use inheritance with methods marked as RPC?
I am getting error with this simple example because the child method is for some reason called in loop.
This is a stripped down example of the code:
public abstract class TestBase : NetworkBehaviour
{
[Rpc(SendTo.Server)]
public virtual void TestRpc()
{
Debug.Log("parent");
}
}
public class TestChild : TestBase
{
[Rpc(SendTo.Server)]
public override void TestRpc()
{
base.TestRpc();
Debug.Log("child");
}
}
public class SampleUser : MonoBehaviour
{
private void Update()
{
if (Input.GetKeyDown(KeyCode.T))
{
var o = FindObjectOfType<TestBase>();
o.TestRpc();
}
}
}
Output is only “child” over again until stack overflows.
Could someone provide a simple example of inheritance with RPC or state if it is even possible?
Edit 1
As @Pangamini suggested It is enough to put only one attribute in the base class and it indeed works in this simple scenario.
[Rpc(SendTo.Server)]
public virtual void TestRpc() {...}
...
public override void TestRpc() {... base.TestRpc(); ...}
But there is a problem with this approach. The child method is then executed on both client and server because it lack the RPC attribute. If you reverse the attribute then both methods are executed on server correctly:
public virtual void TestRpc() {...}
...
[Rpc(SendTo.Server)]
public override void TestRpc() {... base.TestRpc(); ...}
But this just delays the problem on the next child class of TestChild.
Edit 2 (Possible solution 1)
I found a workaround. You can create an UnityEvent
in the base class and invoke it in the base method. In the child class you can add a listener (the fake override method) to this event:
public abstract class TestBase : NetworkBehaviour
{
protected UnityEvent myCallbacks = new UnityEvent();
[Rpc(SendTo.Server)]
public void TestRpc()
{
Debug.Log("parent");
myCallbacks.Invoke();
}
}
public class TestChild : TestBase
{
private void Start()
{
myCallbacks.AddListener(FakeTestRpc);
}
private void FakeTestRpc() //Fake override method
{
Debug.Log("child");
}
}
This way the callback is invoked on the server.
Edit 3 (Possible solution 2)
You can keep your inheritance as at the top of this post but instead marking the methods with RPC attribute you just create another class RpcInvoker
which invoker you methods via its own RPC:
public abstract class TestBase : NetworkBehaviour
{
// Now without RPC attribute
public virtual void Test()
{
Debug.Log("parent");
}
}
public class TestChild : TestBase
{
public override void Test()
{
base.Test();
Debug.Log("child");
}
}
//The RPC invoker class
public class RpcInvoker : NetworkBehaviour
{
[Rpc(SendTo.Server)]
public void InvokeMyMethodsRpc()
{
Debug.Log("invoking on server");
GetComponent<TestBase>().Test(); // Or you can use UnityEvent to make it more generic
}
}
// And modify the input logic like this
public class SampleUser : MonoBehaviour
{
private void Update()
{
if (Input.GetKeyDown(KeyCode.T))
{
// we look for RpcInvoker instead of the base class
var o = FindObjectOfType<RpcInvoker>();
o.InvokeMyMethodsRpc();
}
}
}
Still if anyone know how to make a proper inheritance with RPC feel free to share.