This page does a slightly deeper dive into how DeckStacker works. I'm trying to be illuminating, here, but not dive toooo deep into everything. You should be able to find more detail into any of these subjects in the API documentation pages.
Card movement is managed, using the DSCardMover static class. In that script, there are several lists that are being monitored by DSCardMover's update loops, RunUpdate() and RunLate().
These lists are:
The types of animation that these lists manage can be categorized as:
Let's briefly summarize how each of these styles of animation work, and why you would want to use them.
This is one of the most common ways a card will move.
When a group of cards has been marked for a "deal" (aka moving from one stack to another), the cards are added to the cardsWaitingToBeDealt list, in DSCardMover.
While in the cardsWaitingToBeDealt list, each card is evaluated by the following criteria:
Once the card is out of the cardsWaitingToBeDealt list, and in the cardsInMotion list, the card will be officially added to its destination stack, and the Restack operation will take hold of it, moving it to its proper place in the new stack.
When a card has been added to the cardsInMotion list, the DSCardMover script will lerp the card's position between its starting location (DSCardMovementHelper.startPos) and the new target position (DSCardMovementHelper.endPos).
The most common way this will happen is during a Restack operation for a stack. Restacks are when the stack arranges all of its cards according to its stack type.
DeckStacker also provides DSActions that utilize this behavior, such as the DSMoveCardInDirAction and the DSMoveCardToPositionAction.
If you want more continuous control of a card's position, I would recommend having the card belong to an Undefined stack, or else Restack operations are going to constantly try and move your card(s) to where the stack thinks the card(s) should be.
You can use the DSCardMovementHelper.MoveCard() method to utilize this system, outside of the core DSActions provided in DeckStacker.
Note: This movement is applied to the base Transform of the card (the Transform attached to the same object that has the DSCard component). See Card Prefab Setup for more info.
A card "offset" is when the card maintains its position, but the card visuals are moved or scaled.
When making card games, I often find myself wanting to make small position and/or scale adjustments to a card to add visual emphasis to the card, like when a card is selected by the player. You can use the DSCardMovementHelper.OffsetCard() method to offset a card, which will then add the card to the DSCardMover.cardsOffset list. The DSCardMover script will then iterate through that list, every Update, and move / scale any cards that haven't finished their offset animations.
Note: This movement is applied to the DSCardMovementHelper.offsetParent object in the card prefab. See Card Prefab Setup for more info.
Similar to the previous sections, describing moving a card object: Cards are rotated by adding them to the DSCardMover.cardsRotating list, and then the DSCardMover script will iterate through the list and lerp the rotations of the DSCard objects that haven't finished rotating to thier endRotation values.
This bit is primarily used for angling cards for Fan stacks, and/or correcting the rotation of cards being passed between stacks of different rotations.
This can also be used to "tap" cards in a Magic The Gathering style action.
If you want to lock the rotation of a card, and prevent the rest of these systems from rotating it (like when a restack happens), you can utlized the DSCardMoveHelper.lockRotation flag, disabling future card rotations until that flag has been reset.
You can use the DSCardMovementHelper.RotateCard() method to utilize this system, or use the DSRotateCardAction.
Note: This rotation is applied to the base Transform of the card object (DSCard object). See Card Prefab Setup for more info.
Similar to the previous sections, describing moving a card object: Cards are scaled by adding them to the DSCardMover.cardsScaling list, and then the DSCardMover script will iterate through the list and lerp the scales of the DSCard objects that haven't finished scaling to thier endScale values.
You can use the DSCardMovementHelper.ScaleCard() method to utilize this system, or use the DSScaleCardAction.
Note: This scale animation is applied to the base Transform of the card object (DSCard object). See Card Prefab Setup for more info.
This style of movement works slightly different than the other types of movement.
A "grab" is intended to be a player-controlled, dynamic input that will move the card visuals.
Similar to a card "offset", a card grab does not move the base position of a card, but moves a DSCardGrabber.grabParent, instead.
It still uses a list in DSCardMover (cardsGrabbed) where cards that are marked as "grabbed" are then added to this list, and DSCardMover iterates through the list to update positions.
The ideal use cases for card grabs are when a player clicks and drags on a card to signal some kind of intention or action the player wants to take.
Example: A player grabs a card from their hand, dragging it to the center of the screen which then signals that they want to activate the card's abilities.
Note: This grab movement is applied to the DSCardGrabber.grabParent object. See Card Prefab Setup for more info.
Simply put: Card flipping is a fundamental need for a card game. If you're not flipping cards, then what are you doing with your life? jk
Each card has a DSCardFlipper attached to it that drives the card flipping animation for its card.
Let's examine some of the essential parts of this script to understand how flip animations work...
In DSCardFlipper, there is a DSCardFacing enum saved that tells the card which side it should be showing.
When the DSCardFacing value doesn't match the object's state (ie When the card is showing it's back face, when the enum is DSCardFacing.Up), the appropriate card flip animation starts playing, bringing the card's state and the current DSCardFacing enum into alignment.
This string is used as a key for searching what rotation lerp-curves the flip animation should use.
These curves are saved in the DSCardMovementSettingsSO Scriptable Object that you'll need for your project.
Why AnimationCurves instead of Animator Controllers for each card?
Default lerp-curves are provided in the DeckStacker Movement Settings asset:
DeckStacker/DSCore/Resources/GlobalData/DeckStacker Movement Settings.asset
This key is saved on a prefab-by-prefab basis, and is accessed through the DSCard.cardPool property for consistency. (See DSCardPool for more info)
Simply rotating the Y axis to achieve a card flip is pretty boring, so why not put a little more PAZAZZ on it!?
In the above image, you can see that the flip animation is broken up into individual axes (X, Y, Z), and that the X and Z curves are somewhat symetrical while the Y starts at 0 and ends at 1. This is because...
Obviously, your mileage may vary, and you may want a different rotation setup for X and Z axis curves to fit your aesthetic.
Just be mindful that the X and Z curves are aesthetic, while the Y curve has a function.
More info on card flipping can be found on the DSCardFlipper page.
DeckStacker provides a DSCardArt script that updates card art, based on what a traditional western-style card needs:
By default, card art is updated after the card is released from its corresponding DSCardPool.
Obviously, unless you are making a card game consisting of traditional western-style cards, you'll want to remake this script to support the needs of your game.
More info on DSCardArt can be found on its page.
Conceptually, any place that gathers and arranges cards, as a group, is what DeckStacker calls a "stack".
Stacks represent a group of cards in a place.
A stack can be a pile (deck), a row, a column, or a fan of cards.
An "undefined" stack does not arrange cards, and is ideal for when cards are not gathered into a group, and generally "float" around the table.
When a stack moves its cards into a particular layout, it is called a restack.
Each stack type has a default direction that it will position its cards.
Note that the DSRestackHelper of a stack has a "Reverse Direction" flag. This will reverse the direction of the stack.
Card spacing determines how far the cards are spaced apart in a restack.
The edge of the card that is being measured from is different, between stack types.
Note: If Reverse Direction is enabled in DSRestackHelper, the above edge directions are flipped, as well.
Card spacing settings can be found in the Scriptable Object:
DeckStacker/DSCore/Resources/GlobalData/DeckStacker Card Spacing.asset
How does a stack know what DSCardSpacing to use?:
That sounds complicated, but just make sure your Card prefab's cardSpacingKey matches with a setting in "DeckStacker Card Spacing" asset.
In a stack's DSRestackHelper, there are card spacing overrides in the form of DSCardSpacingOverrideSettings.
This will override the spacing settings of any card that is put into it, universally.
This subject deserves its own page. See DSAction Guidelines and Use