Monthly Archives: June 2016

Unity: Adding children to a GameObject in code and retrieving them

HoloLens, Technical stuff, Unity, Work
2 Comments

Update: The following feedback was pointed to me:

  • You should be careful when using GameObject.Find(…). First, it is bad for performance (note that in my code, I was using it in the Start method and then caching it. This is OK according to documentation, from a performance standpoint). Then, it relies on strings to pass the name of the object you are looking for. That’s not easily maintainable. Instead, it is better to set a public field in your script, and then assign the GameObject that you need in the Unity editor. To keep things simple, I won’t be doing this here but check the blog post here for more information
  • When you remove objects from a scene, you should always start by the last object and then go upwards.

End of update

When you work in the Unity editor, it is quite natural to use hierarchies of objects. For instance, you will have a table object and on this table object you want to place some cups objects, but if you move the table, you want the cups to move too. That’s quite a natural thing to do because it corresponds to the way that things are organized in “real life”. In fact, it even makes sense to have a hierarchy where the parent is an empty GameObject (which will be invisible), this way you can create logical groups of items.

For example, you can go in the Editor’s Hierarchy panel, create an empty GameObject (Right click on the panel and select Create Empty), and name it “Container”. Then you set a transform on the container, for example position = 0, 0, 2 meaning that the Container will be positioned 2 meters in front of the origin point.

2016-06-22_16-35-34

 2016-06-22_16-36-14

Then you can right click on the Container and select 3D Object / Cube to add a cube to this parent. If you so, the new Cube will appear at the exact same position at the Container, as you would expect.

2016-06-22_16-36-57

 2016-06-22_16-39-29

In code however, this is a little more tricky. This is where we realize that there is no true hierarchy of object in Unity but there is a hierarchy of transforms. Let see how to do that:

Creating new objects below the Container

Since we have an empty GameObject named Container in the scene, we can retrieve it in a script with the following code:

_container = GameObject.Find("Container");

The _container field, as you would expect, is of type GameObject. If you inspect it in the debugger, you will see that it is placed, as expected, at (0, 0, 2) (this is the transform.localPosition).

Now let’s create a new Cube and add it to the GameObject. Unfortunately, we notice that there is no Add or AddChild or similar method on the GameObject class. This is where we need to work with Transforms. The following code helps:

var newCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
newCube.transform.SetParent(_container.transform, true);
newCube.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);

In this snippet, we create a new Cube of 20 cm size, and we specify that the Cube’s transform’s parent is the Container’s transform (incidentally, Unity says that you should use SetParent and not the parent property directly, even though it can be set. Welcome to the ugly world of scripting ;). This will effectively create a hierarchy like we have in the editor. But there is a catch! If you run the code now, you will notice that the new Cube doesn’t appear, like you would expect, at (0, 0, 2) but it appears at (0, 0, 0). If you run this in a HoloLens, you will get pretty confused because (0, 0, 0) is probably going to be your head, and so the Cube is placed around your head and you won’t even see it until you move to a different location).

If you inspect the newCube in the debugger, you will see that its localPosition is set to (0, 0, –2). So it seems that Unity went out of this way to misunderstand what I was trying to do, and forced the newCube location to be at (0, 0, 0) globally, which means (0, 0, –2) relative to the parent. Ugh…

When reviewing the documentation, I found an overload of SetParent which takes a parameter named worldPositionStays of type bool. I thought that was promising, but setting this parameter to true didn’t change a thing. I also tried variations of the calls above. The newCube still appeared at (0, 0, 0). So to fix it, I forced the localPosition to be at (0, 0, 0) (relative to the Container). This way the global position of the Cube is (0, 0, 2).

newCube.transform.localPosition = new Vector3(0f, 0f, 0f);

This sounds unnecessarily complicated, so if I am doing things the wrong way, please add your knowledge in the comments, thanks!

Retrieving the children

Now how can we retrieve the children and iterate on them? For instance, this can be useful if you want to clean the scene by removing all the Cubes, but leaving the Container in place so the user can add more Cubes. Here too, we need to work with the transform hierarchy. Here is the code:

Note: For this simple demo I am not going to update the code BUT as was pointed in the comments, you should rather remove objects from the end of the hierarchy!

foreach (Transform t in _container.transform)
{
    var cube = t.gameObject;
    Destroy(cube);
}

In this code, we get the transform property of the Container and then we iterate through all its children. Then we retrieve the gameObject property of each transform, which corresponds to the Cube that we want to delete, which is done by calling the Destroy method.

Hopefully this quick tutorial will help you when you do this kind of things. Structure is very nice, but structuring a scene in code is a bit tricky. This should save you some time. Now again, if you see something that can be improved, don’t hesitate to point it out in the comments.

Happy coding!
Laurent

GalaSoft Laurent Bugnion
Laurent Bugnion (GalaSoft)

Share on Facebook
 

Slides and sample code for my presentations at #VSLive Boston

.NET, Conferences, Universal Windows Platform UWP, VSLive, Windows 10, Work, WPF, XAML
2 Comments

