"Exception occurred in Python script: ReferenceError: "$B" is not defined."

Hello,
at a specific point in my Python Delightex Project I get this Error (only occures on iPad/Phone, but not on PC.

This is my code:
from delightex import *

=== Szenenobjekte ===

start_knopf = scene.get_item(“Gi57DR3X”)
start_knopf_hitbox = scene.get_item(“srjPadIr”)
weiter_knopf_hitbox = scene.get_item(“FPq1EsKH”)
weiter_knopf = scene.get_item(“3QpevabJ”)
small_cube = scene.get_item(“38QgFiG5”)
stange = scene.get_item(“BfKXvEL8”)
platte = scene.get_item(“KZlBN0Gw”)
pyramid = scene.get_item(“Gbd0pMUW”)

Improvisation, weil man den Würfel im AR mode net unsichtbar machen kann…, statt im Würfel sind die jetzt auf dem Würfel

=== Alle Objekte um 10 Z-Einheiten erhöhen (Höhe) ===

sceneObjects = [start_knopf, start_knopf_hitbox, weiter_knopf_hitbox, weiter_knopf, small_cube, stange, platte, pyramid]

DEBUG

if None in sceneObjects:
warn(“EINES DER SZENEN-OBJEKTE IST NONE!!”)
for item in sceneObjects:
pos = item.transform.position
item.transform.position = Vector3(pos.x, pos.y, pos.z + 10)

=== Hilfsfunktionen ===

def set_opacity(opacity, *items):
for item in items:
if item is not None:
item.opacity = opacity
else:
print(“WARNUNG: set_opacity-Objekt ist None!”)

def highlight_button(button, scale_factor=1.1, duration=0.2):
original_scale = button.transform.scale
button.transform.scale = original_scale * scale_factor

def reset():
    button.transform.scale = original_scale

time.schedule(reset, duration)

def sichtbar(*items):
set_opacity(1.0, *items)

def unsichtbar(*items):
set_opacity(0.0, *items)

def update_info(text, *, done=False):
if not done: titel = f"Aufgabe {current_task_index + 1}"
else: titel = “Volumen”
gui.hud.show_info_panel(titel, text)
print(f"DEBUG: HUD-Text gesetzt:\n{titel}\n {text}")

def shush(*items):
for item in items:
if item is not None:
item.speech = None
print(f"{item.name} hört nun auf zu reden.")
else:
print(“WARNUNG: shush-Objekt ist None!”)

def move_to(item, position): # Y != HÖHE, Z = HÖHE
item.transform.position = position
print(f"DEBUG: {item.name} moved to position {position}")

def add_object(obj):
objects[current_task_index].append(obj)

basically nur für task 0 bzw 1

def spawn_series(base_model, offset, target_list, count=5, include_original=True, delay=0.5, on_done=None, info_text=“”):
base_pos = base_model.transform.position
add_object(base_model)

if include_original:
    sichtbar(base_model)
    target_list.append(base_model)
    print(f"DEBUG: Original {base_model.name} retained at {base_pos}")

def spawn(i):
    new_item = base_model.copy()
    add_object(new_item)
    new_pos = Vector3(
        base_pos.x + offset[0] * i,
        base_pos.y + offset[1] * i,
        base_pos.z + offset[2] * i
    )
    move_to(new_item, new_pos)
    sichtbar(new_item)
    target_list.append(new_item)
    print(f"DEBUG: New {base_model.name} {i + 1} created at {new_pos}")

start = 1 if include_original else 0
for i in range(start, count):
    time.schedule(lambda i=i: spawn(i), delay * (i - start))

if on_done is not None:
    time.schedule(on_done, delay * (count - start) + 0.1)

update_info(info_text)

=== Aufgabensteuerung ===

isRunning = False
tasks =
current_task_index = 0
current_step_index = 0
step_running = False
objects = [, , , , ] # für cleanup

=== Schritt beenden ===

def finish_step():
global step_running
step_running = False
highlight_button(weiter_knopf, scale_factor=1.05, duration=0.1)

=== Schritt starten ===

def run_next_step():
global current_step_index, step_running, current_task_index
highlight_button(weiter_knopf)

if step_running:
    update_info("Bitte warte, ein Schritt läuft noch!")
    return

steps = tasks[current_task_index]
if current_step_index < len(steps):
    step_running = True
    steps[current_step_index](lambda: finish_step())
    current_step_index += 1
else:
    print("DEBUG: Aufgabe abgeschlossen.")
    time.schedule(next_task, 0.5)

=== Aufgabe 0: Würfel erklären ===

def setup_task_0():
def step_1(done):
update_info(“Hallo! Willkommen zu unserem Volumen-Abenteuer. Heute lernst du, wie man das Volumen von Würfeln berechnet.”)
time.schedule(done, 0.5)

def step_2(done):
    sichtbar(small_cube)
    update_info("Schau dir diesen Würfel an. Er ist 1 lang, 1 hoch und 1 breit.")
    time.schedule(done, 0.5)

small_cubes = []
def step_3(done):
    spawn_series(
        small_cube,
        offset=(-2, 0, 0),
        target_list=small_cubes,
        on_done=done,
        info_text="Jetzt haben wir 5 kleine Würfel in einer Reihe."
    )

def step_4(done):
    update_info("Diese 5 Würfel ergeben eine Stange: 5 lang, 1 hoch, 1 breit.")
    time.schedule(done, 0.5)

def step_5(done):
    unsichtbar(*small_cubes)
    sichtbar(stange)
    time.schedule(done, 0.5)

stangen = []
def step_6(done):
    spawn_series(
        base_model=stange,
        offset=(0, 2, 0),
        target_list=stangen,
        on_done=done,
        info_text="Jetzt haben wir 5 Stangen in die Tiefe gestapelt: 5 x 1 x 5."
    )

platten = []
def step_7(done):
    unsichtbar(*stangen)
    sichtbar(platte)
    platten.append(platte)
    update_info("Diese Stangen werden zu einer Platte mit 5 x 5 x 1.")
    time.schedule(done, 0.5)

def step_8(done):
    spawn_series(
        base_model=platte,
        offset=(0, 0, 2),
        target_list=platten,
        on_done=done,
        info_text="Jetzt haben wir 5 Platten gestapelt: ein Würfel mit 5 x 5 x 5."
    )

def step_9(done):
    update_info("Das Volumen dieses Würfels ist Länge × Breite × Höhe.")
    time.schedule(done, 0.5)

def step_10(done):
    update_info("Das ergibt 5 × 5 × 5 = 125 Kubikeinheiten.")
    time.schedule(done, 0.5)

return [step_1, step_2, step_3, step_4, step_5, step_6, step_7, step_8, step_9, step_10]

=== Aufgabe 1: Volumeneinheiten ===

def setup_task_1():
def step_1(done):
update_info(“Volumen misst, wie viel in einen Körper passt – z. B. in cm³, dm³ oder m³.”)
time.schedule(done, 0.5)

def step_2(done):
    update_info("Ein Würfel mit 1 cm Kantenlänge hat 1 cm³ Volumen.")
    time.schedule(done, 0.5)

def step_3(done):
    update_info("Ein Würfel mit 10cm = 1dm Kantenlänge hat 1000 cm³ = 1 dm³.")
    time.schedule(done, 0.5)

def step_4(done):
    update_info("1 dm³ ist genauso viel wie 1 Liter. Also: 1 l = 1 dm³.")
    time.schedule(done, 0.5)

def step_5(done):
    update_info("Und 1 Liter sind z. B. 1000 ml, wie in einer Wasserflasche.")
    time.schedule(done, 0.5)

return [step_1, step_2, step_3, step_4, step_5]

=== Aufgabe 2: Volumenformel beim Quader ===

def setup_task_2():
cubes =

def step_1(done):
    update_info("Ein Quader hat unterschiedliche Seitenlängen.")
    time.schedule(done, 1.5)

def step_2(done):
    update_info("Angenommen, ein Quader ist 2 lang, 3 breit und 4 hoch.")
    
    base = small_cube.transform.position + Vector3(-4, 0, 0)  # weiter rechts bauen
    count = 0
    for x in range(2):      # Länge
        for y in range(3):  # Breite
            for z in range(4):  # Höhe (Z!)
                def spawn(i=count, x=x, y=y, z=z):
                    cube = small_cube.copy()
                    move_to(cube, Vector3(
                        base.x + x * 2,
                        base.y + y * 2,
                        base.z + z * 2
                    ))
                    sichtbar(cube)
                    cubes.append(cube)
                    add_object(cube)
                time.schedule(spawn, count * 0.15)
                count += 1
    time.schedule(done, count * 0.15 + 0.5)

def step_3(done):
    update_info("Das Volumen ist: 2 × 3 × 4 = 24 Kubikeinheiten.")
    time.schedule(done, 3.0)

return [step_1, step_2, step_3]

=== Aufgabe 3: Volumen verschiedener Körper ===

Diese Aufgabe zeigt einen 3D-Körper (Raumkreuz) mit Volumen-Quiz.

def setup_task_3():
cubes =

def step_1(done):
    update_info("Jetzt schauen wir uns verschiedene Körper und ihr Volumen an.")
    time.schedule(done, 0.5)

def step_2(done):
    update_info("Hier bauen wir eine 3D-Kreuzform als Beispielkörper.")
    base = small_cube.transform.position + Vector3(-4, 4, 4)

    directions = [
        Vector3(1, 0, 0), Vector3(-1, 0, 0),  # X-Achse
        Vector3(0, 1, 0), Vector3(0, -1, 0),  # Y-Achse
        Vector3(0, 0, 1), Vector3(0, 0, -1)   # Z-Achse
    ]

    count = 0

    def place_cube(pos):
        cube = small_cube.copy()
        move_to(cube, pos)
        sichtbar(cube)
        cubes.append(cube)
        add_object(cube)

    # Mittelwürfel
    place_cube(base)

    # In alle 6 Richtungen je 2 Blöcke raus
    for dir in directions:
        for i in range(1, 3):
            pos = base + dir * (i * 2)
            time.schedule(lambda pos=pos: place_cube(pos), count * 0.15)
            count += 1

    time.schedule(done, count * 0.15 + 0.5)

def step_3(done):
    update_info("Wie viel Volumen hat dieses Kreuz?")

    def on_correct():
        update_info("Richtig! Das Kreuz besteht aus 13 kleinen Würfeln.")
        time.schedule(done, 2.0)

    def on_wrong():
        update_info("Fast! Das Kreuz besteht aus 13 kleinen Würfeln.")
        time.schedule(done, 2.0)

    gui.hud.show_quiz_panel(
        question="Wie viele kleine Würfel hat das Kreuz insgesamt?",
        answer1="11",
        answer2="13",
        correct_answer=2,
        answer3="15",
        answer4="12",
        on_correct=on_correct,
        on_wrong=on_wrong
    )

return [step_1, step_2, step_3]

=== Aufgabe 4: Volumen einer Pyramide ===

def setup_task_4():
def step_1(done):
update_info(“Jetzt betrachten wir das Volumen einer Pyramide.”)
sichtbar(pyramid)
add_object(pyramid)
time.schedule(done, 1.5)

def step_2(done):
    update_info("Diese Pyramide hat eine Grundfläche von 5 × 5 = 25 und eine Höhe von 5.")
    time.schedule(done, 1.5)

def step_3(done):
    update_info("Die Volumenformel lautet: V = \u2153 \u00d7 Grundfläche \u00d7 Höhe")
    time.schedule(done, 2.0)

def step_4(done):
    update_info("Also: V = \u2153 \u00d7 25 \u00d7 5 = ?")

    def on_correct():
        update_info("Richtig! Das Volumen der Pyramide ist \u2153 \u00d7 25 \u00d7 5  \u2248 41,67 Einheiten³.")
        time.schedule(done, 3.0)

    def on_wrong():
        update_info("Fast! Richtig ist: \u2153 \u00d7 25 \u00d7 5  \u2248 41,67 Einheiten³.")
        time.schedule(done, 3.0)

    gui.hud.show_quiz_panel(
        question="Wie groß ist das Volumen dieser Pyramide?",
        answer1="50",
        answer2="62.5",
        answer3="41.67",
        correct_answer=3,
        answer4="25",
        on_correct=on_correct,
        on_wrong=on_wrong
    )

return [step_1, step_2, step_3, step_4]

=== Aufgabe 5: Abschlusstest ===

def setup_task_5():
def step_1(done):
update_info(“Jetzt zeigen wir, dass du Volumen auch im Alltag berechnen kannst!”)
time.schedule(done, 1.5)

def step_2(done):
    def on_correct():
        update_info("Richtig! Der Blumenkasten fasst 60 dm³ Erde.")
        time.schedule(done, 2.0)

    def on_wrong():
        update_info("Fast! Der Blumenkasten hat 100 cm × 30 cm × 20 cm = 60000 cm³ = 60 dm³.")
        time.schedule(done, 2.0)

    gui.hud.show_quiz_panel(
        question="Ein Blumenkasten ist 1 m lang, 30 cm breit und 20 cm hoch. Wieviel Erde passt hinein?",
        answer1="60 dm³",
        answer2="6 dm³",
        correct_answer=1,
        answer3="600 dm³",
        answer4="18 dm³",
        on_correct=on_correct,
        on_wrong=on_wrong
    )

def step_3(done):
    def on_correct():
        update_info("Genau! 5 × 5 × 1 = 25 Würfel.")
        time.schedule(done, 2.0)

    def on_wrong():
        update_info("Nicht ganz. Es sind 5 × 5 = 25 Würfel in der Schachtel.")
        time.schedule(done, 2.0)

    gui.hud.show_quiz_panel(
        question="Eine Schachtel ist 5 cm lang, 5 cm breit und 1 cm hoch. Wieviele 1 cm³-Würfel passen hinein?",
        answer1="25",
        answer2="10",
        correct_answer=1,
        answer3="5",
        answer4="50",
        on_correct=on_correct,
        on_wrong=on_wrong
    )

def step_4(done):
    def on_correct():
        update_info("Sehr gut! Das Volumen des Eimers ist 10 × 10 × 30 = 3000 cm³ = 3 Liter.")
        time.schedule(done, 2.0)

    def on_wrong():
        update_info("Nicht ganz. Der Eimer fasst 10 × 10 × 30 = 3000 cm³ = 3 Liter.")
        time.schedule(done, 2.0)

    gui.hud.show_quiz_panel(
        question="Ein kleiner Eimer ist 10 cm lang, 10 cm breit und 30 cm hoch. Wieviel Liter Wasser passt rein?",
        answer1="3 l",
        answer2="30 l",
        correct_answer=1,
        answer3="0,3 l",
        answer4="10 l",
        on_correct=on_correct,
        on_wrong=on_wrong
    )

def step_5(done):
    def restart():
        global isRunning
        isRunning = False
        sichtbar(start_knopf)
    update_info("Super gemacht! Du hast den Abschlusstest bestanden.", done=True)
    time.schedule(done, 2.5)
    time.schedule(restart, 3)

return [step_1, step_2, step_3, step_4, step_5]

=== Cleanups ===

def cleanupTask():
for obj in objects[current_task_index]:
unsichtbar(obj)
shush(obj)

“”" Auskommentiert weil nicht gebraucht
if not current_task_index in cleanups: return
cleanupscurrent_task_index

def cleanup_task_3():
# dann kann ich hier so specific cleanups machen
pass

cleanups = {
3: cleanup_task_3
}
“”"

=== Steuerung ===

def start():
global isRunning
if isRunning: return
isRunning = True
global current_task_index, current_step_index
shush(start_knopf)
unsichtbar(start_knopf)
current_task_index = 0
current_step_index = 0
update_info(“Spiel wurde gestartet.”)
sichtbar(weiter_knopf)
run_next_step()

=== Nächste Aufgabe laden ===

def next_task():
global current_task_index, current_step_index
cleanupTask()

current_task_index += 1
current_step_index = 0
if current_task_index < len(tasks):
    update_info("Neue Aufgabe gestartet!")
    run_next_step()
else:
    update_info("Alle Aufgaben abgeschlossen!", done=True)
    print("DEBUG: Alle Aufgaben abgeschlossen.")

=== Initialisierung ===

def main():
sichtbar(start_knopf)
start_knopf_hitbox.input.on_click(start)
weiter_knopf_hitbox.input.on_click(run_next_step)
print(“Main eingeleitet”)

=== Aufgabenliste aufbauen ===

tasks = [setup_task_0(), setup_task_1(), setup_task_2(), setup_task_3(), setup_task_4(), setup_task_5()]
main()