I'm pretty new to C# and Unity and I've trying to figure out how to handle subclasses through the base class.
I am making a card game. I've made a baseclass PlayerCard, which has subclasses such as Minion : PlayerCard.
My current structure is that PlayerCard class is instantiated like this from the deck at the start
public class PlayerDeck : MonoBehaviour{
[SerializeField] PlayerCard[] playerCardArray;
private int xPos = 2;
public void DrawCards()
{
var cardIndex = Random.Range(0, playerCardArray.Length);
AddCardToPlayer(playerCardArray[cardIndex]);
}
private void AddCardToPlayer(PlayerCard myCard)
{
Vector3 cardPos = new Vector3(transform.position.x xPos, transform.position.y, transform.position.z);
PlayerCard newCard = Instantiate(myCard, cardPos, transform.rotation) as PlayerCard;
xPos = xPos 2;
}
I want my baseclass (PlayerCard) handle all mundane things such as dragging and moving the card as they will be the same for all the cards.
private void OnMouseDown()
{
ToggleDrag();
}
void Update()
{
if (DraggingON) { Drag(); }
}
private void ToggleDrag()
{
Debug.Log(playerCard);
mouseOffset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, mouseScreenPoint.z));
if (DraggingON)
{
DraggingON = false;
SnapCardToPosition();
}
else
{
DraggingON = true;
SnapPositionX = transform.position.x; //Return to same x position if user has not hovered other available slot
SnapPositionY = transform.position.y; //Return to same y position if user has not hovered other available slot
//Variables above will be reset to default position x/y when user has hovered a slot but then moved object away from the slot, so reset to default
defaultPositionX = transform.position.x;
defaultPositionY = transform.position.y;
}
}
private void Drag()
{
Vector3 currentMouseScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, mouseScreenPoint.z);
Vector3 currentMousePosition = Camera.main.ScreenToWorldPoint(currentMouseScreenPoint) mouseOffset;
transform.position = currentMousePosition;
}
My problem lies, when SnapCardToPosition is called, which is when I want the subclass (whatever it is) to take over and handle interactions with position they were dragged into.
private void SnapCardToPosition()
{
Vector2 NewCardPosition = new Vector2(SnapPositionX, SnapPositionY);
transform.position = NewCardPosition;
//Dynamically call the subclass here?
}
So the subclass would look something like this
public class Minion : PlayerCard{
[SerializeField] int Damage = 1;
public void HandleCardPlacement()
{
//Do something
}
I haven't figured out how this could be achieved using my structure or is it fundamentally wrong?
CodePudding user response:
- Make your method not
private
(= only this class can see this) but ratherprotected
(= this and any derived class can see this) - And make your method either
virtual
(if there is a common base behavior) orabstract
(if every card has to implement it from scratch) andoverride
it in the subclass
In your base class e.g.
protected virtual void SnapCardToPosition()
{
Vector2 NewCardPosition = new Vector2(SnapPositionX, SnapPositionY);
transform.position = NewCardPosition;
}
and then in the subclass
protected override void SnapCardToPosition()
{
// make sure that the base implementation is executed first
base.SnapCardToPosition();
// do additional stuff
}
so here each subclass can decide
- whether to
override
the method or simply keep he default one of the base class - if it overrides it can decide if and when to call the default behavior via the
base.SnapCardToPosition();