Random function with interval

Hi folks! I’m curious how to create an interval that refreshes my random function each N second.
In my project, I have an object falling on the user’s head and I want to set some random rotation on Y-axis. Also, I want to lock the axis that the falling object always falls from the top.

For now the object always fall from top and rotation position is update by lens refresh.

My script

// -----JS CODE-----
// @input SceneObject source
// @input SceneObject target
// @input bool lockX
// @input bool lockY
// @input bool lockZ

var targetRotation = script.target.getTransform().getWorldRotation().toEulerAngles();


function GetRandomFloat(min, max) {
    return Math.random() * ((max) - min) + min;
}

var randomNumber = GetRandomFloat(-360, 360);

var delayedEvent = script.createEvent("DelayedCallbackEvent");
delayedEvent.bind(function(GetRandomFloat)
{
    print("delay is over");
});
delayedEvent.reset(1);
print("delay has started");



script.createEvent("UpdateEvent").bind(function() {
var sourceRotation = script.source.getTransform().getWorldRotation().toEulerAngles();

var xRot = script.lockX ? targetRotation.x : sourceRotation.x;
var yRot = script.lockY ? targetRotation.y : sourceRotation.y;
var zRot = script.lockZ ? targetRotation.z : sourceRotation.z;
var newRotation = quat.fromEulerAngles(xRot, yRot+randomNumber, zRot);
script.target.getTransform().setWorldRotation(newRotation);
});

scene

This is pretty close. All you really need to do is add a delayedEvent.reset(1) inside the function bound to the delayed event. I’ll also point out that the argument inside the function comes from the delayed event, don’t put the name of your randomizing function there otherwise it will be overwritten (JavaScript scope).

Here’s a working example of the 1 second delay part. Hopefully it formats correctly.

// -----JS CODE-----
function GetRandomFloat(min, max) {
    return Math.random() * ((max) - min) + min;
}

var delayedEvent = script.createEvent("DelayedCallbackEvent");
delayedEvent.bind(function()
{
    print(GetRandomFloat(0, 10));
    delayedEvent.reset(1);
    print('delay is resetting');
});
delayedEvent.reset(1);
print("delay has started");
1 Like

Now is logger show me updates

