1
\$\begingroup\$

As part of an interactive book I'm developing in Unity3D, I'm attempting to make an introductory scene that consists of moving lots of objects at different times - usually when another animation has completed.

For example, some trees (sprites) move down the page, which starts some text moving in and cloud sprites to appear and start to move across the page, then some text begins to scroll from the bottom to the top of the page, while some audio beings to play.

Currently, I've made a script that can move a series of clouds from left to right, or right to left across a background sprite given a speed (note: I'm not using any of the animation tools, simple C# scripting to move the objects on a loop).

Within Unity3D, what is the recommended approach to achieve this?

My thoughts are:

  1. Create a series of scripts that waits for n seconds (where n is the duration a desired 'animation'), and then start another - with somekind of 'master' or 'controller' script to manage the timeline.
  2. Somehow use the animation tooling built into Unity3D, although I don't think that this what they were indented for...
  3. Find a plugin that can help me create the scene and trigger animation/ scripts either on an event (animation finished) or after a specific time.

I've been using Unity3D for about 2 weeks now, so I'm certainly at the (pre?)-beginner level, I do however have over a decade of C# experience, so I'm comfortable with the scripting aspect.

Thanks in-advance,
Kieron

\$\endgroup\$
  • \$\begingroup\$ One problem I've encountered with using elapsed time to control animation events is that it depends on the frequency of the checking code. i.e. it may be time to invoke the event but the code which checks the time might not be called for another 100ms or so. Obviously this resolution might be acceptable for simple cases. I'm currently solving the same problem (non-unity) with a rudimentary event model to fire animations when required. I'll share some code once it's finished if still of interest. \$\endgroup\$ – Adam Naylor May 15 '15 at 8:08
  • \$\begingroup\$ @AdamNaylor Thanks! In Unity, presumable you could used the FixedUpdate to better guess when it's finished? \$\endgroup\$ – Kieron May 15 '15 at 8:39
  • \$\begingroup\$ unfamiliar but the name suggests that method will give you a fixed timestep. That could cause the problem above. If your fixed timestep is say every 100ms but your animation finishes every 70ms you'll get an error of 30ms which may accumulate if unchecked. An easy fix is just to re-integrate the offset - so you start the next animation at T+30ms instead of T. But if your rendering loop is non-fixed (it should be) then they will be out of sync and could look weird. \$\endgroup\$ – Adam Naylor May 15 '15 at 9:00
  • \$\begingroup\$ a great article on fixed vs non-fixed updating is here: gafferongames.com/game-physics/fix-your-timestep it relates to physics but hopefully helps. \$\endgroup\$ – Adam Naylor May 15 '15 at 9:03
2
\$\begingroup\$

I once needed to do this, to have several "animations" play off one after the other, here's my approach :

1- Create an empty gameObject, let's call it SceneControl that will be the parent of everything you need animated in your scene, for example Trees, which will contain all the trees, Clouds, that will contain all the clouds, Text, etc..

2- Set all the childs of SceneControl as inactive, from the Editor.

3- Make a script that you will then attach to SceneControl. In this script, you can choose whatever you like to do with the children :

A time loop that waits for X seconds to start childs sequence, rough example of this :

if( SceneControl.childCount > i) {
      if(Time.time - elapsedTime > X) {
      this.transform.GetChild(i).SetActive(true);
      i++;
      elapsedTime = Time.time
      }
}

This is automated to run every time the counter reaches X seconds, and it will start the next object on the order of the children of SceneControl, (make sure to declare SceneControl in Start()). You can otherwise choose whatever to do with the objects, and whenever to control them according to your needs, the basic idea is to make them all inactive, and set them to become active, after X second passes, after animation ends, after (insert condition here).

\$\endgroup\$
  • \$\begingroup\$ That's a good solution. I suppose you can set all of the timing offsets as properties. So start animation X via a matching 'delay' property? \$\endgroup\$ – Kieron May 20 '15 at 10:34
  • \$\begingroup\$ The code I wrote takes into count a set value of X. Like I said, if you want to have different timings according to every animation, you could just write a different "child activation" script. If you want another loop that won't wait for delays, you can just do something like if (FirstChild.isActive == true) SecondChild.SetActive(true); that will activate the second child as soon as the first one activates, etc... You can use whatever condition you need. I just gave you the general approach. \$\endgroup\$ – Zee May 20 '15 at 10:53
0
\$\begingroup\$

Just revisiting this after a while, I've found that the Fungus Framework on the Asset Store was just what I needed.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.