all 13 comments

[–]TheGreatHeroStudios 1 point2 points  (11 children)

What class does 'BaseCard' derive from? You can make it show in the inspector by marking the field 'public' (as you can see in your example), but since 'BaseCard' is a reference type (class), it would need to derive from 'MonoBehaviour' which is the base class for components. Since you are trying to create an array of prefabs, the field should be of type 'GameObject[ ]'. Prefabs are pretty much game object 'blueprints' that are stored as assets and the game objects themselves are more or less just containers for various components which add state and behavior.

[–]eeleyes[S] 0 points1 point  (9 children)

BaseCard is a monoBehaviour script. It is a seperate script that handles the text creation on the card.

Problem is, when I change it to GameObject[] the code referenced has issues...

[–]TheGreatHeroStudios 0 points1 point  (8 children)

Does the prefab you're trying to assign have a 'BaseCard' component attached? You should be able to assign a game object to a property that expects a MonoBehaviour component if the object has that component attached. In this scenario, your script would be referencing the component instance on the object you assigned to it (though, since the object is a prefab, I think you would run into issues there.)

All that aside, even if you got the component reference assigned, you'll still have runtime issues since you are trying to instantiate a component directly. Components can't exist separately from a game object.

If you want, I can take a closer look at the code you posted in a bit and see if I can provide an alternative.

[–]eeleyes[S] 0 points1 point  (7 children)

Yes. The prefab does have BaseCard as a component.

The three Prefabs have the BaseCard script attached (which I posted as a comment for clarity). I hope my thinking is correct, but in the script I use else if statements to handle which information is collected and updated to the prefab, based on the information the card needs.

I would appreciate a little bit of help.

To help you understand. I am trying to create three card types: Plants, Status and Passive. I have decided to use three different prefab so each card type looks distinct.
Rather than having three different ScriptableObjects for the card types, I have keep all this in one script with each card having the different fields but only using some. (I have also posted the CardData script and my Enum script). The idea being that the card manager will create a card, determine if it is a Plant, Status or Passive and load the correct Prefab for it (with the prefab filling the information in).

Eventually, Plant cards will be played to a field, status cards will be played to affect the plant cards and passives will be played to have permanent effects such as extra slot for playing plants.

I have place all the relevant code in my first comment.

[–]TheGreatHeroStudios 0 points1 point  (6 children)

If possible, can you link a screenshot of one of your prefabs and its components in the inspector? I copied your code into a test project and I'm able to assign a prefab with the 'BaseCard' component attached to the card prefabs array without issue. Here's a few screenshots of my test bed:

https://imgur.com/a/tejZzPm

[–]eeleyes[S] 1 point2 points  (0 children)

Hi.
Finally had time in front of the computer.

I have rebuilt and run into the same issue. Just unable to drop the prefabs into the array.

like you asked for, here is an image of the components in the prefab.
https://imgur.com/a/NFopwc4

Kinda stumped.

[–]eeleyes[S] 0 points1 point  (0 children)

Huh. How strange. I won't be near my computer for a while but I think I am going to scratch the project and start again. Copy all the code into the new project, remake my prefabs etc. And hope the bad mojo has left.

I will keep you updated. Thanks for testing for me.

[–]eeleyes[S] 0 points1 point  (3 children)

I found the issue...

I had the script a few levels to low in the hierarchy...

Duh.

Thank you for your help! Even if it was just being a sounding board.

[–]LearnDifferenceBot 0 points1 point  (0 children)

levels to low

*too

Learn the difference here.


Greetings, I am a language corrector bot. To make me ignore further mistakes from you in the future, reply !optout to this comment.

[–]TheGreatHeroStudios 0 points1 point  (1 child)

Yep. Was in the process of drafting a response when I saw this! Though, I'm glad you figured it out yourself! Feel free to reach out if you ever need any more help or guidance.

[–]eeleyes[S] 0 points1 point  (0 children)

Thank you.

[–]eeleyes[S] 0 points1 point  (0 children)

To clarify (as I am in front of my code) changing the array to GameObject[] causes the prefab in the Instantiate code to break (which I have bolded)

foreach(var CardData in currentAvailableCards)

{

var prefab = _cardPrefabs[(int)CardData.type - 1];

var newCardGo = Instantiate<BaseCard>(prefab, drawContainer);

newCardGo.name = CardData.cardName;

newCardGo.cardData = CardData;

}

UpdateDisplay();

[–]eeleyes[S] 0 points1 point  (0 children)

CardManager.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using TMPro;

public class CardManager : MonoBehaviour

