one action for many objects - rayCastTo

Help and examples in this topic, there is free and extended help on BGE.
---------------------------------------------------------------------------------------------------------

Hello everyone.
I wrote something here, even funny to show - this is a simple flare scale. Of course, there is a more perfect script, as many people probably know - but it will suit me. In BGE API help, I already found and rayCastTo, and localScale…
That’s what I got - just everything is simple .

import bge


cont = bge.logic.getCurrentController()
own = cont.owner
scene = bge.logic.getCurrentScene()
obj = scene.objects['flare01']
flare = obj["flare"]
rayCast = own.rayCastTo(obj)


if not rayCast:
    obj.visible = 1
    dist = own.getDistanceTo(obj)
    if dist > flare:
        obj.localScale = (dist*0.2, dist*0.2, dist*0.2)
#    print(dist)        
else:
    obj.visible = 0

But here again I do not know how to apply everything to objects with the “flare” property. Help someone please solve this problem.
Example for clarity: flare_scale01.blend (550 KB)

Thank you for attention.

p.s. thanks to John Hamilton for the lesson about the nodes.

OK!
I scrolled a little bit of help, and on this forum - there were already such questions / solutions … and so I got it - clean code:


import bge

cont = bge.logic.getCurrentController()
own = cont.owner
scene = bge.logic.getCurrentScene()

for flare in scene.objects:
    if "flare" in flare:
        flareProp = flare["flare"]
        max = flare['flareDist']
        ray = own.rayCastTo(flare)
        if not ray:
            dist = own.getDistanceTo(flare)
            flare.visible = 1
            if dist > flareProp and dist < max:
                flare.localScale = (dist*0.2, dist*0.2, dist*0.2)
            
        else:
            flare.visible = 0
  • if I show the programmer my code, then he will ask - Nicolas, what is it - dist*0.2 :mad:? Probably professionals find professional solutions, and amateurs - are strange, but effective. The script works:D!

Example: flare_scale01.blend (550 KB)

p.s. sometimes there are very strange (unusual) solutions - thank Red Frost Games forinfinity

I found a flaw in this script - own [“flareDist”], should be equal to - Camera data\Divide (in NOD) - Value. Otherwise the scale will be with visual jump … although for me this is not a problem, it can then be eliminated.

No idea what you are doing with this piece:


 ray = own.rayCastTo(flare)
        if not ray:
            dist = own.getDistanceTo(flare)
            flare.visible = 1
            if dist > flareProp and dist < max:
                flare.localScale = (dist*0.2, dist*0.2, dist*0.2)
            
        else:
            flare.visible = 0

so if ray does not hit flare, get distance to that flare and set it visible. And when it hits the flare turn it invisible?
How can this work?

I assume you want it to change the visibility and scale when its in range and turn of visibility out of range?
try this:


def get_all_flares(cont):


    own             = cont.owner
    flare_list      = [obj for obj in own.scene.objects if 'flare' in obj]
    
    return flare_list




def do_stuff_with_flares(cont):
    
    own         = cont.owner
    flare_list  = get_all_flares(cont)
    
    if flare_list:
        
        for flare in flare_list:


            flareProp   = flare["flare"]
            max         = flare['flareDist']        
            dist        = own.getDistanceTo(flare)


            if dist >= flareProp and dist <= max:
                
                flare.visible       = 1
                flare.localScale    = (dist*0.2, dist*0.2, dist*0.2)
            
            else:
                flare.visible = 0
    else:
        print('No flares found in flare_list') 

you don’t even have to import anything. You dont even have to cast a ray, you already grabbing the object so you can directly ask for getDistanceTo() and use that to set a flare visible and it’s scale.

-You gave a piece of code in the example and asked - how does it work?
Well, I’ll try with my meager brains to describe how I thought when I wrote this script:

first I created a list of objects in the scene
for flare in scene.objects:
then I requested the conditions of the list - property availability “flare”
if “flare” in flare:
now I hit the properties for each object in the list, individually for each object
flareProp = flare[“flare”]
max = flare[‘flareDist’]
since, in the material settings, it is set to infinity (Z-offset), I send rays to each object in the list - flare
ray = own.rayCastTo(flare)
here I still have twisted the brains - according to my logic it is necessary to put - if ray. Well, after my experiments, I realized that I had to - “not”
if not ray:
If the above conditions are met, I get a distance to each object in the list
dist = own.getDistanceTo(flare)
then turn on their visibility
flare.visible = 1
Further, under conditions of certain distances, my experimental zooming goes on
if dist > flareProp and dist < max:
flare.localScale = (dist0.2, dist0.2, dist*0.2)
in contrast “if”, I turn off the visibility of the object
else:
flare.visible = 0

