I’ve tried to get this working with limited understanding. I’ve got as far as working out printing ‘beat’ to the console window, but I get groups of four beats at 120bpm, and then a pause before the next group of four. Can anyone tell me what I’m doing wrong?
function Awake()
{
beat = 60.0/120.0;
print("Beat is: " + beat);
}
function FixedUpdate ()
{
time += Time.deltaTime;
if (time >= beat)
{
print("beat");
time = 0.0;
}
}
Thanks for the reply. Neither FixedUpdate or Update give anything near musical timing.
It should be a solid beat you can tap your foot to. Is that what you’re getting?
I’m also finding it hard to track down information on the web about keeping good musical timing. I’ve only found one book on the subject, which was written 12 years ago and was for Windows 95:
I’m guessing it will help me understand the principles, but whether it’ll help me build a plugin for Unity I don’t know.
I think that trying to achieve timing that is suitable for music performance will be hard to achieve in the Update loop (which is for graphics processing and game logic). You probably won’t get millisecond precision, which is really what you want.
Perhaps there is the possibility of creating a .Net assembly that uses threading to run separate the music loop from the game loop. C++ would be even better I guess.
(I could be entirely wrong, as I haven’t done serious testing. Right now I’m just sending data through OSC to a supercollider server for some prototyping.)
It’s fine on my Mac, which was top of the range about 4.5 years ago. Have you tried with actual sound instead of printing? Logging output might be messing things up.
Actually the timing is pretty tight playing just one audio clip, but things start to slip when there’s more than 5 sounds being triggered. I wanted to implement a simple quantise to make sure that sounds are only played during a 16th of a beat.
Thanks for suggesting I ignore the printing speed though, as it does seem to be getting a lower priority than audio playback (obvious when you think about it!).
The code “works”, but it doesn’t do what you want it to do. :?
By resetting “time” to zero as you do, you are ensuring that the “beat” is being printed later than it should be. It’s as if you effectively decrease your bpm by a random value that is constantly changing, because of the imprecision of either Update or FixedUpdate, which unfortunately are all we have right now.
So, it’s completely possible to write different code, that tracks how many beats have passed, but that’s not going to be useful for any sort of quantizing operation. It’s only good for numeric feedback.
Unity has no ability to “keep up”, on anyone’s system, from any time in the future, with your code. However, even with more appropriate code, what you are trying to do simply doesn’t work in Unity yet without plugins.
I think the trouble is that the execution of the Update functions is always going to be tied to the speed of the renderer. What you could do is start your own update loop for musical timing and have that running as a coroutine and use Time.time for timing instead of Time.deltaTime (which is pegged to the Update functions).
This is basically what a C++ plugin for quantising musical timing would do anyway, the only question is whether the time value you use to track the beats is regular enough (in C++ you could peg it to the processor ticks, which is the best you can do on a computer and more than sufficient for musical timing).
The only reason I can see that the above code wouldn’t work is if the way Time.time is incremented is also tied to Update and rendering. I don’t know if this is the case or not, but maybe someone else might have a better idea.
We’re a minority, I think, so I don’t give us much of a chance. And I still think it’s possible to code it without official support, it’ll just take some work (have you tried dawvee’s approach?)
Besides, I would start demanding proper DSP support for audio synthesis and processing the minute they gave me built-in timing.
I’ve elaborated the above script a bit, so now it fires an OnBeat method once every beat (and an OnSwingBeat method that fires at an adjustable proportion after OnBeat). As you can see in the code, you would put functions like playing sounds into the OnBeat or OnSwingBeat methods, and you could use counters inside OnBeat() to construct a full transport.
I haven’t tested this out too extensively, but it seems to keep decent time. I’d have to test it on different machines under different loads to be sure, though.
Sure, we’re in the minority, but Unity Studios do contract work. If we’re willing to put some money behind it, it may not be too expensive for them to implement.
You can call a C# script from javascript if you put it in your Standard Assets folder, but it’s probably easier to have a javascript version if you want to extend it or add functionality. So, javascript version attached.
Unusually, it’s giving me the same behaviour as the print() test I was doing at the start - a group of three beats, then a pause, then another three beats, then two, then two, then three - completely random.
Hmm, I think C++ must be the way to go, but I really appreciate your help!