Added objects lag behind when created

Hi all

When I create an object when the spawning object is travelling at speed, the added object lags behind, for what looks like 1 frame.

What I don’t understand is that I thought added objects inherited the speed of the spawning object. So if a gunbarrel travels at 300 b/u’s then added objects (in this case a muzzleflash) travel at the same rate.

Here is the code I am using, as far as I can see nothing is too out of the ordinary:


 
import bge

def Cannon(cont):
    
    scene = bge.logic.getCurrentScene()    
    Cannon_barrel = cont.owner      
    Turret = Cannon_barrel.parent
    cannonHelper = [i for i in Cannon_barrel.children if "Cannon" in i]    
    cannonRay = cannonHelper[0].sensors["Ray"]
    cannonRadar = cannonHelper[0].sensors["cannonRadar"]
    currentSpeed = Cannon_barrel.getLinearVelocity(True)
    
    if Turret["lapNumber"] and Turret["lapNumber"] > 0 and Turret["const"].valid():    
        print(currentSpeed)        
        if cannonRadar.positive and Cannon_barrel["ammunition"] > 0:                      
            muzzleflash = scene.addObject('generic_gunShot', cannonHelper[0], 2)
            Cannon_barrel["ammunition"] -=1     
        
        if cannonRay.positive and cannonRadar.positive and Cannon_barrel["ammunition"] > 0:
            
            pos = cannonRay.hitPosition            
            Cannon_barrel["ammunition"] -= 1 
            added = scene.addObject('generic_hit', cannonHelper[0], 1)
            added.worldPosition = pos
            muzzleflash = scene.addObject('generic_gunShot', cannonHelper[0], 2)
            shipHit = cannonRay.hitObject
            if shipHit["health"] and shipHit["health"] > 0:
                shipHit["health"] -= 1
                shipHit["weapon_hit_toggle"] = True
                       
        if Cannon_barrel["ammunition"] <= 0:   
            Cannon_barrel["ammunition"] = 0

It just seems that the object is added too late… attached is a screenshot of what I mean:

Any thoughts?

Cheers

Paul

Attachments


No the added object does not receive the velocities from the “other” object. It inherits the transformations (pos/rot/scale) only.

You need to copy the velocities manually.

Hi Monster!

I have modified the code to this:


 
import bge

def Cannon(cont):
    
    scene = bge.logic.getCurrentScene()    
    Cannon_barrel = cont.owner      
    Turret = Cannon_barrel.parent
    cannonHelper = [i for i in Cannon_barrel.children if "Cannon" in i]    
    cannonRay = cannonHelper[0].sensors["Ray"]
    cannonRadar = cannonHelper[0].sensors["cannonRadar"]
    currentSpeed = cannonHelper[0].getLinearVelocity(True)[1]
    
    if Turret["lapNumber"] and Turret["lapNumber"] > 0 and Turret["const"].valid():           
        if cannonRadar.positive and Cannon_barrel["ammunition"] > 0:                      
            muzzleflash = scene.addObject('generic_gunShot', cannonHelper[0], 2)
            muzzleflash.setLinearVelocity([0,(currentSpeed + 20),0],1)
            Cannon_barrel["ammunition"] -=1     
        
        if cannonRay.positive and cannonRadar.positive and Cannon_barrel["ammunition"] > 0:
            
            pos = cannonRay.hitPosition            
            Cannon_barrel["ammunition"] -= 1 
            added = scene.addObject('generic_hit', cannonHelper[0], 1)
            added.worldPosition = pos
            muzzleflash = scene.addObject('generic_gunShot', cannonHelper[0], 2)
            muzzleflash.setLinearVelocity([0,(currentSpeed + 20),0],1)
            shipHit = cannonRay.hitObject
            if shipHit["health"] and shipHit["health"] > 0:
                shipHit["health"] -= 1
                shipHit["weapon_hit_toggle"] = True
                       
        if Cannon_barrel["ammunition"] <= 0:   
            Cannon_barrel["ammunition"] = 0

But the same thing happens (i.e. lag). How should I set the velocity?

Are the objects that are added Dynamic or Rigid Body? Linear Velocity can’t be used on No Collision or Static objects.

I agree with SolarLune.

The next thing is if cannonHelper[0] is not dynamic it has no velocity either. But I guess it has as you print the “speed”.

Some Remarks:

  • Try to avoid writing the exactly same code multiple times. I think you already recognized this produced a lot of additional work.
    Alternatives:
    –> Add a function and call the function
    –> re-desing the conditions (they are replicated as well)

  • using the sensors of another object is pretty dangerous better run the script at the “cannonHelper” (better call it cannonControl or something like that)

  • the conditions are to complex and therefore hard to read

  • do not read the list all the time for the exact same element (this is heavier than reading it once and cache it in a variable).

redesigned (and renamed identifier according to PEP008):


 
import bge

def cannon(cont): 
    
   scene = bge.logic.getCurrentScene()    
   cannon_barrel = cont.owner      

   muzzleEmitters = [i for i in cannon_barrel.children if "Cannon" in i]   
   muzzleEmitter = muzzleEmitters[0]

   cannonRay = muzzleEmitter .sensors["Ray"] 
   cannonRadar = muzzleEmitter .sensors["cannonRadar"] 
    
   if not Turret["lapNumber"]:
      return
   if Turret["lapNumber"] < 0:
      return

   if not Turret["const"].valid():    
      return
       
   if (not cannonRadar.positive or 
       not cannon_barrel["ammunition"] > 0):
      return
   

   muzzleflash = scene.addObject('generic_gunShot', muzzleEmitter, 2)
   muzzleflash.setLinearVelocity(muzzleEmitter.getLinearVelocity(True),1)
   cannon_barrel["ammunition"] -=1     
        
   if cannonRadar.positive:            
      hitPosition = cannonRay.hitPosition            
      cannon_barrel["ammunition"] -= 1 # dangerous you have decreased this value already

      hitVisualization = scene.addObject('generic_hit', cannonHelper[0], 1)
      hitVisualization.worldPosition = hitPosition 

   hitShip= cannonRay.hitObject

   health = hitShip["health"]
   if (health > 0):
      hitShip["health"] = health - 1
      hitShip["weapon_hit_toggle"] = True
                       
   if cannon_barrel["ammunition"] < 0:   # shouldn't be necessary
      cannon_barrel["ammunition"] = 0

This code is untested, but should give you an idea
First it test for all conditions when the code should not proceed. The conditions are the opposite to your conditions. Indeed you can merge them to larger “if” statements.

Only perform processing when it is needed (e.g. reading linear velocity ;))

Hi guys- you are both right that the muzzle flash is not dynamic- it is just a shape set to no collision as anything else blocks the raycast used to ‘shoot’ through it and hit the target (ghosted objects still receive raycasts). I imagine I will have to re-arrange things or find a new effect.

Monster, why is it dangerous to access sensors from another object? I have to communicate via the parent/child method as my vehicles use several parts (for example the cannon uses six pieces), messages would be more complex, and I wish to avoid globalDict if I can. Since the object that has the sensor is accessed via a list (since the cannon could be duplicated on another racing ship) does this negate any problems? If I kept this as it was, what could /would happen?

Cheers

Paul

It is in that way dangerous as you run logic by one object but you look for events at another one. As you see this is possible. But it is very confusing as there is no obvious relationship between them.

As you do not even touch the sensors of the other object it wiuld
make sense to run the controller from the object with the sensor.
You have to search for the other object anyway.

This enables you to use the sensors to trigger the Python controller when the sensors detect changes. this increases performance.
Additional you can easily see the relationship between the Sensors and controllers at the GUI. This increases reada ility and prevents hard to discover side effects.

Try to make your code as less dependent to other objects (game objects, sensors, etc.) as possible. If you have dependencies try to make it as obvious as possible.

This will help you when your game is growing. Keep in mind you cant hold every detail in your head. Therefore it is good to makeit as readable aspossible.

I see- so is it better to have one sensor (radar or near) that feeds several functions (detecting other objects, collision avoidance etc) or have a radar/ near sensor for each, or is there no net benefit as long as the sensor is not triggered unnecessarily?

Sensors are always evaluated. (…but you can deactivate them with a state switch.) The evaluation eats processing time. Therefore as less sensors you have at the same time as better it is performance-wise.

If you have multiple sensors checking for exactly the same results it is better to use only one of them. Otherwise they do exactly the same work … multiple time. (This is not only true on sensors, it is also true on code).
There might be good reasons to ignore the performance and continue with multiple sensors. This needs to be decided for each situation.

From your code I can see you have a radar and a ray. They both do differentiated things. From first sight this looks ok. Without more details it is hard to guess if one of them is obsolete or not.

What I meant with my above code is:
A sensor of one object should be checked from a connected controller (as this is what a reader would expect when looking at the GUI … and the code).
Please keep in mind, sensors without a connected controller will not be evaluated or in worst case not even exist in the BGE. The above design can easily produce these situations. Therefore it is dangerous.

One last question (I promise;) )

How would you code a system that exchanges information between objects inside a group?

Since this group of objects can be duplicated in any number I avoided globalDict, and I would have to make any sent message unique (which is possible since I have something similar working already). Creating lists is handy as it (the duplicated parent) searches for any connected children, ensuring each group does not trigger each other.

Was I wrong to take the approach I did, or am I underestimating the capabilities of messages and globalDict?

No you approach was fine. You searched through the parent/child tree. This is one of the options to do that.

A) parenting -> parent the objects of the group together (not always applicable) then parse through the tree
B) interobject connection -> connect logic bricks of different objects together (can easily produce ugly and complicated structures)
C) combination of both
D) other

You can have a look at LinkLib (see my signature) it uses the uses the parenting method as well.