using { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /Verse.org/Simulation/Tags } using { /UnrealEngine.com/Temporary/SpatialMath } using { /UnrealEngine.com/Temporary/Diagnostics } # BUILD THE CAR PRIMITIVE — Part 1 of "Scene Graph: Car Primitive". # # A "car" in UEFN can mean two very different things. The real modular wheeled # vehicle (engine + suspension + wheels) is built from `modular_vehicle_*` # scene-graph components that are ALL Epic-internal in build 41.00 — a creator # cannot assemble one from Verse. So we build the honest, creator-usable version: # a PRIMITIVE. A primitive is just a placed prop (a mesh body) that we claim as # "the car", find from Verse, and move on command. That is the foundation every # later lesson builds on: colour it (Part 2), drive a camera into it (Part 3), # and make it actually move under input (the capstone). # # We use TAG DISCOVERY (the proven working-island idiom) instead of @editable # wiring: the car body is any placed prop carrying the `car_body_tag`, and the # ignition is any button carrying the `car_ignition_tag`. Press the ignition and # the car nudges forward — proof we have a live handle on a real placed prop. # A tag is any class deriving from `tag`. Put the matching string on the actors # in the editor (set the actor's Tags array) so Verse discovers them with no # Details-panel binding. car_body_tag := class(tag) {} car_ignition_tag := class(tag) {} car_build_primitive_device := class(creative_device): # How far (cm) the car nudges forward on each ignition press. @editable NudgeDistance : float = 250.0 # How long (seconds) the nudge takes. @editable NudgeSeconds : float = 0.6 OnBegin() : void = # Find the ignition button(s) by tag and react to each press. for (Obj : FindCreativeObjectsWithTag(car_ignition_tag)): if (Ignition := button_device[Obj]): Ignition.InteractedWithEvent.Subscribe(OnIgnition) Print("CarPrimitive: ignition wired.") # Confirm we actually found a car body to drive. for (Obj : FindCreativeObjectsWithTag(car_body_tag)): if (Body := creative_prop[Obj]): Print("CarPrimitive: car body found and ready.") OnIgnition(Agent : agent) : void = spawn { NudgeForward() } # Move every tagged car body one nudge along its own forward (+X) direction. NudgeForward() : void = for (Obj : FindCreativeObjectsWithTag(car_body_tag)): if (Body := creative_prop[Obj]): spawn { NudgeOne(Body) } NudgeOne(Body : creative_prop) : void = Current : transform = Body.GetTransform() # GetLocalForward gives the prop's own +X axis as a unit vector; scale it # by NudgeDistance and add it to the current position. The rotation is # unchanged so the car keeps facing the same way. Forward : vector3 = Current.Rotation.GetLocalForward() Target : vector3 = Current.Translation + Forward * NudgeDistance Body.MoveTo(Target, Current.Rotation, NudgeSeconds) Print("CarPrimitive: car nudged forward.")