So - two things are happening when this sprite flips. There's this magic animation and then a shockwave, but the shockwave goes invisible when I turn left. Not up, down or right, only left, and turning right restores it. Pretty sure this is tied to my sprite flipping, but the magic/rune animation is unaffected. I also checked transform values through debugging and nothing looks amiss. I even tried using a "home transform" value that is set at the ready() for the sprite to snap back into, but no luck. I even put an additional mesh so I could see the area3d moving and it is unaffected. What is happening here? (I've tried my best to truncate this to the relevant code.)

extends KinematicBody

## base speed movements
export var _baseSpeed = 150
var _speed = _baseSpeed
export var _runSpeed = 300
var _velocity = Vector3.ZERO
const _scaleRef : float = 0.25 ## base value for sprite scaling

### movement state machine
var _playerStatus : int = 1
enum _PLAYER_STATES {WAIT, IDLE, WALK, RUN, JUMP, FALL, LAND, HIT, SICK, DEAD}

## attack state machine
var _isAttacking : bool = false
var _canChangeWeapon : bool = true

## spell state machine
var _isCasting : bool = false
enum _SPELL_NAME {SCREAM}
export (_SPELL_NAME) var _SPELL_EQUIPPED
onready var _spellArea = $SpellRange/CollisionArea
onready var _spellPlayer = $SpellRange/SpellAnimator
onready var _spellSprite = $SpellRange/SpellSprite
onready var _shockWave = 	$SpellRange/CollisionArea/AreaEffect
var _spellLocation = null
var _defaultSpellAreaSize = null

func _ready(): ## set default animations
	_defaultSpellAreaSize = _spellArea.scale
	_spellSprite.frame = 0
	_animator.play("Grandma Idle 1")


func _physics_process(delta):
	_escapeToEditor() ## editor shortcut, remove before build
	
	## listen for movements when not attacking or casting
	if !_isAttacking and !_isCasting and _playerStatus > 0:
		_movement_state(delta)
	
	if _playerStatus == _PLAYER_STATES.LAND or _isCasting:
		_velocity.x = 0
		_velocity.z = 0


	if _spellLocation != null:
		_spellArea.global_transform = _spellLocation
		_spellSprite.global_transform = _spellLocation
	else:
		_spellSprite.global_transform = $Sprite.global_transform
		_spellArea.global_transform = _spellSprite.global_transform


## movement machine
func _movement_state(delta):
	var _direction = Vector3.ZERO ## set local direction variable
	if Input.is_action_pressed("ui_left"):
		_direction.x-=1
		_walkOnGround() ## check animation states
		_airMove()
		if $Sprite.scale.x > -_scaleRef: ## sprite flip
			$Sprite.scale.x-=(_scaleRef/4) ## gradual
	if Input.is_action_pressed("ui_right"):
		_direction.x+=1
		_walkOnGround()
		_airMove() ## check animation states
		if $Sprite.scale.x < _scaleRef: ## sprite flip
			$Sprite.scale.x+=(_scaleRef/4) ## gradual
	if Input.is_action_pressed("ui_down"):
		_direction.z+=1
		_walkOnGround()
		_airMove()
	if Input.is_action_pressed("ui_up"):
		_direction.z-=1
		_walkOnGround()
		_airMove()
	
	
	if Input.is_action_just_released("ui_left"):
		$Sprite.scale.x = -_scaleRef ## set sprite scale instant on button release
		_direction.x = 0 ## stop movement
		_idleOnGround()
	if Input.is_action_just_released("ui_right"):
		$Sprite.scale.x = _scaleRef  ## set sprite scale instant on button release
		_direction.x = 0 ## stop movement
		_idleOnGround()
	if Input.is_action_just_released("ui_down") or Input.is_action_just_released("ui_up"):
		_direction.z = 0 ## stop movement
		_idleOnGround()
	
	
	if Input.is_action_just_pressed("cast") and is_on_floor(): ## SPELL CALL
		_isCasting = true ## movement and input pause until resolved
		_magicState()


## reset states, open input on attack or spell animation finish
func _on_AnimationPlayer_animation_finished(_anim_name):
	if _isAttacking:
		_isAttacking = false
	
	if _isCasting:
		_isCasting = false

	
	if _playerStatus == _PLAYER_STATES.JUMP:
		if is_on_floor():
			_playerStatus = _PLAYER_STATES.LAND
		else:
			_playerStatus = _PLAYER_STATES.FALL
	
	
	if _playerStatus == _PLAYER_STATES.LAND:
		_playerStatus = _PLAYER_STATES.IDLE


	_animator.playback_speed = 1


## spell state machine
func _magicState():
	_velocity = Vector3.ZERO
	$SpellRange/CastingDelay.start(1)
	_spellLocation = $SpellRange/CollisionArea.global_transform
	_spellSprite.frame = 0
	_animator.playback_speed = 3 ## up animation speed for less latency
	_spellSprite.global_transform = _spellLocation
	_spellArea.global_transform = _spellLocation
	match _SPELL_EQUIPPED: 
		_SPELL_NAME.SCREAM:
			_animator.play("Grandma Scream 1") ## player animation
			_spellPlayer.play("field") ## spell animation
			_spellSprite.play("default")
			


func _on_SpellSprite_animation_finished():
	_spellSprite.stop()
	_spellSprite.modulate.a = 0


func _on_CastingDelay_timeout():
	_spellLocation = null
	_shockWave.scale = _defaultSpellAreaSize
	_spellPlayer.play("RESET")
  • SnapCracklins replied to this.
  • SnapCracklins ah rats. i wasted someone's time. it was my scene tree order. My mesh was a child of my collision shape rather the area object. It's working now. 🤣

    Leaving it here for who needs it next.

    SnapCracklins ah rats. i wasted someone's time. it was my scene tree order. My mesh was a child of my collision shape rather the area object. It's working now. 🤣

    Leaving it here for who needs it next.