Jump to content

collision issues


testgenord1
 Share

You are about to reply to a thread that has been inactive for 1005 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hi!
I've had two issues with collision events that I couldn't figure out.
Maybe you guys can help me with this.

This is issue number 1:

When an avatar flies through an object, an event is supposed to be triggered.
However, the script first works for some time but then stops working with the particular avatar.
I couldn't find out why.
The script looks as follows (it's a standard script):

default
{
    state_entry()
    {
        llVolumeDetect(TRUE); // Starts llVolumeDetect
    }
    collision_start(integer total_number)
    {
        llSay(0, "Detected!"); // Tells you when something penetrates the prim
    }
}

I had to completeley get rid of llVolumeDetect to make it work.


issue number 2:

When an avatar walks or falls onto an object, the object is supposed to become alpha and phantom.
The script works at first, but at the second collison with the same avatar, it doesn't work any more.

This only seems to be the case with a "collision" event.
"collision_start" doesn't seem to cause that issue.

Do you maybe have some ideas of why this could be?
 

(What is the difference between "collision" and "collision_start" anyway?)


Thank you very much in advance!


This is the script:

float idle = 5.0;
key user;
string nplayer;

default
{
    state_entry()
    {
        llSetLinkPrimitiveParamsFast(2, [
        PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 0.0>, 1.0,
        PRIM_PHANTOM, FALSE,
        PRIM_LINK_TARGET,1,
        PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 1.0
        ]);
    }
    collision(integer num_detected)
    {
        user = llDetectedKey(0);
        nplayer = llDetectedName(0);
        state phantom;
    }
}
state phantom
{
    state_entry()
    {
        llRegionSayTo(user,0,"Hi, " + nplayer);
        llSetLinkPrimitiveParamsFast(2,[
        PRIM_COLOR, ALL_SIDES, ZERO_VECTOR, 0.0,
        PRIM_PHANTOM,TRUE,
        PRIM_LINK_TARGET,1,
        PRIM_COLOR, ALL_SIDES, ZERO_VECTOR, 0.0]);
        llSleep(idle);
        llResetScript();
    }
}

 

Link to comment
Share on other sites

A collision_start event is triggered when something starts colliding with the object.  A collision _end event is triggered when something stops colliding with it.  A collision event is triggered as long as something is still colliding with the object.  You very rarely want to use a collision event.

Your full script is failing because you have used a collision event, which immediately throws execution to state phantom and then, 5 seconds later, resets the entire script.  But of course you are still in contact with the object, so execution immediately goes again to state phantom, and so on and on and on....  So, aside from needing a collision_start event there, you really don't want to reset the script at all.  You want to wait until the colliding person stops colliding (using a collision_end event), and then you simply want to return to state default.

Returning to your first question, time in SL is cut into frames, 45 per second.  A fast moving object can make it all the way through a thin phantom collision prim in one frame, so that your script doesn't detect any collision at all.  The way to beat that is to either (1) make the collision prim thicker or (2) fly through it slower.   Or, maybe, put a second detector right after the first and only pay attention to the signal from it if there was no signal from the first one.

 

  • Like 1
Link to comment
Share on other sites

Thank you so much for your help!

This was a lot of new information for me. 👍

It seems to have solved both issues. 🙂

 

Maybe one more question:

What advantage exactly is there in going back to state default compared to resetting the script?
I guess the main advantage is that going back to state default is more memory / server friendly than resetting the script completely?

Link to comment
Share on other sites

1 hour ago, testgenord1 said:

What advantage exactly is there in going back to state default compared to resetting the script?

You retain the values stored in global variables which would otherwise be reset

As far as memory goes states do grab a bit more memory.

 

Edited by Profaitchikenz Haiku
  • Like 1
Link to comment
Share on other sites

A script with more than the default state will need a bit more memory allocated when it compiles. However, this isn't large enough to justify a reset instead.

What I don't know, (and this is an @Wulfie Reanimator @Quistess Alpha @Mollymews type issue) is whether more server time or resources are consumed when fully resetting a script compared to simply switching from one state to another.

 

In your example though, I would probably have one state, and use a timer event to trigger the transitions between phantom and non-phantom.

There would be a variable timerAction which would be set to either "phantom" or "non-phantom", and when the timer event occurs, the value of that variable controls what it does.

Having done it, part of is action is to then clean up, if it was "phantom" it has to change timerAction to "non-phantom" and then set the timer event for how long the phantom state is to persist.

If it was "non-phantom" it changes the state back to non-phantom and sets the timer event to 0.0;

 

  • Like 2
Link to comment
Share on other sites

1 hour ago, Profaitchikenz Haiku said:

whether more server time or resources are consumed when fully resetting a script compared to simply switching from one state to another.

I don't know much about testing for resource use, but empirically speaking, resetting a script takes much longer (but still pretty short in the whole scheme of things) than changing states:

separate script for timing:

default
{
    link_message(integer SendersLink, integer Value, string Text, key ID)
    {
        llOwnerSay((string)llGetAndResetTime());
    }
}

3 scripts for testing:

/* // infinite loop (control test)
default
{
    state_entry()
    {
        while(TRUE)
        {
            llMessageLinked(LINK_THIS, 0, "", "");
            llSleep(1.0);
        }
    }
}*/

/* // whole script reset.
default
{
    state_entry()
    {
        llMessageLinked(LINK_THIS, 0, "", "");
        llSleep(1.0);
        llResetScript();
    }
}
*/

/* // state change
default
{
    state_entry()
    {
        llMessageLinked(LINK_THIS, 0, "", "");
        llSleep(1.0);
        state alternate;
    }
}
state alternate
{   
    state_entry()
    {
        llMessageLinked(LINK_THIS, 0, "", "");
        llSleep(1.0);
        state default;
    }
}
*/

 

  • Doing litterally nothing in a loop shouldn't take any time, but by my testing apparatus, usually takes -1,0 or 1 frames (1 frame is 0.022 seconds). (not sure why it sometimes doesn't sleep the whole time it's asked to. . .)
  • a Whole script reset usually takes 1 or 2 frames, sometimes 3 on a rare occasion.
  • a State change takes 0 or 1 frame, sometimes reporting extremely low times. I'm almost tempted to say it does better than the control test.
Edited by Quistess Alpha
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

I improved my methodology . . .

Quote

(quotes compact for less spam)

Timer script

float average;
integer number;
default
{
    link_message(integer SendersLink, integer Value, string Text, key ID)
    {
        if(Value==1)
        {   average=0;
            number=0;
            llOwnerSay("Reset");
            llResetTime();
        }
        else if(Value==2)
        {   llOwnerSay((string)average+"::"+(string)number);
        }
        else
        {
            float time = llGetAndResetTime();
            ++number;
            average *= (float)(number-1)/number;
            average +=time/number;
            if(!(number%50))
            {
                llOwnerSay((string)time+"::"+(string)average+"::"+(string)number);
                number = 0;
                average= 0;
            }
            //if(!(number%50)) llOwnerSay("Debug");
        }
    }
}
 // infinite loop (control test)
/*
default
{
    state_entry()
    {
        //integer i = 201; // more than 64 would break the stack.
        llMessageLinked(LINK_THIS, 1, "", "");
        while(TRUE)
        {
            llMessageLinked(LINK_THIS, 0, "", "");
            llSleep(0.1);
        }
        llMessageLinked(LINK_THIS, 2, "", "");
    }
}
*/
// script reset:
/*
default
{
    state_entry()
    {
        llMessageLinked(LINK_THIS, 0, "", "");
        llSleep(0.1);
        llResetScript();
    }
}
*/

// state change
/*
//integer i = 50;
default
{
    state_entry()
    {
        //i = 50;
        llMessageLinked(LINK_THIS, 2, "", "");
        llMessageLinked(LINK_THIS, 1, "", "");
        llSleep(0.5);
        state a;
    }
}
state a
{
    state_entry()
    {
        llMessageLinked(LINK_THIS, 0, "", "");
        //--i;
        llSleep(0.1);
       // if(!i) state default;
        state b;
    }
}
state b
{   
    state_entry()
    {
        llMessageLinked(LINK_THIS, 0, "", "");
        //--i;
        llSleep(0.1);
        //if(!i) state default;
        state a;
    }
}
*/

 

  • Infinite loop logic seems to take 0.0111 seconds,
  • Script reset seems to take 0.0485 seconds,
  • State change seems to take  0.0111 seconds.

state change and infinite loop are quite close. . .

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

The main advantage I can see to a reset is that it clears memory, apart from that, I can't see any real need to reset simple scripts. Should memory ever becme an issue then I'd suggest putting that little Garbage-collection forcer that Animats came up with into the state_entry of default.

  • Like 2
Link to comment
Share on other sites

11 hours ago, Profaitchikenz Haiku said:

little Garbage-collection forcer

That's only needed if you really need to know how much memory you have left. Which, in turn, is only useful if you can take corrective action. Releasing some historical data, such as a list of past visitors, would be an example.

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1005 days.

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
 Share

×
×
  • Create New...