How to programmatically insert a ScrollView into a Canvas?

New to Unity here; still reading the docs, but this had me stumped.

I understand that I can .transform.SetParent() to set a GameObject as another GO’s child, but whenever I try to do that to a ScrollView, like this:

ScrollView scroller = new ScrollView(ScrollViewMode.Vertical);
scroller.transform.SetParent(canvas.transform);

the editor tells me that “‘ITransform’ does not contain a definition for ‘SetParent’ and no accessible extension method ‘SetParent’ accepting a first argument of type ‘ITransform’ could be found (are you missing a using directive or an assembly reference?)”

I thought that every transform property was a RectTransform, but evidently I’m mistaken. What am I missing (besides the fact that the ScrollView isn’t a GO and its transform is different) and how can I add a ScrollView to a Canvas?

Thanks in advance.

ScrollView is a UI Toolkit (it’s in the UIElements namespace) object. It cannot be added to the UGUI Canvas. You need the new UI system and UIDocument or VisualElement to do that.
You can find the new UI Toolkit API here:
https://docs.unity3d.com/Packages/com.unity.ui@1.0/api/index.html

Thanks! So this can’t be solved purely with C#? From what I gather, I should delve into UXML, is that correct?..

If you want to use this piece of control, then yes. If you need a scroll area for your UGUI, then my advice is create a “Scroll View” prefab in the UGUI (Canvas) and instantiate when it is needed.
The things is, in UGUI everything is a pile of game objects and components on them. You can’t make a new one just like 'new SomeUIWidget();"-way.

I guess I am one of those code-centric, visual-editing-averse guys, so I’m not really comfortable with the visual editor…

I wonder why the Unity developers made that design choice – not of using XML, which can be expressive, albeit a little bit verbose, but of not allowing a more code-focused solution.

Anyway, thanks a lot for your help, really.

And even more than this, even if you do make all the objects properly, the UnityEditor “helpers” for the UI set of objects add so much value that you will be very frustrated trying to do it all in code. You’ll basically spend HOURS tracking down why something isn’t anchored right. Source: I’ve tried, given up.

Make the UI parts in the editor, parent them into your UI, turn them off, then either enable them or Instantiate them at runtime if you need to do dynamic stuff. I do this for things like “here are all the levels” added programmatically. I make a single “template” UI chunk in the editor, and then a script that turns it off and instanatiates as many copies of it as needed at runtime.

ALSO: whenever you instantiate a copy of some chunk of UI that is already in your UI, ALWAYS do it this way:

public GameObject MyExampleButtonChunkWithImageAndText;

When you want a new one:

GameObject freshCopy = Instantiate(
    MyExampleButtonChunkWithImageAndText,
    MyExampleButtonChunkWithImageAndText.transform.parent);

The second argument makes sure it gets parented right, otherwise it won’t show.

To clarify/summarize…

  1. As Lurking-Ninja alluded to, you seem to be confusing ScrollView and ScrollRect. ScrollView is part of the UIElements system. Canvases are part of the UGUI system, and within that system, that class for a scrollable area is ScrollRect. So you probably want to be using ScrollRect (part of the UnityEngine.UI namespace), not ScrollView (part of the UnityEngine.UIElements namespace).

  2. You should never directly create a component with the “new” keyword. Components are always supposed to be attached to a GameObject. You can create a component for an existing GameObject using AddComponent, or you can create a new GameObject with whatever components you want using the GameObject constructor. If you want to do things entirely from script, this is the way to do it.

  3. However, creating things entirely from script is not usually the easiest option. The more common way to create objects at runtime is to copy some other object using the Instantiate function. You can copy another object in your scene, or you can copy a prefab that you’ve created for this purpose. In both cases, you can set up all of the object’s components, properties, children, etc. the way you want them using the editor, and then create that whole arrangement from script using a reference instead of building it up piece-by-piece.

Exactly – the piece of the puzzle I was missing is the fact that an UIElement is neither a GameObject nor a Component. For some reason I thought I could treat the ScrollView (really, the UIElement) the same as a GameObject. Thanks to all of you, I have a better understanding of Unity’s object relationships.

And like @Kurt-Dekker mentioned, after understanding this, I too glanced at the possibility of recreating all of the ScrollView structure by hand… but I guess I’ll spare my sanity and just instantiate prefabs indeed. Thanks again, y’all.