Hi!
I’m making a fan-made Smash Brothers platform fighter in Unity. I have a lot of stuff working: like how to play animations at the right times with the right button combinations, basic collisions for ground, hovering platforms, ceilings and walls (using a custom physics system and not Rigidbody). I can move, jump, taunt, “attack” (with no hitboxes yet), crouch, move through hovering platforms, etc. Basically, I can control and move my fighters around with almost nary an issue (except for my controller being not quite complete yet.)
I’m developing something called AnimCommand, a custom scripting “language” / system just for this game: a scripting system for characters’ move sets where scripts for each relevant animation are stored in a ScriptableObject, where the execution is done by the system’s own associated C# interpreter MonoBehaviour. It can play sounds, wait (with varied results upon repeating the animations), stop sounds, play particle effects, change script upon changing animator controller states, manipulate variables, and slow down/speed up animations for attacks to sort of “create” ending/recovery lag. Problem is, I can’t seem to get the frame timing frame-perfect, or consistent, to my liking. This poses problems for both particles and hitboxes, making attacks all wonky.
What I mean is that, if I: say, play a Particle Effect. It’ll play at different times, at different locations, etc. I wait, say, for frame number 5 in the current animation. The effect never plays at the right time, or never does it consistently. I want to avoid having to turn to animation events due to certain limitations (event functions only using one parameter, for example, while my hitbox command has over 20). I’m using a coroutine to read through each script line by line, and have it yield a new WaitForSeconds(framesToSeconds) when a Timer (wait) command is reached, after which it starts over each time a script re-starts or a new one is loaded.
But that yield new WaitForSeconds(framesToSeconds) is where the problem lies. It waits for varying numbers of seconds each time the animation runs. So it could be called on frame 5 like before, or frame 4 or 6 or even 7. Here’s the algorithm I’d come up with. I need help figuring out consistent, frame-dependent timing for AnimCommand, and how on Earth to handle frame stutter: ie lag or picking up frames. I even get performance variations in the Editor play mode VS a development build of the same project.
Current code:
yield return new WaitForSeconds(acmd_Effect.syncFramesToWait / motion.GetFrameRate());
Where acmd_XXX.syncFrameToWait = the amount of animation frames to wait for as an Int, divided by the animation’s current float frame rate(60fps in most cases). So say I want an effect to play at frame 5 again, it’s 5/currentFrameRate (if 60, that’s 0.83333… seconds) But that will cause events to fire off at random times. I know I’m missing something, but what that is completely escapes me. I’d post the whole Coroutine, but the timing is the issue, everything else works perfect, so I posted the WaitForSeconds.
What I need is to know how to convert a positive integer amount of frames within the currently-playing animation state to a float timeInSeconds for use in yield new WaitForSeconds(). so that the timing will be the EXACT SAME on each animation play, bar for performance drops/spikes (which should still be a very similar timing thing) A former acquaintance of mine who RE’s game console stuff tried explaining this to me, but the actual info passed right over my head as he preferred me to figure this out myself. I wanted to, I really did, but I just can’t do that. It’s kinda embarrassing for me to admit that I’ve hit such a possibly simple snag in my project. I’ll bet if I get the answer, I’ll be like “DUH, that shoulda been obvious lol”
Thank you for reading this wall of text, and I hope it’s understood! haha