- Home /
How to move a gameObject without affecting its childrens' positions?
Hello, I'm working on a File manager-like structure with NGUI, so far so good. The way I got my "Folder" set up, is that a folder consists of "Parts" which consists of a Background, Icon and a Label, "Contents" which carry the folder's content, a "FolderContent" could either be a "Folder" or "FILE".
Whenever I "Open" a folder, (in short) I hide the previous folder contents and show the new ones'.
The problem is, when I pickup a folder and move it with the mouse (drag and drop or just pick and hold) I auto-organize the current folder's contents (reposition them), when a folder gets repositioned (n shifts to the left/up), its contents also shift with it, so when I open the folder later, I will see that the contents' are not positioned correctly.
I can get around that by using one of my methods "OrganizeContents" which does exactly what you think, but that wouldn't be necessary to do each time I open a folder, it's redundant.
Have a look:
Any ideas how to move a gameObject without affecting its children?
Another work-around would be to move the Folder's "Parts" when auto-positioning it, but that would bring inconsistencies in other places.
If I can't do what I'm asking for, any other work-arounds beside the two I mentioned?
Thanks.
Actually, each folder has a List of "FolderContent"s, if that's what you mean. It just makes sense to put the contents of a folder, inside the folder, doesn't it? - It has nothing to do with NGUI, just common sense.
Of course that folder has some content, but this does not mean you have to create it using Unity objects hierarchy. If you gain nothing from it, and additionally it causes problems, then why even bother?
In my approach, you still have proper hierarchy. I'll try to describe it in more detailed way.
Let's assume every folder/file is represented by a Plane object for which you have created a prefab. You also have to create a FileSystemObject script and attach it to this prefab. Basically, FileSystemObject should look like (C#):
public class FileSystemObject
{
public FileSystemObject[] children;
public FileSystemObject[] parent;
public ObjectType type; // this can be an enum {File, Directory}
}
When browsing your data you can dynamically create a number of Plane instances, get their FileSystemObject components and sets their properties. And you have the hierarchy you wished for, but don't have the problems related to position.
Ins$$anonymous$$d of dynamic creation of Planes, it would be much better to reuse some instances created at the start of your application.
As to navigation: when you click on my Plane (or in your case object visually representing the folder), you can retrieve its script and properly instantiate children:
var fso = GetComponent();
foreach(var child in fso.children)
{
// instantiate children
}
I think it should be quite easy to convert your current solution to this approach.
why the array of parents? a folder content has only one parent. storing a ref to the parent was my previous setup, but then I figured I don't need it. Is there a reason for the parents array?
O$$anonymous$$ thanks I got your point, basically keep everything the same, but don't mess with the game objects' hierarchy, no parenting. gonna have to go now, I'll do it. could you move your comments to an answer? I will accept it once everything's ok.
Answer by ArkaneX · Sep 01, 2013 at 04:15 PM
What is the reason behind storing subfolders and files as children of the folder? I know nothing about NGUI, but if I were to code it in pure Unity, I would probably store subfolders and files as an arrays of GameObjects[] in parent folder script, not as standard GameObject children. If required, I would add another property for keeping reference to parent (null for top level folder):
public GameObject[] folders;
public GameObject[] files;
public GameObject parentFolder;
This way, repositioning parent would not affect children position. You can of course change GameObject in above snippet with proper objects.
EDIT: converted to answer after exchanging a few comments with OP (under question).
That did it just nice! A lot of code has been nuked on the way :) Easy conversion as well like you said.
However I think it's more elegant to use OOP here and not simply an enum to represent a FileSystemObject. There's a lot of benefits to that, for example, a folder doesn't need to have an array of files and folders, just an array (preferably a list) of FileSystemObjects, which could be either a File or a Folder.
Again, no need for the parentFolder, in case you're putting it so that each folder knows its parent when you "GoBack", you could just use a stack, each time you open a folder you just push, when you go back you pop, the parent would be left out as extra luggage in the folder class. Thanks a lot for your help :)
You're right regarding OOP - my solution was just a quick 'how to' example. Glad it was helpful :)
Answer by DESTRUKTORR · Sep 01, 2013 at 04:17 PM
The best method for moving the parent object without moving the child objects would be to save the child object's absolute position (transform.position) prior to moving the parent, then, after calling the move on the parent, set the child's absolute position back to what it was before the move.
This does sound quite like repositioning them once again, but performance-wise, it's better. 2 n loops, an assignment in each loop, saves some math/calculations. I'll benchmark it with the auto organizing method, if there's a huge dif, I'll choose your solution :)
I'm afraid it's not gonna work in my situation. Thinking about it, it is a good solution but not for me because what would happen if there ware more folders to the right/under 'Vids'? (in the previous example), using your method, I would have to save the contents positions of all those folders and then re-assign them again... :/
Why do it in the loop? The user will only notice that their position is changed after the next frame is loaded. Just ensure that it's moved back to its original position after everything else has moved XD. One way or another, it's only a reassignment of a Vector3 variable, which is little more than 3 floats (12 bytes, which, in the grand scheme of things, is really not much, considering we are beginning to see megabytes, or millions of bytes, as being laughably small amounts of data), and it's an O(n) efficiency, as the only level of variation is the first layer of children.
However, like ArkaneX said, it might just be easier if you simply didn't have the objects parented to one another, lol. The primary purpose, by and large, of making a game object a child of another is to ensure that they move, together, and sometimes to allow scripts to more easily access components of their children/parents (or, on occasion, to organize the hierarchy a bit better, but that's really not all that usual, nor should it take precedence over efficiency, I$$anonymous$$O).
Thanks for clearing out when to make objects childs of other objects. I obviously mis-used parenting there.