0
\$\begingroup\$

I have anywhere from 1-5 GameObjects that I'd like to distribute horizontally over a fixed distance. For example, if there are 3 GameObjects they might be spread out with a distance X between them like so:

[G1] <--x--> [G2] <--x--> [G3]

I was writing my own code to do this, when I realized that I could use a Grid Layout Group instead. I started to implement that but realized something: each of my GameObjects has scripts which let them be dragged and dropped around the screen.

If I use a Grid Layout Group to organize the GameObjects on the screen, then they will all be under a Canvas object. But with my drag-and-drop functionality, I only want the GameObjects to be organized in a 1x3 line when they first render. After that, I want to be able to control the location of the GameObjects manually using their Rect Transform positions.

I've never used Canvas before, and a lot of the documentation mentions that they are meant to control the layout of UI elements. My GameObjects are not really UI elements, but are letters and pictures that can be dragged around the screen (it's for an educational app).

Was hoping for some advice from someone experienced with using Canvas to control layouts. Should I:

  1. Start off the GameObjects nested under the Canvas with a Grid Layout Group... but when the item is picked up and dragged, unparent the GameObjects from the Canvas
  2. Find another way to initially layout the GameObjects without using the Canvas
  3. Something else entirely?

Thanks!

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Treating those objects as UI widgets of a canvas would probably be a very essential redesign. Objects on a canvas behave very differently from regular game objects. They don't even have the usual Transform component (They use a RectTransform instead). Converting objects back and forth between regular game objects and canvas game objects is certainly not impossible, but it's going to get iffy. But if you want drag&drop functionality, then you probably don't have to unparent those objects from the canvas. You just have to unparent the dragged object from the layout group and parent it to the canvas directly. You can then move it around using absolute positioning.

So it is certainly possible to have a game which plays only on a canvas. Whether or not this is the right approach for you and your game is something only you can tell. It depends on how many features you already implemented and if the features you still want to implement would be easier to do on a canvas vs. in scene space.

If you want to do it with objects in scene space, here is an example script which arranges its children in an evenly spaced line between two additional gameObjects (which you need to assign via the inspector):

using UnityEngine;

public class AutoArrange : MonoBehaviour {
    public Transform from;
    public Transform to;

    void Update() {
        for (var i = 0; i < transform.childCount; i++) {
            Vector3 childPos = Vector3.Lerp(from.position, to.position, (i + 0.5f) / transform.childCount);
            transform.GetChild(i).transform.position = childPos; 
        }
    }
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ If you want to create your own MonoBehaviour to arrange children in a line between two points, I could probably write you that in ~10 lines. Please respond if you need me to. \$\endgroup\$
    – Philipp
    Commented Nov 29, 2022 at 12:43
  • \$\begingroup\$ I think you are right, creating a non-canvas solution is my gut instinct and just wanted to doublecheck! yes i would love help writing that code... ideally it would take into account the width of the objects when spacing them out over a fixed distance!! \$\endgroup\$
    – kanamekun
    Commented Nov 29, 2022 at 12:52
  • \$\begingroup\$ @kanamekun Added the script. Taking "the width of the objects" into account is unfortunately easier said than done, because Unity GameObjects don't have a width. There are several components of an object which can have a width (collider, mesh, sprite...), but there can be several of those with different widths on the same object (and its children as well). \$\endgroup\$
    – Philipp
    Commented Nov 29, 2022 at 23:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .