MajorCooke Posted April 30, 2019 Share Posted April 30, 2019 I've seen people with a footstep effect before, but I've always been at a loss on how to recreate this ability, except for a script someone gave me. However, unfortunately it tends to go out of sync, so I'm wondering if there's a better way to perform this? float timerevent = 0.40; float sleeper = 0.25; float vol = 1.0; integer running = FALSE; default { on_rez(integer start_param) { llResetScript(); } state_entry() { integer agentinfo = llGetAgentInfo(llGetOwner()); llSetTimerEvent(timerevent); } timer() { integer agentinfo = llGetAgentInfo(llGetOwner()); if(agentinfo & AGENT_ALWAYS_RUN) { running = TRUE; } if(agentinfo & AGENT_WALKING) { if(running == TRUE) { //llStopSound(); llTriggerSound("6559cdbf-a664-d93c-184e-42d95a965104", vol); llSleep(sleeper); } else { //llTriggerSound("4c19068e-38ae-f3a9-21a3-630a59d62a31", 0.4); llTriggerSound("6559cdbf-a664-d93c-184e-42d95a965104", vol); llSleep(sleeper); } } else { running = FALSE; llStopSound(); } } } I have an object attached to the feet already, but depending on how intensive the place I'm at will definitely slow it down, since animation speeds and the like are not synced together. I was considering using http://wiki.secondlife.com/wiki/LlGetPos by getting the distance from the avatar, but unfortunately, the caveat of object position with avatar animation being invisible to the simulation means I cannot get it based on that. Does anyone have a better idea on how to do this? Link to comment Share on other sites More sharing options...
Kyrah Abattoir Posted April 30, 2019 Share Posted April 30, 2019 Why on earth are you using llSleep() commands inside a timer event. Link to comment Share on other sites More sharing options...
steph Arnott Posted April 30, 2019 Share Posted April 30, 2019 1 minute ago, Kyrah Abattoir said: Why on earth are you using llSleep() commands inside a timer event. Sorry? Are you not alowed to stall the script in the timer event? Link to comment Share on other sites More sharing options...
Kyrah Abattoir Posted April 30, 2019 Share Posted April 30, 2019 2 minutes ago, steph Arnott said: Sorry? Are you not alowed to stall the script in the timer event? It's bad practice to lock up the main thread instead of rescheduling your timer event. You can't process events during a sleep. 1 Link to comment Share on other sites More sharing options...
steph Arnott Posted April 30, 2019 Share Posted April 30, 2019 Just now, Kyrah Abattoir said: It's bad practice to lock up the main thread instead of rescheduling your timer event. You can't process events during a sleep. Okay, I guess all functions with with time penalties are 'bad practice' as well. Lost me me on that logic. Link to comment Share on other sites More sharing options...
Kyrah Abattoir Posted April 30, 2019 Share Posted April 30, 2019 You're off topic once again. I can understand someone using llSleep() to avoid using a timer, but llSleep() inside a timer is just silly, especially here where the sleep time is shorter than the timer scheduling anyway. But I also don't expect someone like You @steph Arnott to understand good practices given how you deliver bad advice with the precision of a swiss clock. 3 Link to comment Share on other sites More sharing options...
steph Arnott Posted April 30, 2019 Share Posted April 30, 2019 Just now, Kyrah Abattoir said: You're off topic once again. I can understand someone using llSleep() to avoid using a timer, but llSleep() inside a timer is just silly, especially here where the sleep time is shorter than the timer scheduling anyway. But I also don't expect someone like You @steph Arnott to understand good practices given how you deliver bad advice with the precision of a swiss clock. No, that script is alowing the server to catch up. Clearly it is you that does not understand. 2 Link to comment Share on other sites More sharing options...
steph Arnott Posted April 30, 2019 Share Posted April 30, 2019 (edited) 6 minutes ago, Kyrah Abattoir said: So server catch up is beyond your comprehension? Okay, whatever. Edited April 30, 2019 by steph Arnott Link to comment Share on other sites More sharing options...
Kyrah Abattoir Posted April 30, 2019 Share Posted April 30, 2019 (edited) @MajorCookeUnfortunately, animations are purely clientside, so there isn't even a guarantee that they started at the same time for everyone unless llStartAnimation was fired for everyone while the object was in view. Even two animations started at the same time will eventually drift apart. The only way to "resync" is essentially to stop the animation and start playing it again. Edited April 30, 2019 by Kyrah Abattoir Link to comment Share on other sites More sharing options...
steph Arnott Posted April 30, 2019 Share Posted April 30, 2019 2 minutes ago, Kyrah Abattoir said: @MajorCookeUnfortunately, animations are purely clientside, so there isn't even a guarantee that they started at the same time for everyone unless llStartAnimation was fired for everyone while the object was in view. Even two animations started at the same time will eventually drift apart. The only way to "resync" is essentially to stop the animation and start playing it again. The script is not an animation. Secondly the sync is subjective to how fast the others BB is and how far away from the server in RL. Link to comment Share on other sites More sharing options...
MajorCooke Posted May 1, 2019 Author Share Posted May 1, 2019 (edited) Like I said, it was sent to me by someone else. I know very little about scripting. As for the stopping and restarting, I could try and measure when the animation stops and starts, but I have no idea how to script that in properly. Can someone help me out there? Anything to get it as close as possible would be appreciated. Edited May 1, 2019 by MajorCooke Link to comment Share on other sites More sharing options...
Coffee Pancake Posted May 1, 2019 Share Posted May 1, 2019 It's impossible. LSL can never know the state of an animation playing on the client. There is an indeterminate about of time between the the script saying "play this anim" or "play this sound" and either events actually happening in the client. Load times, latency, etc etc. The best you can do is time your sound effects to match the speed of the animation as played, aim for ideal conditions (both sounds and anim are loaded and ready to be played AND the latency for both instructions is the same) and hope for the best. 1 Link to comment Share on other sites More sharing options...
Kyrah Abattoir Posted May 1, 2019 Share Posted May 1, 2019 You can't "measure" it per say, but when a non-looping animation ends it will be removed from llGetAnimationList(). However the keys returned by this function do not correspond to animation asset UUIDs so you'll have to deal with that too. I understand what you're trying to do but you're fundamentally trying to synchronise server side with something that is purely client side and not synchronised across clients. 2 Link to comment Share on other sites More sharing options...
Coffee Pancake Posted May 1, 2019 Share Posted May 1, 2019 Scripts asking the server "is animation playing" / "whats the avatar doing" often enough to work smoothly is kind of why LL went to the trouble of adding AO functionality in the first place. Link to comment Share on other sites More sharing options...
MajorCooke Posted May 1, 2019 Author Share Posted May 1, 2019 Then that's what I'd like to do. How would I go about doing this? Particularly I'd like to start with the walking animation. I should note I learn best by examples with explanations. Link to comment Share on other sites More sharing options...
Mollymews Posted May 1, 2019 Share Posted May 1, 2019 (edited) 9 hours ago, MajorCooke said: Then that's what I'd like to do. How would I go about doing this? Particularly I'd like to start with the walking animation. I should note I learn best by examples with explanations. this is not an easy problem and there is no total solution to it. The main obstacle is that we can't make our script run in constant time on the server. Best we can do is try to ameliorate matters by knowing the server dilation time (how slower than the standard 1.0 is the server running). http://wiki.secondlife.com/wiki/LlGetRegionTimeDilation. 1.0 dilation equates to 45 server frames a second our walking animation is running client side in constant time (30 frames a second typically). Lag caused by network data traffic excepted. Nothing can be done from LSL about network lag Proceeding then some arithmetic: 1.0 / 30 * 45 = 1.5. Or more simply 2 client side animation frames for every 3 server side frames If we don't have access in RL to the animation file then we use our eyes and a stopwatch to get the time for each walking stride. From this we work out the number of animation frames for the stride. Lets say we calculate 3 client-side animation frames per stride with this information we get the following: 1.5 * 3.0 = 4.5. 4.5 server frames for each stride when the server is running at 1.0 dilation. knowing this we then can set llSetTimerEvent() to some proportion of this. 1.0 / 45 * 4.5 = 0.1 seconds basically when the server is lagging then we try to muscle the server event queue so our script timer event gets called proportionately sooner state_entry() { llSetTimerEvent(0.1); } timer() { // ... play our effect ... llSetTimerEvent(llGetRegionTimeDilation() / 45 * 4.5); } ps. add as wrote this is just the basic beginning of how this can be ameliorated. We can do further amelioration (adjusting for spikes and dips - smoothing) by using a queue. Queue in this case meaning putting the last x number of dilations into a list. Removing the oldest dilation and adding the latest dilation. Then setting the next timer event to an average of the queue Edited May 1, 2019 by Mollymews ps add 1 Link to comment Share on other sites More sharing options...
Coffee Pancake Posted May 1, 2019 Share Posted May 1, 2019 4 hours ago, Mollymews said: basically when the server is lagging then we try to muscle the server event queue so our script timer event gets called proportionately sooner For a vanity effect most wont even hear because they turn sl sounds off. Link to comment Share on other sites More sharing options...
MajorCooke Posted May 1, 2019 Author Share Posted May 1, 2019 (edited) Okay, @Mollymews I get the last part but I don't know how to write it for SL. I've been trying to learn it but this is syntax I've never worked with before, and I thought LUA was rough. Would you mind helping me adapt the current code I have for it? As for the what you wrote above, I take it I can just put that in my code and replace the current SetTimerEvent I have already? I clocked the animation stride to be roughly 0.55 seconds between the steps. @CoffeeDujour Understandable, but the folks I hang out with, they rather enjoy it. Quite a lot of them. Edited May 1, 2019 by MajorCooke Link to comment Share on other sites More sharing options...
Profaitchikenz Haiku Posted May 1, 2019 Share Posted May 1, 2019 9 minutes ago, MajorCooke said: this is syntax I've never worked with before It's pretty much the same as C/java languages. What you may need to study is the events, since most of the interesting things happen in response to an event being triggered (notified to your script by the server). It isn't predictable, you can't assume that a touch event will occur in your script at a set number of milliseconds after the user touches the scripted item. The other issue, clientside versus serverside has already been mentioned. Link to comment Share on other sites More sharing options...
MajorCooke Posted May 1, 2019 Author Share Posted May 1, 2019 (edited) Yeah. I get that much, which is why I was considering having some form of change to the script where instead of the body itself doing the animation when walking/running, a script detects if moving and letting that both change the animation and do the playing sound... if that's at all possible. Then at least it can try to be a little more concise. Is that possible? Or as a last resort, I upload a custom looping variant of the steps that I loop and monitor for possible desyncing and, every X seconds, stop the loop and restart it in order to bring it back in line using the dilation @Mollymews suggested. I've already tweaked the audio to Hell and back to ensure it's as consistent as possible so that part's been taken care of, as I recorded the character strolling and used Premiere Pro to align the audio clips. But I certainly want that to be a last resort because that requires using lindens. While I have some, I cannot afford mistakes. @Mollymews Also, should I be using http://wiki.secondlife.com/wiki/LlGetRegionFPS as part of it? Since that can certainly have an effect, I've been told by a friend, do you recommend I plug that in for the 45 of your code? Edited May 1, 2019 by MajorCooke Link to comment Share on other sites More sharing options...
Kyrah Abattoir Posted May 1, 2019 Share Posted May 1, 2019 Sidenote, i believe that most of the good footstep gadgets out there don't actually care about the animation that is playing, the velocity of the avatar is what drives the footstep frequency. 1 Link to comment Share on other sites More sharing options...
MajorCooke Posted May 1, 2019 Author Share Posted May 1, 2019 (edited) I was just about to ask you, actually, what would you use in place of llSleep? Just llSetTimerEvent? Also, the animation I have is not controlled by speed. Where can I view some of those footstep gadgets? And, is it possible to change the AO I have to work based on velocity? Edited May 1, 2019 by MajorCooke Link to comment Share on other sites More sharing options...
MajorCooke Posted May 1, 2019 Author Share Posted May 1, 2019 Okay. Stepping back and thinking about this for a moment, it's not so much the desyncing happening between animation and sounds that bothers me, so much as the sounds themselves. There's a lot that could be fixed here. I am not caring so much about syncing it with the animation directly, so much as playing them without them being delayed rather sporadically. I think, if I addressed this issue, then that could make enough of a difference. 1 Link to comment Share on other sites More sharing options...
MajorCooke Posted May 1, 2019 Author Share Posted May 1, 2019 Okay, so after doing a lot of experimentation, what I came up with is a lot more feasible. float timerevent = 0.5615; float sleeper = 0.2; float vol = 0.8; float delaytime = 0.30; integer delay = TRUE; default { on_rez(integer start_param) { llResetScript(); } state_entry() { integer agentinfo = llGetAgentInfo(llGetOwner()); llSetTimerEvent(sleeper); delay = TRUE; } timer() { integer agentinfo = llGetAgentInfo(llGetOwner()); if (agentinfo & AGENT_WALKING) { // Add a small delay because it takes this long for the foot to make // contact with the ground when transitioning from normal to this. if (delay) { llSetTimerEvent(delaytime); delay = FALSE; } else { if (agentinfo & AGENT_ALWAYS_RUN) { llTriggerSound("6559cdbf-a664-d93c-184e-42d95a965104", 1.0); } else { // Since the object is an attachment, play is fine. llPlaySound("6559cdbf-a664-d93c-184e-42d95a965104", vol); //llTriggerSound("4c19068e-38ae-f3a9-21a3-630a59d62a31", 0.4); } llSetTimerEvent(timerevent); } } else { delay = TRUE; llSetTimerEvent(sleeper); } } } Something amusing I found out... llTriggerSound is susceptible to a small delay - and this is primarily a guess, but after having worked with some game engines in the past, I think it's safe to say: because it spawns a temporary object. At least, that's what the engine I fiddled around with the most did. It spawned an object to play the sound, and then destroyed itself immediately afterwards which means it's subjected to more networking stuff than that of llPlaySound. Considering this is an attachment at any rate doing the sound playing, I don't need to worry about occupying the objects sound channel - in fact it's wide open for use. Furthermore, using llSetTimeredEvent definitely seemed to help a little as well, and while it's still not perfect, it at least won't go completely out of whack in more populated areas and won't screw up the rest of the timing, which apparently llSleep was doing for the script. Not perfect, but still a LOT better than what it used to be. I'll continue expanding upon this as time goes on. 1 Link to comment Share on other sites More sharing options...
Coffee Pancake Posted May 1, 2019 Share Posted May 1, 2019 54 minutes ago, MajorCooke said: Something amusing I found out... llTriggerSound is susceptible to a small delay - and this is primarily a guess, but after having worked with some game engines in the past, I think it's safe to say: because it spawns a temporary object. Don't forget there is a delay between the script command to play a script, that being translated to a command for the viewer, and that in turn being sent down the wire to the client. Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now