Progression of Event Over Time

I’m certain this probably has been addressed in several different places, most likely in several different pieces but I’m not finding what I think I want:

Essentially, I want to have a progression of an event (i.e. translation) over a time AND, in stages. Pseudo-code…

function LoveMeDoMe!()
{
     Translate Me Up for 1 Second
     (wait until I'm at the desired position) then...
     Translate Me Forward for 1 Second
     (wait until I'm at the desired position) then...
     Rotate Me Left for 1 Second
     (wait until I'm at the desired angle) then...
     ...and so on
}

In other words I’m wanting to move say the camera to various positions in space over a period of time (rather than instantaneous). I’m not quite clear on working with a timer in code (which is what I was searching for in the first place); While() loops tend to hang Unity, which I understand but I’m apparently not using them safely, so any guidance would be very much appreciated. :slight_smile:

Thank you!

-Steve

You might find this thread useful - there’s a class attached that implements a simple timer. The basic idea with timed progression is that you record the start time and then each frame update, you subtract the start time from the current time to get the elapsed time. If you divide that by the time scale of the event (eg, duration of an animation) you get a value from 0 to 1. This is very handy for moving an object along a path with Vector3.Lerp or rotating or whatever.

As for the separate stages, a simple way to handle this is with a switch statement and an integer representing the current stage:-

int stage = 0;

switch (stage) {
    case 0:
        // Initialise first stage.
        stage++;
        break;

    case 1:
        // First stage action.
       if (progress > 1) {
           stage++;
       }
        break;

     case 2:
        // Initialise stage 2.
        stage++;
        break;

        // ...etc...
}

The key thing to notice is that each stage will typically have an initialisation phase on the even numbers that should be carried out only once. The odd numbers are the action phases - these are usually repeated until they time out, at which point they advance to the next stage.

Thank you andeeee (Andy? :smile: ) for the quick response!

I’ll parse all this right now and see what I get, but at first glance I do understand what you wrote which is perfect.

Thank you!!

-Steve

I would do

function Start () {
   yield MoveObject (transform, position1, position2, 1.0); // go up over 1 second
   yield MoveObject (transform, position2, position3, 1.0); // go forward over 1 second
   yield RotateObject (transform, angle1, angle2, 1.0); // rotate left over 1 second
}

MoveObject could be something like

function MoveObject (thisTransform : Transform, pos1 : Vector3, pos2 : Vector3, time : float) {
   var i = 0.0;
   var rate = 1.0/time;
   while (i <= 1.0) {
      i += Time.deltaTime * rate;
      thisTransform.position = Vector3.Lerp(pos1, pos2, i); 
      yield; 
   } 
}

And RotateObject would be similar.

–Eric

^^ Those are called coroutines if you’re not familiar with them: Unity - Scripting API: MonoBehaviour.StartCoroutine

The code posted so far are great for doing what you’d describe, and I’d absolutely, definitely recommend figuring them out and reading and understanding Andeeee’s description of the solution, since it’s a useful tool all around. If you’re planning on moving a camera around on a fixed path (for visualization, presumably), there’s a very handsome script on the wiki that does spline interpolation (basically, it smooths out the transition from one point to the next). You can find it here.

First of all this is great thank you all!

@burnumd:

Actually truth be told I’m doing a climbing system for my first-person character controller; think Thief, Dark Messiah or Mirrors Edge.

My first attempt was to disable collision on the Character Controller and move it through the climbable collider to no avail. I’ve now resigned myself to some fancy trickery by making the camera appear to be mantling the ledge (player wont know the difference) and at the end of it all simply relocating the Character Controller to the impact point of my raycast (RayCastHit.point) and animating the camera back to it’s default position relative to the Controller. Smoke and Mirrors! I have the Character Controller detecting climbable surfaces just fine and successfully being relocated to the ledge, I just now need to make it look good.

Anyway, the progression as such is first to translate the camera forward, a few scant units above the surface the player is climbing, then straight up back to its default position, giving the illusion the player has raised himself up onto the ledge.

The addition of rotation (which I may do without) was to loosen up the motion a bit to feel more like a body and thus less robotic.

Familiar with coroutines and the like as I’m using one for crouching, but I was stuck at creating a progression of events over time which has turned out to you guys offering a bountiful of information, so again thanks you guys…

…getting to studying right now!

-Steve

Actually maybe I better ask this before attempting:

Visualize a floor and a crate, and the player is going to ‘climb’ on top of the crate.

What I was thinking of doing is:

  • Store the WORLD transform for the Main Camera at that moment
  • Position the Character Controller to the RayCastHit.point WHILE…
  • …simultaneously Positioning the Main Camera at the the newly stored World Coords.
  • Translating, over time, the Main Camera to the RayCastHit.point + Vector3(0,0.5,0) (0.5 units above the surface lets just say, be it Y or Z or whatever :smile: )
  • Translating, over time, the Main Camera back to it’s known LOCAL POSITION to the Character Controller
  • Voila now the Character Controller AND the Main Camera are back together and standing on the crate, having appeared to have ‘climbed’ it?

Is there perhaps a more reliable way to reduce the potential for jittering such as temporarily deparenting the Main Camera from the Character Controller then reparenting after all the transforms are complete? (I worry that instantaneously positioning the Character Controller at the RayCastHit.point and the Main Camera at the stored World Coord in my list above might cause a pop, unless both can be reliably done on the same frame. I’m fully aware that the Main Camera is inheriting its local position from the Character Controllers world position, I just hope perhaps doing it fast enough and keeping the Controller still until all of this is complete will be smooth)

Thanks again in advance!

-Steve

Alright, victory!

My list above is exactly what I executed and it works! I opted to use Eric’s(Eric5h5) method since I already had a coroutine in my script so I was most familiar; I AM going to now at least apply switch:case to get some perspective on both methods but I’m so satisfied with how this turns out that at least this is a definite “win”. :smile:

Again thank you guys a TON!!

-Steve

Great! And thanks for posting detailed process of what worked for you – always good for other people with similar questions :slight_smile: