1
$\begingroup$

Problem:

I have an object which, when triggers, is supposed to exert a force all around the object itself. I am looking to have the force affect other objects. How can I create a force coming out of an object and going in all directions?

Include/Note:

  • Force decreases over distance. This way, an object close to the force will be affected more than an object farther (than origin of the force) in distance.
  • Force does not decrease/increase strength over time; force is constant. This will be useful in many ways. For example, if the object exerting the force exerts the force for only 1 ms, the objects affected by it will be affected by this (1 ms lasting) force which has just been activated (1 ms lifetime) by the same strength as a force that affects them for 1 ms but has been going on for 60 ms.
  • A property that defines how much force to use
  • A property that defines how long the force will last.
  • Please try to answer in python

I'm sorry if this is too much to ask for. I still have a lot to add to this, but I will try to put those in separate questions if I don't figure them out. Any help is appreciated. Thanks!

$\endgroup$

1 Answer 1

2
$\begingroup$

There is no build-in method to do that.

You need to write your own Python controller. But it is not that hard.

I suggest you use a near sensor to identify objects around your force source. It does not only detect the objects to be affected it also sets up the range of your "force field".

To adjust the strength of the force you can use the optional property "strength". It tells how much the force would be at the location of the source object. It will be linear reduced by the distance of the affected object and the source object. At the outer range the force strength will be 0.0.

Usage:

Place this snippet in a python file force.py

import bge 

PROPERTY_STRENGTH = "strength"
DEFAULT_STRENGTH = 1.0

def applyForceFromHere():
    if not allSensorsPositive():
        return 
    sensor = getDetectionSensor()
    affectedObjects = sensor.hitObjectList

    maxRange = sensor.distance
    source = getOwner()
    strength = getOwner().get(PROPERTY_STRENGTH, DEFAULT_STRENGTH)

    for affectedObject in affectedObjects:
        sourceToObject = affectedObject.worldPosition - source.worldPosition
        direction = sourceToObject.normalized()
        ratio = max(0, maxRange - sourceToObject.length) # linear interpolation
        force = direction * strength * ratio
        affectedObject.applyForce(force)

def getDetectionSensor():
    return bge.logic.getCurrentController().sensors[0]

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

def allSensorsPositive():
    for sensor in bge.logic.getCurrentController().sensors:
        if not sensor.positive:
            return False
    return True

Apply following logic to the source object:

  • Setup a near sensor (must be the first one) with a distance that covers the area you want to have, ensure to enable [True Level Triggering] at the sensor that activates the force field
  • Setup a Python controller in module mode with Module: force.applyFromHere
  • Ensure affected objects are physics objects (dynamic, rigid body, softbody)

enter image description here

How does it work?

When all sensors are positive and any of the sensors triggers the controller the function applyFromHere() will be executed. Each run will apply exactly one force or no force at all. There will be no "duration". Either you trigger the controller or you do no trigger it. Forces will only applied when triggered. That is the reason for [True Level Triggering]. This is not necessary when you do not want to have your force field active.

The near sensor provides the affected objects (only physics objects) within the distance. The Python controller calculates the

  • distance to the source object
  • direction to away from the source object
  • ratio (linear interpolation) with
    • 1.0 at the location of the source object
    • 0.0 at the distance and further away
  • the strength of the force

With that the Python controller applies the individual forces to each single affected object.

Remark: The duration of the force is the atomic minimum (one frame). The Python controller is no actuator. Therefore you need to run it again and again and again to get a continuous force.

Hint: You can enter a negative strength

I hope it helps

$\endgroup$
5
  • $\begingroup$ Great answer, I couldn't have asked for anything in more detail. Also, I'm having a small issue and I can't get the force to work. Can you add a sample .blend? Thanks. $\endgroup$
    – blackhole
    Commented Nov 21, 2015 at 5:11
  • $\begingroup$ Have you set the Physics type in the Physics tab to all objects that should be affected (not the one that runs the Python code)? $\endgroup$
    – Monster
    Commented Nov 23, 2015 at 5:11
  • $\begingroup$ After recreating the answer in a separate .blend, I noticed the following: the module is "force.applyFromHere," when what works is "force.applyForce." Also, it seems that when I hold it (spacebar, my test scene's 2nd sensor is keyboard), it puts a continuous force even though I have true level triggering enabled. The answer states there is no "duration." I'm not so sure, but I got a duration by holding spacebar. Alternatively, we should use "tap" to remove duration. Thanks though, I really didn't expect such a quick and informative answer! Also: pasteall.org/blend/39343 for anyone. $\endgroup$
    – blackhole
    Commented Nov 23, 2015 at 22:08
  • $\begingroup$ Yes, you are right, the function name is different. I corrected the snippet in the answer. $\endgroup$
    – Monster
    Commented Nov 24, 2015 at 7:00
  • $\begingroup$ The duration is still one frame. Each time you trigger the controller (with positive sensors) you will add the force. With True Level Triggering enabled you get the continuous application. If you use tap or no True Level Triggering you need to release the button before you can add another force. $\endgroup$
    – Monster
    Commented Nov 24, 2015 at 7:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .