Card Game - Neewbie doesen't know what to do

Hi everyone!
I started a new project, a tabletop-like card game. I made a card prefab based system with a script that updates the card visuals (name, costs, etc.) based on ScriptableObject data.
I also set up a “card slot” system: each slot is a RectTransform inside my Canvas (it’s the market area) to draw cards from the pile, but each time I instantiate a prefab to my card slot, it appears way offset. It should appear centered into my card slot.
I suspect this is related to the RectTransform (anchors / pivot / SetParent), but I’m a newbie with UI layout and I’m not sure what I’m doing wrong.

Here is a screenshot:


(screenshot of the scene, the cards you see on the bottom left should appear centered in the “MarketSlot” I have selected)

Code-wise, I’m doing something like this when spawning a card:

GameObject cardObj = Instantiate(cardPrefab);
cardObj.transform.SetParent(cardSlotTransform, false);

then I set cardObj’s CardDisplay data…

What is the correct way to set up RectTransforms (anchors/pivot) on the prefab and the slot so that the card appears centered in the slot when I instantiate it?
Any tips or best practices for UI card layouts are very welcome!

Thanks in advance, and sorry if my explanation isn’t super clear :slight_smile:

For UI stuff you should probably just Instantiate() it with the variant that accepts a second argument as the parent. This will confidently “do the right thing.”

Your approach is fundamentally correct. I’m not sure if MarketArea has a GridLayoutGroup on it, but that’s a good way to start out, or at least a HorizontalLayoutGroup to lay the cards out going right. Don’t get too wrapped up in making cool fan-shaped stuff right now, just get the default card prefab instantiating the way you need in a grid first.

Attached is an example of “data driving” an arbitrary grid of objects, essentially the same problem you are working with.

9557998–1351300–DynamicUIDemo.unitypackage (94.0 KB)

What’s the reason you use UI for this?

I feel this unnecessarily complicates things, especially considering that you’ll also want to move things around too.

Detecting if a sprite received a mouseover or click is easy. Drag & drop is still manual coding in both scenarios. Alignment isn’t automatic without UI on the other hand it’s straightforward to accomplish and there’s no UI autolayout that would mess with your expectations.

What’s slightly more difficult, or at least different, is adjusting content to varying screen resolutions and aspects. But that’s assuming you already know how to do that with UGUI in the first place.

I’m already using a Instantiate() to spawn the card.
My main problem is that I’m not trying to do any fan-shaped hand. I’m just trying to lay my cards on display, but I have trouble understanding what is miss placing my clones.
First, I tried working with my MarketSlots, some empty rect transform where I could instantiate my prefabs.

(ideally it should look like this, my hands aranged horizontally)

but, for some reason I don’t understand, my cards end up layed in a completly diffent way, just like I showed in the first screenshot

I guessed it was caused by the rect transform, but I can’t find a way to fix it

Moving stuff on your own computations is almost never successful with RectTransform.

Sure, you can do it, but whoo boy, you’re in for a rough ride and you’re on your own. See below.

Here’s more reading.

Instantiating things into a UnityEngine.UI (aka, com.unity.ugui) Canvas hierarchy:

Everything instantiated in a UI MUST be parented to something valid in the hierarchy.

Therefore, if you instantiate prefabs into your UI hierarchy, always use the version of Instantiate that takes two arguments, with the second argument being the parent.

ALWAYS supply a valid under-a-canvas parent Transform where you want the UI chunk to appear.

Supplying positions to anything in UI space via code is almost always an exercise in futility. This is due to the inscrutable nature of the RectTransform object and how it interacts with other RectTransforms, anchors, and the CanvasScaler as well as the canvas mode.

By this I mean compute your positions as Lerp()-ed from other RectTransforms properly anchored in the corners of your UI in order to have the highest chances of success.

You are of course welcome to supply positions but it is on you to test on EVERY possible combination of aspect ratio and resolution to verify your positioning and anchoring. Expect it to fail if you do not do this testing.

Instead of supplying positions, either use a flavor of the Layout family of components to position things automatically, or else use invisible pre-existing Transforms in your UI as positional inputs.

Here’s why RectTransform stuff is hard: it takes 15+ lines of code just to move the anchors to the corners:

Now if you REALLY want to mess with computing your own UI positions, by all means go right ahead. But just know that there is almost ZERO support out there, as well as extremely few examples. Almost nobody does things this way, so be prepared to do it all alone and figure it out yourself.

That’s what I’m doing.
I’m using an invisible RectTransform called CardSlot in the exact position where I want the card. And when instantiated it simply makes it a child of that transform.
My main issue is, why isn’t it placing it in the right place?


is there any list of things I can check to see why it fails?

That’s a great question to answer by debugging.

Anytime code compiles correctly but misbehaves, that means it is time to start debugging!

As noted above however, there is a VAST surface of unknown behaviour behind RectTransforms, as outlined above. Good luck. The entire system is some devilish nefarious hackery that once you understand its limitations, works VERY well. But moving RectTransforms by code isn’t one of its core intended use cases.

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.

Welcome to the forums. Please know that RectTransform, Canvas (etc) is part of the UGUI UI feature and isn’t part of the 2D system if you ignore the fact that everything you see on the screen appears 2D. :wink:

Joking aside, if you’re asking about UGUI then please use that tag rather than 2D tags such as 2D-Graphics or Sprites as that puts your question in the 2D forum area rather than the UI area. The UI area is the place for your question to get the attention it needs.

I’ll go ahead and update the tags for you.

Thanks!

The anchors on the prefab cards are likely wrong. They seem to be anchoring to the bottom left when they probably need to anchor to the middle. Change all anchor values to 0.5, and then make sure the position and the width and height are still correct.

This should fix it, but also, your market slot rect transform seems to have an unnecessarily large rect. You should probably set its width and height to be 0 so that it’s just a point. This way, even if you have children with cornered anchors, they will not appear far away from it.

Btw a pro-tip when setting anchors, instead of setting the number values manually, click the grid-like graphic in the top left of the inspector and choose the behaviour you want. This makes it much easier to understand what the anchors are doing rather than just typing in the numbers. For a centered anchor (ie with values of 0.5), you would choose the middle element that looks like a cross.