Thanks to everyone who came to my sessions at VSLive Boston. I had a great time. I hope it was informative and useful. I am aware that you take time out of your job to come and see us speak and I really hope that you found it worth your time.

I had two sessions:

Windows 10 – The Universal Application: One App To Rule Them All?

You can find the slides and sample code for this session here. This page also links to a video showing how Windows 10 Universal apps work on HoloLens!

Windows Presentation Foundation (WPF) 4.6

Here are the slides and sample code.

Thanks again for your warm welcome in Boston!! I even had some time to visit the city and had a blast in the historical places.

Happy coding
Laurent

GalaSoft Laurent Bugnion
Laurent Bugnion (GalaSoft)
Share on Facebook
 

A world of devices – Upcoming talk

Personal, Technical stuff
No Comments

In September, I will give a special session in Amsterdam, at an event titled LevelUp Mobile. My talk is titled “A World of Devices”. Here is the abstract:

How do you feel when you forget your phone? If, like Laurent, you feel lost, you are probably also living in a world where devices are augmenting you and making you more connected, more efficient and more skilled (or is it addicted?). In this session, Laurent Bugnion, geek, developer and gadget addict will show you next generation devices and the collaboration between
them. From smartphones to smartwatches, from IOT and phablets to XBOX and Surface Hub, from Cortana to HoloLens, we live in a world of devices where software is coming out of the computer more and more. We’ll take a quick look at the past, a good look at the present and a glance at the future with lots of demos.

This talk is based on thoughts that I have had in my mind for many years already: Our devices, even the so-called smartphone (which, let’s face it, is not a phone but rather a pocket-sized computer with which you can, if you have to, place calls over the phone network) are augmenting us with superhuman abilities. How else could we know, with a precision of a meter or less, where we are positioned geographically? How else could we have access, from almost anywhere in the world (OK, that’s an exaggeration, but it is close enough for most of the civilized world) to a very significant portion of human knowledge? How else could we have access, anywhere and at any time, not only to enough movies, music and books to educate and entertain us multiple lifetimes. How else could we keep in touch 24/7 with our families and friends all over the world?

The smart device we have in the pocket is effectively turning us into cyborgs. Augmented humans. And this is only the beginning.

Picture1

These days, we witness an incredible number of new devices, with new form factors. Maybe the most intriguing ones are the ones placed in the “wearable” category. The most common are smartwatches (which, like the smartphones, are much more than “just” watches). In their lowliest form, they need a connection to a smart device to be effective. But many are doing more than that. For instance the Microsoft Band 2 has a built in GPS and so it can record a run even without the help of a connected device. It also has a wealth of sensors that can be used to build mobile applications: Pressure sensor (so you can use it as a barometer / altimeter), heart rate, pedometer, distance, stairs, accelerometer and gyroscope (so you can use it to control 3D scenes or even physical objects), and even a UV-meter to tell you when you should put on solar cream.

We also saw the appearance, and then the quasi-disappearance, of connected glasses made by Google. It was certainly an interesting sociological experiment. Very soon we witnessed a lot of resistance in the population. Many felt aggressed, violated by the glass wearers (who were often referred to as “glassholes”). They felt that the wearers were displaying arrogance, and invading their private life, possibly recording video or taking pictures. The fact that the device had a low battery life and a low resolution was not playing a role in this concern. Neither was the fact that our lives are already recorded all the time, either by so-called security cameras, or by the constant picture-taking that everyone is doing these days. For some reason, the Google glasses were different and were perturbing the peace much more than any other device. This is (partially, to be completely fair) why they failed to gain traction, and why you don’t see them anymore these days. There are no doubts in my mind that more such devices will appear on the marketplace at some point in the future, although probably in a different form factor, less conspicuous and closer to normal glasses. There are already amazing devices available such as this model which allows an app to inform a person with impaired vision about what is happening around him/her. See Shaqib Shaikh’s great video shown at Microsoft Build this year!

This brings us, of course, to augmented and virtual reality. Even though these are not new domains, we are seeing this year a lot of interest and new devices. Oculus Rift is releasing its second iteration, HTC is selling its Vive device which is pretty great. Even on the low end of the marketplace we see devices like the Samsung Gear which takes advantage of smart devices and turns them into a poor man’s VR headset. And on the AR front we have of course Microsoft HoloLens, released to developers, an incredible device that not only places holograms in your everyday world, but also interacts with the real world and allows, for example, virtual objects to bounce off the real tables and the real walls, and for virtual characters to sit in real chairs.

And the most beautiful is when all these devices, from small to large, interact together and create a connected, augmented environment. This is the promise of Windows 10 and its universal applications, of cross-platform computing which has never been so promising, of wireless protocols that connect devices in very short or very large range, and allows them to collaborate.

At the LevelUp event, I will be talking about these concepts but also demonstrating some of the futuristic features that are already available to developers and to the public. I am really looking forward to have the occasion to share these thoughts with the audience, and demo how far we came with devices and their interactions.

Happy coding!
Laurent

GalaSoft Laurent Bugnion
Laurent Bugnion (GalaSoft)
Share on Facebook