Monthly Archives: December 2014

ThreeBody – Can Gravity “keep it all together”?

I have returned to N-body, my first mobile effort , with the goal of making it cross -platform and adding new ideas. Given all my recent positive experiences with the Unity game engine the idea is to port as much as possible and avoid “the rewrite”. (This has a very tempestuous history in software and is one of the things Joel Spolsky thinks you should never do.)

The good news for the small community who have enjoyed N-body is that moving it to Unity is going quite well, and I am FULL of cool ideas I want to add: gravitational fields for non-spherical objects, galactic potentials, dust accretion – it’s almost endless. The bad news is that I read a great Sci-Fi novel “The Three-Body Problem” by one of China’s top sci-fi writers, and this has caused me to set aside Nbody for awhile. “The Three Body Problem” reminded me of the non Sci-Fi book with the same title (you could see how that would happen). One of the things I made a note of when I read the more academic of these books was the static three body problem. The question is: can three bodies be placed in initial conditions with zero velocity such that they will stay in a bound configuration? Would you expect that since gravity is attractive they would “keep together”, perhaps with some cool triple orbits?

As I was reading the sci-fi 3BP I was feeling like I needed a break from NBody and figured I’d try a quick mock up of the static three body problem in Unity. As I get more kung-fu with Unity (and using the leap frog integrator I had ported for Nbody) this kind of side project becomes very do-able. I spent an afternoon doing the basics and found that there was a nice little physics “time waster” game here.

Shortly after, during my usual lunch time perusal of arxiv, I found a paper about using GPUs for N-body simulations which mentioned replacing the three bodies with three binaries. Another addition for the ThreeBody app.

This was all about a month ago and since then I have added the minimum of “gamification” so others can take a swing at this problem on their mobile devices. It is weirdly addictive and a good way to see how sensitive the problem is to initial conditions. Hope someone out there also finds it fun.

You can find ThreeBody for Android and Blackberry (coming soon to  Amazon and iOS). There is some further technical detail.

[social4i size=”large” align=”float-right”]

The Unity 4.6 UI – Some Tidbits

Unity 4.6 provides a fantastic new UI framework. I will never use the old OnGui() again! I have been using the new framework for the past several months while Unity 4.6 was in beta. During this time I have collected a few tidbits on working with the framework.

Getting Started

The tutorials  are very good and the information in the manual is getting better all the time. I found the tutorials on Canvas, RectTransform, Button and Event System a bare minimum to get the idea of the whole thing.

Adapting for Mobile Screen Sizes

This was one of my first “care-abouts”. There are two things that are important to know. The first is the anchor system for the layout of elements  (see the RectTransform tutorial) but that is only part of the solution. The crucial other element is adding a CanvasScaler to your root canvas.

Screen Shot 2014-11-29 at 12.45.51 PM

Once attached to a Canvas this can then be set to give a reference size and you’re good to go. As the device screen size change your UI element will scale appropriately.

UI interactions with Scripts

In the C# world the Unity elements can be created and modified as you would expect. You will want one or both of the following includes:

using UnityEngine.UI;
using UnityEngine.EventSystems;

ColorBlock: Changing Button Colors

The ThreeBody game I am creating makes use of collections of buttons as radio boxes. I set the disabled and highlighted colors to reflect the color I want for unselected and selected. When it is time to enable a button, then the normal color of the button is set to the value in the highlighted color. It would be reasonable to expect that:

button.colors.normalColor = Color.white; // DOES NOT WORK!

would work. It does not. Instead you need to make a temporary copy of the ColorBlock and then modify its elements and copy back the ColorBlock:

    // flip to highlighted color
    private void EnableButton(GameObject go) {
        Button b2 = go.GetComponent<Button>(); 
        ColorBlock cb2 = b2.colors;
        cb2.normalColor = cb2.highlightedColor;
        b2.colors = cb2;        
    }

Touch Events and Buttons

Button touch events will still fall through into code that handles touches so it becomes important to screen out those touches that are over top of buttons. A technique that works for both mouse and touch events is:

    private bool IsTouchOnButton() {
        GameObject go = EventSystem.current.currentSelectedGameObject
        if (go != null) {
            if ( go.GetComponent<Button>() != null) {
                return true;
            }
        }
        return false;        
    }

 Panel Fading and CanvasGroup

There is not a lot said about panels in the tutorials or online docs. These appear to be containers for holding a subset of the UI being developed. I found them useful for Settings Menus and High Score panes. In order to run a fade effect on these panels, you can add a CanvasGroup (which then has a field “alpha” that allows direct control over fading). An example of such a fade coroutine is:

    public GameObject menuPanel; 
    private const float FADE_TIME = 0.5f;
    private const float FADE_STEPS = 10f;
    private const float FADE_INCR = FADE_TIME/FADE_STEPS;
    
    private IEnumerator FadeMenuPanel(bool visible) {
        CanvasGroup cg = menuPanel.GetComponent<CanvasGroup>();
        if (!visible) {
            for (float i=FADE_STEPSi > 0i--) {
                cg.alpha = i/FADE_STEPS;
                yield return new WaitForSeconds(FADE_INCR);
            }
            cg.alpha = 0.0f;
            menuPanel.SetActive(false);
        } else {
            menuPanel.SetActive(true); 
            cg.alpha = 0f;
            for (float i = 0fi <= FADE_STEPSi++) {
                cg.alpha = i/FADE_STEPS;
                yield return new WaitForSeconds(FADE_INCR);
            }
            cg.alpha = 1.0f;            
        }
    }

Note that in my case I also change the panel active status. This needs to be done at the end of the fade out or the start of the fade in for the object to stay visible during the fade.

Off-Topic: Trail Renderers

This is not part of the new Unity UI theme but as part of getting ThreeBody ready I had to learn a bit about TrailRenders. I use these to leave paths behind the “stars” in ThreeBody so the orbital paths can be seen. I always had weird issues with setting materials and colors until I finally found some clear advice on the forums about the material choice. I need to choose a particle material and the trails look best with a mobile/particle/vertex-lit shader on that material. To get solid colors I have created a simple 128×128 solid color PNG, imported as a texture.

Another tidbit is how to recycle objects once you have used trail generation. To get rid of the trail I ended up setting the trail length to -1, then counting 5 update cycles before setting the object inactive and putting it back into my object pool. I played around with coroutines for this but they ended up creating more complications – and a simple synchronous design won out.

Hope some of these save you some time.

[social4i size=”large” align=”float-right”]