Prevent parent from affecting child object scale in Blender GE

As in the title, how would I limit the child objects scale so its unaffected by the parent in the GE. I don’t want to do individual keyframes to keep the scale at normal. An example is a water geyser with a rock.

dont parent them, use two animations, on for translation, one for scale. another solution could be an armature with a bone weighted to the top half to have a scale-like effect when moved.

scale in bge is just nasty, avoid where possible.

For me, I had the same parent scale effecting children scale when making crouching functions.
Solution is to assign all child scales after the parent scaling operation, that way, they all stay at separate scales with no visual children changes except the desired scaling for the parent.

Example.

import bge

def crouch(self):

# CROUCHED
if bge.logic.keyboard.events[bge.events.LEFTSHIFTKEY].status == 2:
  self.owner.worldScale = 0.5
  for child in self.owner.children:
    child.worldScale = 1.0
# UNCROUCHED
elif bge.logic.keyboard.events[bge.events.LEFTSHIFTKEY].status == 0:
  self.owner.worldScale = 1.0
  for child in self.owner.children:
    child.worldScale = 1.0

Hi I am crap with python or any coding, but can you explain what the words in this mean so I can apply it to my own game?

Hello. I’ll try to explain my old code in more laymen terms.


import bge

  • This imports the BGE module so that we can use BGE functions, methods and attributes.

def crouch(self):

  • This defines a function called “crouch” and it also passes the object owner of the script via the “self” argument.

Lines with if bge.logic.keyboard.events

  • These lines define the keyboard input controls and which to use.

These lines self.owner.worldScale

  • They set all of the owner of the script’s world scale [X, Y, Z].

Lines with for child in self.owner.children:

  • They get all of the script owner’s children so that we can reference them on.

These lines child.worldScale reference any found children of the script owner, then sets those found children’s world scale.


So, this is what I have, and I just want to make sure I’m doing this right
I’m probably just missing something silly, but this doesn’t make the parent change scale when I press the lefts shift key.

If you know what’s happening, please let me know
If not, is it too much to ask for a blend file?

Thanks,
Nick

My script is setup as a module. Nothing is working for you because nothing is calling it on your end. You either need to change your Python Controller type from Script to type Module. Or you need to add crouch() at the end of my script on a new line if you wish to keep type, Script for your Python Controller.


Hi,
thanks for the quick response, and I apologize if I am asking too many questions,
but it’s having a problem with ‘status’ now
I also notice that words like ‘self’ and ‘child’ aren’t colored in my script but are in yours, so idk if something else isn’t working either, or if that part doesn’t matter
Thanks,
Nick

No problem. This is what this forum is for; helping and uplifting others.

Sigh. I’m not sure why I put that there. I think it was either a BGE or legacy UPBGE implementation that never got implemented into UPBGE 0.3+. Anyhow, just remove that .status part. I also added .z to the end of all of the .worldScale methods, as the crouching should only affect the z-axis. In the past, I think I rush coded my post because the lines weren’t even properly indented. : - )

Here’s the correct code.

import bge

def crouch(self):

    # CROUCHED
    if bge.logic.keyboard.events[bge.events.LEFTSHIFTKEY] == 2:
      self.owner.worldScale.z = 0.5
      for child in self.owner.children:
        child.worldScale.z = 1
    # UNCROUCHED
    elif bge.logic.keyboard.events[bge.events.LEFTSHIFTKEY] == 0:
      self.owner.worldScale.z = 1
      for child in self.owner.children:
        child.worldScale.z = 1

My script coloring comes from forum syntax. Not Blender syntax. They have different theme colors.

1 Like

Thanks! It works!
A tiny thing that I notice is that the child shifts down a couple pixels when I do it, but idk how fixable that is

Thanks,
Nick

EDIT:
I fixed the shifting down thing
It was just cus before I started the game, the child was shifted a couple pixels up

Oh, real quick
How would I make it always crouch when the script runs, instead of just when pressing left shift?

Or, what I mean is, make it always crouch when the sensor in the logic bricks is being activated, but uncrouch when it isn’t

Yes. This common with meshes that have their origin points at the center of their geometry. Here’s a script that will compensate the location offset manually.

Video Demo

Script

  • New things:
    • Updated keyboard inputs to current - BGE had .status and legacy UPBGE 0.2+ & 0.3+ now have inputs instead of events.
    • Replaced world methods with local methods.
    • Replaced .children with .childrenRecursive so that we can get the children of children as well.
import bge

def crouch(self):

    # NO INPUT - SCALE
    if bge.logic.keyboard.inputs[bge.events.LEFTSHIFTKEY].inactive:
        self.owner.localScale.z = 1
        for child in self.owner.childrenRecursive:
            child.localScale.z = 1
    # JUST ACTIVATED INPUT - POSITION
    if bge.logic.keyboard.inputs[bge.events.LEFTSHIFTKEY].activated:
        self.owner.localPosition.z -= 0.5
        for child in self.owner.childrenRecursive:
            child.localPosition.z += 2
    # ACTIVE INPUT - SCALE
    if bge.logic.keyboard.inputs[bge.events.LEFTSHIFTKEY].active:
        self.owner.localScale.z = 0.5
        for child in self.owner.childrenRecursive:
            child.localScale.z = 1
    # JUST RELEASED INPUT - POSITION
    if bge.logic.keyboard.inputs[bge.events.LEFTSHIFTKEY].released:
        self.owner.localPosition.z += 0.5
        for child in self.owner.childrenRecursive:
            child.localPosition.z -= 2

Final Notes

  • If you set the origin point of your object’s at the bottom of the mesh on the Z-axis, the scaling automatically only scales upwards and not downwards as well. Hotkey to set mesh origins CTRL+ALT+X. Using these operators along with Edit Mode while selecting a vertex, edge or face that is near the bottom of the mesh is also quick to setup.

For 1 time on controller run:

  • Use self.owner.sensors["Always"].status == 1.

If you have true-pulse enabled and want the controller to run continuously:

  • Use self.owner.sensors["Always"].status == 2.
    • You don’t really need this function, only if you use .status == 1 to implement init and update areas alongside one another.

If you only have one sensor just replace "Always" with 0 to indicate the first sensor.

Take a look at my new script and if anything doesn’t make sense. Feel free to drop a post.