Functions are not to be used as arguments for other functions.

I have found own.applyMovement to be unreliable, (sometimes it just fail to do anything)

I have found own.worldPosition+=offset works well for global

and

own.worldPosition= own.worldPosition+(own.worldOrientation*Vector([x,y,z]))

works fine for local

cheers.

Edit:

Ok, I will say this

I know that I don’t know why this does not always work…

You’ll need to post an example of it failing. It’s such a simple command it’s far more likely your scripts aren’t doing what you expect them to do.

check the video,

applyMovement does not always work…

own.applyMovement((own.getDistanceTo(ray[1]),0,0),1)

did not work

own.worldPosition=own.worldPosition+(own.worldOrientation.col[0]*own.getDistanceTo(ray[1]))

works just fine :smiley:

Recreation
I was not able to reproduce the behavior you describe. So I can’t tell what your exact situation is.

Analysis
You do a lot of things that are not necessary. That might implement some unwanted side-effects. When you want to let the arrow stuck I think all you need is:

  • place the arrow at the hit position (via setWorldPosition)
  • parent the arrow to the hit object (via setParent) [this makes the object static already = no velocities]

Especially the last point has a lot of redundancies in your implementation. But I would say they should not harm.

Conditions:
You have two expressions with the same code [not “done” in own]. Your condition check does not benefit from that. I suggest you move it to an outer condition check:


if not "done" in own:
   if ray[0]:
   else:

Naming
Additionally I suggest to avoid “ray[0]”. While it reduces the code to a minimum it still reminds my on the cryptic notation of accountants ;). I recommend to name it hitObject as this expresses what it is rather than ray[0].
e.g.


hitObject, hitPosition, hitNormal = rayCast(...

Disabling arrows
From what I see you do not even need the property “done”. I guess this arrow stuck just one time. I do not see the logic at your arrow object (because you selected the cube rather than the arrow). So I assume you have following logic:

ray sensor -> python controller.

supposed to stuck the arrow when the ray triggers.

To make this more efficient especially after you fired really a lot of arrows, it would be nice to avoid any running controllers and any evaluated ray sensors on the already hit arrows.

Option A)
Replace the complete object. As you replace the mesh and completely change the arrows behavior, I think this is the bests option in your situation.


if hitObject:
    owner.worldPosition = hitPosition
    stuckArrow = scene.addObject("stuckArrow", owner)
    stuckArrow.setParent(hitObject)
    owner.endObject()

Option B)
Switch state. This way the sensor and the controller are completely disabled and do not waste any time. You can do that via state actuator or via Python.

I hope it helps somehow
Monster

I think it’s because I passed ray[1] as a argument to a function, where as

own.worldPosition is setting a value directly ?

own.applyMovement(vector,flag)

vs

own.setPostion = vector

set/get is different then referencing a function right?

I modified Nines script btw, I did not setup the ‘Done’ etc,

swapping to a ‘dead arrow’ would also be acceptable right?

(instead of moving self to arrow ray hit spot, add new arrow that is a dummy?)

or better yet, add a arrow that is retrievable :smiley:

Confirmed - if I used

D= own.getDistanceTo(ray[1])

own.applyMovement((D,0,0),1) it works just fine,

apparently you can’t always pass a function as a argument?

As usually I do not get what you mean.

You can pass a function as parameter to a function call.



def myFunction(myParameter):
   print("called myFunction with", myParameter)

def callFunction(functionToCall):
   functionToCall("parameter")

callFunction(myFunction)


This works as functions are objects too.

The difference between function and return value is the syntax


def createReturnValue():
   return "return value"

# the ( ) make the difference
function = createReturnValue 
returnValue  = createReturnValue() 

print("function", function )
print("return value:", returnValue  ) 

Just be careful to check that ray[1] is not None. You can’t get distance to a None object, so that function would fail causing the other function to fail in turn.
After casting a ray I always check “if hitObject”, since otherwise further code can’t continue.

I do if ray[0] above the code posted here,

it all works nice now,

it’s in resources , I love having fast moving physics items working in the bge,

I hear there is a constraint to do CCD , (I assumed it was all CCD but apparently it’s not?)

You’re not passing a function to a function, you’re passing a function result (a variable) to a function. It makes no difference to the interpreter where you do this (besides the fact that exceptions would bail earlier).

strange, I dont know then,

its only apply rotation, and apply movement that seem to do this occasionally…

It’s because whatever you’re passing in is not valid. Read the Python Console.

it throws no errors

own.applyMovment((own.getDistanceTo(ray[1]),0,0),1)

iz codez.

For good code practice and readability, you really want to do something like…


dist = own.getDistanceTo(Ray[1])
own.applyMovement([dist,0,0],1)

That is providing that Ray[1] is a set of coordinates.

With no code I can’t test this. But, it’s very likely something you’re doing, as the API is well tested. Just use a print statement to verify what’s going in, and determine if that’s what you expected.