So I’m making a timeline driven game that fires objects at the player according to signals on the timeline. But, I want each shot to arrive at the player according to that time (think rhythm games like Beat Saber). So what I need is to off-set each signal by how long it takes for the shot to get from the emitter object to the player object. I can do this all by hand after I’ve created each signal track, but if I can manage this via a script I’d save a ton of effort.
To reiterate:
-
At the start of runtime:
-
Script measures distance from Object to Player, determines shot travel time will be e.g. 2 seconds based on shot speed*.*
-
Script changes all the Fire signals on the timeline track to be 2 seconds earlier.
-
Repeats for all other alike firing signal types.
Looking through the timeline docs I’m not sure if I can even edit existing signals like this? I see I may be able to read a track and maybe create a clone with the corrections and delete the old one, but I don’t know.
Maybe, if it’s possible, I can just offset the time of the entire track at once, and just put each shot with a different speed on their own track (I’d end up with no more then 3 extra signal tracks if that works). This would be the best solution using the least amount of CPU time when starting the level.
I have never tried it, but in case it sparks an idea in your investigations… it looks like according to the docs SignalTrack inherits from MarkerTrack? So you would be looking for GetMarker(n) sorts of calls, where a Marker has a get/set on “time”? (Rather than clips which have a duration etc.)
(No idea if you can adjust at runtime. My very limited experience was with a window of my own to make assembling timelines a bit faster (with clips, not signals). Hopefully someone with more experience jumps on.)
OK, after digging through the API for hours, I’ve figured this much out:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Timeline; //IMPORTant, don't leave this out.
public class TEMP : MonoBehaviour
{
public TimelineAsset timeLine; //Timeline asset
// Start is called before the first frame update
void Start()
{
//This script will find all markers named "X" in track 1 of the timeline.
//It will change their time, and then rename it.
//
//WARNING all changes this script makes to the asset are permanent
TrackAsset track = timeLine.GetRootTrack(1);
int mCount = track.GetMarkerCount();
for (int i = 0; i < mCount; i++)
{
IMarker marker = track.GetMarker(i);
var signal = marker as SignalEmitter;
if (signal.name == "X")
{
Debug.Log("Signal named "+ signal.name + " found @"+ marker.time + " Attempting to move 10 seconds, and rename.");
marker.time = marker.time + 10.0f;
signal.name = "New Signal Name";
Debug.Log("Signal now named '"+ signal.name + "' time is now @"+marker.time);
}
}
}
}
You very sadly can not get a marker’s Emit Signal, as it does not exist in the API, but oddly each marker is named “Signal Emitter” by default when you drop a signal onto the timeline. You can see this in the properties window at the top. You can find this name with GetMarker, but for some reason it also tacks on a bunch of extra crap, so by default GetMarker will have a value of “Signal Emitter (UnityEngine.Timeline.SignalEmitter)” which is messy to look at. Anyhow, after dropping my signal on the timeline track I named the marker on it to “X”, and then I searched for it and changed its time right on the TimeLine asset itself.
Not ideal but this is a jumping off point.
Side note: I’ve found an older post on the forums asking questions along these same lines that I can now answer, but I’m not sure if I should dig up old posts with no responses for nearly a year to post the solution.
edit
Crap, I did this wrong. I forgot, I’m supposed to add “DEAR PEOPLE FROM THE FUTURE: Here’s what we’ve figured out so far”
edit
I’ve further refined my test script solving many of the issues with names.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Timeline; //IMPORTant, don't leave this out.
public class TEMP : MonoBehaviour
{
public TimelineAsset timeLine; //Timeline asset
// Start is called before the first frame update
void Start()
{
//This script will find all markers named "X" in track 1 of the timeline.
//It will change their time, and then rename it.
//
//WARNING all changes this script makes to the asset are permanent
TrackAsset track = timeLine.GetRootTrack(1);
int mCount = track.GetMarkerCount();
for (int i = 0; i < mCount; i++)
{
IMarker marker = track.GetMarker(i);
var signal = marker as SignalEmitter;
if (signal.name == "X")
{
Debug.Log("Signal named "+ signal.name + " found @"+ marker.time + " Attempting to move 10 seconds, and rename.");
marker.time = marker.time + 10.0f;
signal.name = "New Signal Name";
Debug.Log("Signal now named '"+ signal.name + "' time is now @"+marker.time);
}
}
}
}
1 Like