I have 2 types of NPC's (Guest and Worker) which will have different logic and behaviors. For example:
at GuestController I want to manage places the Guest joined.
at WorkerController I want to manage current job the Worker is doing.
So I created these base classes to be extended.
NPC.NPCController{} // navmesh, animator, statemanager...
NPC.INPCState{} // State's methods like Enter, Execute, Exit
NPC.StateManager{} // switch current State
Then I create NPCGuest classes:
NPCGuest.NPCGuestController : NPCController{}
NPCGuest.StateFreeWalk : NPC.INPCState{}
And then created NPCWorker classes:
NPCWorker.NPCWorkerController : NPCController{}
NPCWorker.StateFreeWalk : NPC.INPCState{}
The problem I'm having is to create and use each Controller's specific logic.
For example, specific method in GuestController:
using Myproject.NPC;
namespace Myproject.NPCGuest
{
public class NPCGuestController : NPC.NPCController
{
public void guestSpecificMethod()
{
Debug.Log("specific method for Guest");
}
}
}
And then try to use this method from Guest State class:
using Myproject.NPC;
namespace Myproject.NPCGuest
{
public class StateFreeWalk : NPC.INPCState
{
public void Enter(NPCController npc)
{
npc.guestSpecificMethod();
}
}
}
This causes error because Enter method expects an NPController
instead NPCGuestController
.
If I change it to expects NPCGuestController
, it causes error at line public class StateFreeWalk : NPC.INPCState
, because the INPCState
also expects for the base class NPCController
.
What am I doing wrong?
Is it possible to reuse base classes? Or should I create separated INPCState and StateManager class for Guest and Worker?
I have 2 types of NPC's (Guest and Worker) which will have different logic and behaviors. For example:
at GuestController I want to manage places the Guest joined.
at WorkerController I want to manage current job the Worker is doing.
So I created these base classes to be extended.
NPC.NPCController{} // navmesh, animator, statemanager...
NPC.INPCState{} // State's methods like Enter, Execute, Exit
NPC.StateManager{} // switch current State
Then I create NPCGuest classes:
NPCGuest.NPCGuestController : NPCController{}
NPCGuest.StateFreeWalk : NPC.INPCState{}
And then created NPCWorker classes:
NPCWorker.NPCWorkerController : NPCController{}
NPCWorker.StateFreeWalk : NPC.INPCState{}
The problem I'm having is to create and use each Controller's specific logic.
For example, specific method in GuestController:
using Myproject.NPC;
namespace Myproject.NPCGuest
{
public class NPCGuestController : NPC.NPCController
{
public void guestSpecificMethod()
{
Debug.Log("specific method for Guest");
}
}
}
And then try to use this method from Guest State class:
using Myproject.NPC;
namespace Myproject.NPCGuest
{
public class StateFreeWalk : NPC.INPCState
{
public void Enter(NPCController npc)
{
npc.guestSpecificMethod();
}
}
}
This causes error because Enter method expects an NPController
instead NPCGuestController
.
If I change it to expects NPCGuestController
, it causes error at line public class StateFreeWalk : NPC.INPCState
, because the INPCState
also expects for the base class NPCController
.
What am I doing wrong?
Is it possible to reuse base classes? Or should I create separated INPCState and StateManager class for Guest and Worker?
One of the options I see here is to use generics, it might be a good case for that but it depends on your vision of future functionality and general architecture.
You can make your interface NPC.INPCState
to be generic, something like this:
public interface INPCState<T> where T : NPCController
this way you can clarify the exact type you need in particular states:
public class StateFreeWalk : INPCState<NPCGuestController>
{
public void Enter(NPCGuestController npc)
{
npc.guestSpecificMethod();
}
}
Do not inject the NPCGuestController
through a parameter of the Enter()
method, but through e.g. constructor of StateFreeWalk
.
This decouples the interface NPC.INPCState
from the specific needs (dependencies) of the implementation StateFreeWalk
.
using Myproject.NPC;
namespace Myproject.NPCGuest
{
private readonly NPCGuestController _controller;
public class StateFreeWalk : NPC.INPCState
{
public StateFreeWalk(NPCGuestController npc)
{
_controller = npc;
}
public void Enter()
{
_controller.guestSpecificMethod();
}
}
}