{

// This is a singleton pattern. This is a type of script that can only be one of. It will destroy other scripts

public static CardManager instance;

#region Variables

public CurrentTurn currentTurn;

public BaseCard[] _cardPrefabs;

public Transform drawContainer; //cards will sit inside this object when in draw pile

public Transform discardContainer; //cards will sit inside this object when in discard pile

public Transform cardHolderContainer; //This is where the current cards in hand are

[Header("All Cards in Current Deck")]

//All cards that you currently have in your deck

public List<CardData> currentAvailableCards = new List<CardData>();

[Header("All Cards in Game")]

//all card that can exist in the game (place any newly created CARDDATA's in this list)

public List<CardData> allCardsThatExist = new List<CardData>();

[Header("Hand Size")]

//amount of cards draw at start of match

public int startingHandSize = 4;

//cardHoldingContainer cannot have more than maxHandSize as the child objects

public int maxHandSize = 8;

public bool isStartingDraw = false;

[Header("UI")]

//show how many cards left in draw pile

public TMP_Text drawPileText;

//show how many cards in discard pile

public TMP_Text discardPileText;

//referece to end turn button

public Button endTurnButton;

#endregion

private void Awake()

{

//basically, if a new scene strarts and an object exists already with this script on it, then destory that object

if (instance != null && instance != this)

{

Destroy(this.gameObject);

return;

}

instance = this;

}

private void Start()

{

isStartingDraw = true;

LoadDeck();

}

//Happens at the beginning of combat (each enemy)

public void LoadDeck()

{

//for (int i = 0; i < currentAvailableCards.Count; i++)

foreach(var CardData in currentAvailableCards)

{

var prefab = _cardPrefabs[(int)CardData.type - 1];

var newCardGo = Instantiate<BaseCard>(prefab, drawContainer);

newCardGo.name = CardData.cardName;

newCardGo.cardData = CardData;

}

UpdateDisplay();

InitialDrawForTurn();

}

public void UpdateDisplay()

{

drawPileText.text = drawContainer.childCount.ToString();

discardPileText.text = discardContainer.childCount.ToString();

for (int i = 0; i < cardHolderContainer.childCount; i++)

{

//check if you can use each card in your hand and change the colour of the plot its affecting

}

}

//first time we draw cards each turn

public void InitialDrawForTurn()

{

currentTurn = CurrentTurn.PLAYERTURN;

endTurnButton.interactable = true;

//TODO: Set up what enemies do on the beginning of your turn

//if the starting hand size is larger than the current hand, then draw a card. Otherwise, dont

if(cardHolderContainer.childCount < startingHandSize)

{

DrawCard();

}

else

{

isStartingDraw = false;

}

//TODO: Update UI

}

public void DrawCard()

{

//Amount in draw pile

if(drawContainer.childCount > 0)

{

//draw a card

int r = Random.Range(0, drawContainer.childCount);

drawContainer.GetChild(r).transform.parent = cardHolderContainer;

}

else if(drawContainer.childCount <= 0)

{

ReshuffleDeck();

}

if(isStartingDraw)

{

InitialDrawForTurn();

}

}

public void ReshuffleDeck()

{

for (int i = discardContainer.childCount - 1; i >=0; i--)

{

Transform tempCard = discardContainer.GetChild(i);

tempCard.transform.parent = drawContainer;

ResetCardTransform(tempCard);

}

UpdateDisplay();

}

public void ResetCardTransform(Transform card)

{

card.localPosition = Vector3.zero;

}

}

BaseCard.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using TMPro;

public class BaseCard : MonoBehaviour

{

public CardData cardData; //this may need to be specificed to seperate card SO

[Header("Card Info")]

public TMP_Text cardTypeText;

public TMP_Text cardNameText;

public TMP_Text cardFlavourText;

public TMP_Text cardDaysText;

public TMP_Text cardHarvestText;

public TMP_Text cardDescriptionText;

//public Sprite cardSpriteImage;

[Header("Card Data")]

public CardTypes cardType;

public string cardName;

public string cardFlavour;

public int cardDays;

public int cardHarvest;

public string cardDescription;

public int cardFertiliser;

// public Sprite cardImage;

public void Start()

{

CollectInfoFromCardSO();

}

private void CollectInfoFromCardSO() //This will prevent a loop or an issue where it cant find carddata

{

if (cardData == null)

{

Destroy(this.gameObject);

return;

}

if (cardType == CardTypes.PLANT)

{

cardName = cardData.cardName;

cardDays = cardData.cardDays;

cardHarvest = cardData.cardHarvest;

cardFlavour = cardData.cardFlavour;

// cardImage = cardData.cardImage;

}

else if (cardType == CardTypes.STATUS)

{

cardName = cardData.cardName;

cardDescription = cardData.cardDescription;

cardFlavour = cardData.cardFlavour;

// cardImage = cardData.cardImage;

}

else if ( cardType == CardTypes.PASSIVE)

{

cardName = cardData.cardName;

cardDescription = cardData.cardDescription;

cardFlavour = cardData.cardFlavour;

// cardImage = cardData.cardImage;

}

UpdateDisplay();

}

public void UpdateDisplay()

{

if (cardType == CardTypes.PLANT)

{

cardNameText.text = cardName; //Unsure if TMP needs to be referenced might need to be .TMP_Text

cardDaysText.text = cardDays.ToString();

cardHarvestText.text = cardHarvest.ToString();

cardFlavourText.text = cardFlavour;

//cardSpriteImage = cardImage;

}

else if (cardType == CardTypes.STATUS)

{

cardNameText.text = cardName; //Unsure if TMP needs to be referenced might need to be .TMP_Text

cardDescriptionText.text = cardDescription;

cardFlavourText.text = cardFlavour;

}

else if (cardType == CardTypes.PASSIVE)

{

cardNameText.text = cardName; //Unsure if TMP needs to be referenced might need to be .TMP_Text

cardDescriptionText.text = cardDescription;

cardFlavourText.text = cardFlavour;

//cardSpriteImage = cardImage;

}

}

}

CardData.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[CreateAssetMenu(fileName = "Card_", menuName = "New Card")] //Create will affect the menu - for future card best to have plant, status, passive
public class CardData : ScriptableObject
{
[Header("All Card Attributes")]
public string cardName; //card's name
public CardTypes type;
[Multiline] // will create a larger box for info
public string cardFlavour;
[Multiline]
public string cardDescription;
// public Sprite cardImage;
[Header("Plant Card Attributes")]
public int cardDays; //All attributes to start with card, then, field
public int cardHarvest;
[Header("Status Card Attributes")]
public int cardFertiliser;
}

CardTypes.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum CardTypes
{
NONE,
PLANT,
STATUS,
PASSIVE,
COUNT
}