But, somehow the position doesn’t change =(

not sure I get this one, maybe the problem in this one?

I’ll also point out that the argument inside the function comes from the delayed event, don’t put the name of your randomizing function there otherwise it will be overwritten (JavaScript scope).

// -----JS CODE-----
// @input SceneObject source
// @input SceneObject target
// @input bool lockX
// @input bool lockY
// @input bool lockZ

var targetRotation = script.target.getTransform().getWorldRotation().toEulerAngles();

var randomNum = GetRandomFloat();

function GetRandomFloat(min, max) {
    return Math.random() * ((max) - min) + min;
}

var delayedEvent = script.createEvent("DelayedCallbackEvent");
delayedEvent.bind(function()
{
    print(GetRandomFloat(0, 360));
    delayedEvent.reset(1);
    print('delay is resetting');
});
delayedEvent.reset(1);
print("delay has started");


script.createEvent("UpdateEvent").bind(function() {
var sourceRotation = script.source.getTransform().getWorldRotation().toEulerAngles();

var xRot = script.lockX ? targetRotation.x : sourceRotation.x;
var yRot = script.lockY ? targetRotation.y : sourceRotation.y;
var zRot = script.lockZ ? targetRotation.z : sourceRotation.z;
var newRotation = quat.fromEulerAngles(xRot, yRot+randomNum, zRot);
script.target.getTransform().setWorldRotation(newRotation);
});

You are never assigning randomNum to a new random number. You need to add randomNum = GetRandomFloat(0, 360); inside the delayed event block if you want to keep updating that number.

1 Like

I got it, but after that ive got error

This is a scope issue. You are defining randomNum inside the delay callback, which is a different scope than the update callback. Really though, you shouldn’t be updating the rotation on every frame, rather only when the rotation changes. You can delete the update event and just put all that inside of the delay callback and you won’t have scoping issues (and performance will be better)

1 Like

Yay! Now it’s work! Thank you, guys! :heart:

Here is correct script

// -----JS CODE-----
// @input SceneObject source
// @input SceneObject target
// @input bool lockX
// @input bool lockY
// @input bool lockZ

var targetRotation = script.target.getTransform().getWorldRotation().toEulerAngles();

function GetRandomFloat(min, max) {
    return Math.random() * ((max) - min) + min;
}

var delayedEvent = script.createEvent("DelayedCallbackEvent");
delayedEvent.bind(function()
{
    var randomNum = GetRandomFloat(0, 360); 
    //print(GetRandomFloat(0, 360));
    delayedEvent.reset(1);
    print('delay is resetting');
    var sourceRotation = script.source.getTransform().getWorldRotation().toEulerAngles();

var xRot = script.lockX ? targetRotation.x : sourceRotation.x;
var yRot = script.lockY ? targetRotation.y : sourceRotation.y;
var zRot = script.lockZ ? targetRotation.z : sourceRotation.z;
var newRotation = quat.fromEulerAngles(xRot, yRot+randomNum, zRot);
script.target.getTransform().setWorldRotation(newRotation);
});
delayedEvent.reset(1);
print("delay has started");
1 Like

Hmmm. For now I figured out that the object is not falling from the top when you turn or tilt your head.
So I decide to lock main object and add Null object which I can rotate by Y-axis with random Number.

But, im now stumped with the next issue:

Script:

// @input SceneObject target

var rot = script.target.getTransform().getWorldRotation();

function GetRandomFloat(min, max) {
    return Math.random() * ((max) - min) + min;
}

var delayedEvent = script.createEvent("DelayedCallbackEvent");
delayedEvent.bind(function()
{
    var randomNum = GetRandomFloat(0, 360); 
    delayedEvent.reset(3);
    print('delay is resetting');
    
var xRot = rot.x;
var yRot = rot.y;
var zRot = rot.z;
var newRotation = vec3(xRot, yRot+randomNum, zRot);
script.target.setWorldRotation(newRotation);
    
});
delayedEvent.reset(3);
print("delay has started");

I think it wants you to use new vec3(...)

1 Like

22:45:16 [Scenarium] TypeError: undefined not callable (property ‘setWorldRotation’ of [object Object])
at [anon] (Random rotation 2.js:19) preventsyield

Maybe this needs to be script.target.getTransform().setWorldRotation(newRotation)

1 Like

17:22:26 [Scenarium] Error: Argument 0: Incorrect native object type
at [anon] () native strict preventsyield
at [anon] (Random rotation 2.js:20) preventsyield

strange things =(

Maybe it’s expecting a quaternion?

1 Like

Solved

// @input SceneObject target

function GetRandomFloat(min, max) {
    return Math.random() * ((max) - min) + min;
}

var delayedEvent = script.createEvent("DelayedCallbackEvent");
delayedEvent.bind(function()
{
    var randomNum = GetRandomFloat(0, 360); 
    delayedEvent.reset(3);
    print('delay is resetting');


var rot = script.target.getTransform().getWorldRotation().toEulerAngles();
var x = rot.x;
var y = rot.y;
var z = randomNum;
    
var newRotation = quat.fromEulerAngles(x,y,z);

// Set the object's world rotation to the new rotation
script.target.getTransform().setWorldRotation(newRotation);
    
});
delayedEvent.reset(3);
print("delay has started");

1 Like

Okey. I adapting the script for more user friendly style :slight_smile:

// @input SceneObject obj
// @input float From 
// @input float To
// @input int delay = 1
// @input int every = 1
// @input bool randomX
// @input bool randomY
// @input bool randomZ

    var from = script.From;
    var to = script.To;
    var delay = script.delay;
    var every = script.every;

function GetRandomFloat(min, max) {
    return Math.random() * ((max) - min) + min;
}

var delayedEvent = script.createEvent("DelayedCallbackEvent");
delayedEvent.bind(function()
{

    var randomNum = GetRandomFloat(from, to); 
    delayedEvent.reset(every);
    print('delay is resetting');


var rot = script.obj.getTransform().getWorldRotation().toEulerAngles();
var x = 0.0;
var y = 0.0;
var z = 0.0;  
    if(script.randomX) {
        x = randomNum;
    }
    
    if(script.randomY) {
        y = randomNum;
    }
    
    if(script.randomZ) {
        z = randomNum;
    }

    var newRotation = quat.fromEulerAngles(x,y,z);

// Set the object's world rotation to the new rotation
script.obj.getTransform().setWorldRotation(newRotation);
    
});
delayedEvent.reset(delay);
print("delay has started");

If anyone has a suggestion to optimize this code it would be great

1 Like