I’m designing a card game, new to Unity, but have been developing c# business apps for some time. I always come back to the same nagging architecture problem:
Where is an appropriate place to store common data, and by what mechanism does that instance get shared among the scripts?
For a concrete example, I have the following scripts are attached to the same game object with a sprite renderer. Now I want to add a 3rd script to show card details on mouse-over but am running into these issues.
All 3 scripts need common card-related data but I never know where to store that data. In a business app it would go in a model/poco/dto class. But in Uniity, should it go in another MonoBehavior attached to the same game object or a scriptable object? It could go in a simple model/poco class but then how does that instance get shared between all the scripts?
public class CardManager : MonoBehaviour
{
// it feels like these properties should go somewhere else
public CardValue Value { get; private set; }
public CardSuit Suit { get; private set; }
public bool IsFlippable { get; private set; }
public bool IsFaceUp { get; private set; }
public bool IsDraggable { get; set; } = false;
public bool IsInspectable { get; set; } = false;
public int SortingOrder
{
get => _spriteRenderer.sortingOrder;
set => _spriteRenderer.sortingOrder = value;
}
private SpriteRenderer _spriteRenderer;
private CardFlip _cardFlip;
private void Awake()
{
_spriteRenderer = GetComponent<SpriteRenderer>();
_cardFlip = GetComponent<CardFlip>();
}
public IEnumerator Flip()
{
if (IsFlippable)
yield return _cardFlip.Flip();
yield return null;
}
}
public class CardFlip : MonoBehaviour
{
public float TimeToFlip = 1f;
private Sprite _faceImage;
private Sprite _backImage;
private SpriteRenderer _spriteRenderer;
private bool _isFlipping;
public void Initialize(Sprite faceImage, Sprite backImage)
{
_faceImage = faceImage;
_backImage = backImage;
_spriteRenderer.sprite = /* need reference to IsFaceUp from the other script */ ? _faceImage : _backImage;
}
void Awake()
{
_spriteRenderer = GetComponent<SpriteRenderer>();
}
void Update()
{
if (_isFlipping)
{
// continue flip animation
}
}
public IEnumerator Flip()
{
if (_isFlipping)
yield break;
_isFlipping = true;
// begin flip animation
yield return null;
}
}