at me my code works, I learned by a trial and error method address to objects of a scene with the certain properties and to do over them manipulations.

rayCastTo - It is necessary to disable the overlay glow on all objects of the scene (infinity Z-offset), when object block the appearance of the glow itself.

I forgot to write - one of the conditions for writing this script, was not to look into the script of Vladas and Shtilits, but use the help - it turned out like:yes:.

  • and if I approach the glow at a distance less flareProp, the glow will disappear?

https://docs.unity3d.com/560/Documentation/uploads/Main/FlareInspector.png

this could help you, try it.thank you

Little hint:

it would read a bit better when you write gameObject.visible = True (rather than 0).

While your code is fine here are some remarks:rayCastTo
will be None when the measure does not detect an object. In your code: None when nothing is detected between the owner and the flare (excluding both objects). From bottom-up-view this is perfectly fine (it is the actual implementation).

From top-down-view it causes distortions as you got them. I assume you want to show the flare when it is not covered by other objects. When you rename “ray” to something that expresses what you mean the code suddenly makes more sense:


        flareIsCovered = own.rayCastTo(flare)
        if not flareIsCovered:
            flare.visible = True
        else:
            flare.visible = False


You have more visibility conditions:


for flare in scene.objects:
    if "flare" in flare:
        flareIsCovered = own.rayCastTo(flare)
        if (not flareIsCovered and 
           inViewDistance(flare)):
            flare.localScale = [getOwner().getDistanceTo(flare) * 0.2 ]*3
            flare.visible = True
        else:
            flare.visible = False


Here are the used functions. You can either import them form a separate module or place it before the using code (the function definition needs to be executed before you call the function).


def inViewDistance(flare):
    minViewDistance = flare["flare"]
    maxViewDistance = flare["flareDist"]
    distance = getOwner().getDistanceTo(flare)
    return (distance &gt; minViewDistance and 
            distance &gt; maxViewDistance) 

def getOwner():
    return bge.logic.getCurrentController().owner



You might noticed that the property names do not match the purpose of the properties:

“flare”: A) identifies a flare B) contains minimum view distance
“flareDist”: contains maximum view distance

A reader who did not understand the code will not know what the properties are good for.

Other implementations are possible:

import bge


controller = bge.logic.getCurrentController()
owner = controller.owner
scene = bge.logic.getCurrentScene()


flares = [object for object in scene.objects 
            if object.get("flare", 0) &gt; 0.0]


for flare in flares:
    minViewDistance = flare["flare"]
    maxViewDistance = flare["flareDist"]
    distance = owner.getDistanceTo(flare)


    scale = (distance 
            if (distance &gt; minViewDistance and 
                distance &gt; maxViewDistance) * 0.2 
            else None)
    
    visibility = False
    if scale:
        flareIsCovered = owner.rayCastTo(flare)
        if not flareIsCovered:
            flare.localScale = [scale]*3
            visibility = True
            
    flare.visible = visibility

The calculated scale contains the limit check. objects without property flare and value <= zero are ignored (allows to dynamically disable them).

Maybe it provides you some ideas.

  • Is it Unity?
  • your code does not work. And if you show it to someone, then he will say - it’s you that made everything complicated. Although there are interesting solutions …

The code under “other implementation” is completed and tested with your file.

The code under “rayCastTo” is a fragment. You need to adopt it into your existing code. When you do not feel well to mount that code together here is one possible solution:

flare_scale01.py

from flare import getOwner, getFlares, inViewDistance


owner = getOwner()


for flare in getFlares():
    flareIsCovered = owner.rayCastTo(flare)
    
    if (not flareIsCovered and 
       inViewDistance(flare)):
        flare.localScale = [owner.getDistanceTo(flare) * 0.2 ]*3
        flare.visible = True
    else:
        flare.visible = False

flare.py


import bge


def getFlares():
    return [object for object in getOwner().scene.objects 
            if object.get("flare", 0) &gt; 0.0]
            
def inViewDistance(flare):
    minViewDistance = flare["flare"]
    maxViewDistance = flare["flareDist"]
    distance = getOwner().getDistanceTo(flare)
    return (distance &gt; minViewDistance and 
            distance &gt; maxViewDistance) 


def getOwner():
    return bge.logic.getCurrentController().owner
  • “other implementation” - own.work = False