Hi everyone,
I’ve been working on a Unity implementation of a boardgame for the past few weeks and have a rough prototype ready but am now at the point where I want to make it shine. This is a card-driven game so the player will drop a card down on an active collider and then a variety of things will happen in various locations on two boards/play-mats. My prototype thus far has been able to correctly display what should be on the board at the end of a players turn, but since there can potentially be several things happening as a card is played, I am looking to break things down a bit, so the player can follow each step of gameplay. As a simple example of one of the things I want to do, rather than enabling and displaying 3 pawns at home-plate (this is a baseball game) all at once, I would want the pawns to activate and become visible one at a time with a short delay between them.
I have been fooling around with coroutines to accomplish this and am slowly coming to grips with the way they behave.
My main function for the playing of a card, looks something like…
public void PlayCard(int cardId, GameControlScript.Players team) {
print("Playing card: " + cardId + " for team: " + team.ToString());
// Move card to discard pile
DiscardsController discardsController = activeDiscards.GetComponent<DiscardsController>();
discardsController.AddCard(cardId);
if (this.gameState == GameStates.NormalPlay) {
// Play the immediate action
DoImmediateAction(cardId, team);
// Get The Characteristics of the card
CardDictionaryController cardDictionaryController = cardDictionary.GetComponent<CardDictionaryController>();
// Resolve the hits on the opponents board
ResolveHits(team);
// Place threatened hits on team board
print("Call PlaceThreatenedHits()");
**StartCoroutine(PlaceThreatenedHits(cardId, team);**
print("After PlaceThreatenedHits()");
}
DO OTHER STUFF
}
My first attempt at turning the function PlaceThreatenedHits() into a Coroutine failed pretty miserably because the code in DO OTHER STUFF was being executed after PlaceThreatenedHits() performed its first of 4 yields and altered some members/properties used by PlaceThreatenedHits() when it continued its execution. I thought about passing the entire game context into PlaceThreatenedHits() as a parameter, but that is a fairly heavy solution.
In the end, to maintain the game-state as it was when PlaceThreatenedHits() was initially called, I ended up moving all of the code denoted by DO OTHER STUFF into a new function,
**public void PlayCardPart2(int cardId, GameControlScript.Players team)** {
// Reset the controller sets
SetGameObjects(team);
if (this.gameState == GameStates.ExtraInningResolve) {
ResolveExtraInning();
}
// Toggle the active player
activeTeam = FlipTeam(activeTeam);
if (activeTeam == Players.Player1) {
player2ActiveIndicator.GetComponent<ActivePlayerIndicatorController>().active = false;
player1ActiveIndicator.GetComponent<ActivePlayerIndicatorController>().active = true;
}
else {
player2ActiveIndicator.GetComponent<ActivePlayerIndicatorController>().active = true;
player1ActiveIndicator.GetComponent<ActivePlayerIndicatorController>().active = false;
}
// Check for end of game - the hand counts must have been updated before calling PlayCard
CheckEndOfGame();
}
…and I modified the original coroutine call to pass the new function in
// Place threatened hits on team board
print("Call PlaceThreatenedHits()");
**StartCoroutine(PlaceThreatenedHits(cardId, team, PlayCardPart2));**
print("After PlaceThreatenedHits()");
This approach DOES work, but I’m wondering if it is the best way. I’m concerned at the amount of chopping up of functions I will have to do as I continue forward using this approach. It’s a bit of a shame that I couldn’t keep all that logic in a single PlayCard() function for readability and maintenance purposes. Things will start getting more difficult to follow the more I start chaining things this way and I fear it may even become unwieldly.
Fairly soon, I will want to write an in-game tutorial that will consist of nothing more than a scripted sequence of short animations happening on the screen, most of which will probably be implemented via coroutines. But it looks like I won’t be able to store the master sequence of events for a tutorial section in a single function or other chunk of code.
Any advice or 3rd party add-ons which might help out would be greatly appreciated.