Behind the Scenes of Karol G’s Concert in Fortnite: Combining Creativity and Technical Innovation

Karol G MSB Fortnite was a concert experience built from the ground up in UEFN (Unreal Editor for Fortnite). Throughout the five-part playable concert, users collected EmPower-Ups to blast away negative energy and spread positive vibes in a neon-drenched party. The experience introduced Karol G’s infectious Latin rhythms to newcomers while offering longtime fans a new way to enjoy her music. The creative and technical elements worked hand-in-hand to create a vibrant, digital world. We sit down with some of the team to learn about the making of Karol G MSB Fortnite.

Kevin Hanna, Creative Director, was instrumental in the concert’s creation. We ask him how the project came to life: "UEFN was crucial from the start. The ability to rapidly iterate was game-changing. We didn’t just want to create a passive event – we wanted it to feel like an interactive music video, where every moment meant something to the player. Whether creating special effects or ensuring that enemies moved in time with the beat, UEFN allowed us to play with those elements without a lot of downtime. That flexibility let us focus on crafting an experience that was as interactive as it was visually engaging."

One fan-favorite sequence was the waterslide, where players raced alongside Karol G while blasting away enemies. Hanna elaborates: "That waterslide sequence went through several iterations – five fully playable versions – before we finalized the one with the Joy Cannon. With UEFN, we could snap things together, test them in real-time, and see how they felt in context. The real-time adjustments meant we could experiment, fail fast, and move on, which ultimately helped us create something players really connected with."

Addison Herr Lead Designer, tells us about cross-discipline collaboration. “With the real-time feedback loop, we could prototype and test ideas immediately, whether it was gameplay or audiovisual elements. I worked closely with the art department as well as our other designers, Daryl Kimoto, Gladeline Rufo, and Thomas Wilson, and we were constantly learning from one another – they explored the intricacies of building complex mechanics in UEFN, while I gave input on audio-reactivity, shaders, and game feel. We pulled from our diverse backgrounds, ranging from rhythm game design to real-world concert visuals – to find a sweet spot of merging the spectacle of an arena show with satisfying interactivity.”

We ask Lisa Barber, the environment artist responsible for much of the concert’s look, how UEFN assisted in building the environments. "UEFN’s asset library was a lifesaver. We needed a huge variety of very specific visuals – like glowing, iridescent mountains, beautiful pink foliage, and over five different unique settings – UEFN made it easy to find what we needed. It meant we could focus on perfecting the world rather than getting bogged down in technicalities."

Motion capture was part of the production process, Gabriela Montes, Rigger, explains its role in detail. “We used motion capture for everything related to Karol G’s performance, from her dance moves to facial expressions. UEFN’s character device allowed us to play the motion capture on various character types, outside of Karol G herself,  with the click of a button! This flexibility meant that her character animations, as dynamic and lifelike as they were, could easily be leveraged for use throughout the project, like for the background dancers.”

Montes continues, “The amazing motion capture quality was all thanks to the people at Yoom Studios, Metastage, and Brazen Animation. Yoom captured data that consisted of facial data, body movement, and lipsync in one cohesive file, with production and facilitation effort from Metastage, while Brazen Animation added their animators' touch. All of this was critical for a project of this scale.”

Creating custom arcade shooting mechanics 

On the technical side, Derrick Canfield, Engineering Lead, who was responsible for the arcade shooting mechanics discusses in detail how that came together, starting with the design.

“One challenge was finding a way to implement custom arcade shooting mechanics that aligned with Fortnite’s fast-paced environment, while ensuring it wasn’t too difficult for casual players. We used UEFN to build custom devices that allowed us to control shooting mechanics and create unique physics for the targets. This way, players could get instant feedback without overwhelming them with too much complexity.

He continues, breaking down the core mechanics, “One of those mechanics was an arcade-style shooting section while players rode on a waterslide as Karol G performed. Here, we chose to have shots fired from the player instantly travel to the target, rather than simulating the arc of a projectile. This approach provided instant feedback, enhanced the arcade-like feel, and simplified our logic. Additionally, because all enemies were close to the player, the projectile's travel time would be negligible.”

Canfield explains how the problem was further simplified, “we opted to use spheres as the collision volumes for the targets. Raycasting against a sphere is fairly trivial, and we wanted the shooting to be forgiving in this experience. So, even if you aimed slightly above the shark's head, you'd still be rewarded as if you hit the target.”

Using Verse, Epic Games' programming language for UEFN

Next, we hear how Verse was used, “We created a module named “Physics” with a function for ray-sphere collision testing.

#Copyright (c) Magnopus. All Rights Reserved.
using { /UnrealEngine.com/Temporary/SpatialMath }

Physics<public> := module:

    RaySphereTest<public>(RayOrigin:vector3, RayDirection:vector3, SphereCenter:vector3, SphereRadius:float)<transacts><decides>:float=
        M := RayOrigin - SphereCenter
        B := DotProduct(M, RayDirection)
        C := M.LengthSquared() - SphereRadius * SphereRadius

        # We know they do not intersect so we can exit early with a `false` value
        not (C > 0.0 and B > 0.0)

        Discriminant := B*B - C

        # When the discriminant is negative, the ray and sphere do not intersect
        not (Discriminant < 0.0)
        
        option{ Max(0.0, -B - Sqrt(Discriminant)) }?

The function accepts an origin and direction for a ray, as well as a sphere center and radius. If the ray passes through the sphere, the distance between the ray’s origin and the hit point is returned. If there is no intersection, the function fails using Verse’s <decides> specifier.”

For those new to Verse, Derrick explains its unique specifiers, “Unique specifiers, such as <decides> and <transacts>, play a crucial role in controlling how functions behave and interact with the game state.

  • <decides>: This specifier is used when a function needs to determine or "decide" a result that may not always produce a value. For example, in our ray-sphere collision test, <decides> is used because the function may or may not find a collision point, depending on whether the ray intersects the sphere.

  • <transacts>: This specifier indicates that a function can modify or "transact" changes to the game state. It’s particularly important when you need to ensure that operations happen in a controlled, atomic manner, such as updating scores or player positions in real-time.

For those looking to deepen their understanding of these terms and other unique elements of Verse, we recommend checking out Epic's Glossary of Terms. This resource provides detailed explanations and examples, making it easier to get up to speed with the language’s capabilities and best practices.”

Arcade Shooter Minigame Devices

Canfield, walks us through how the custom Verse devices for the arcade shooter minigame were developed, especially the mechanics behind the target system and how it all comes together during gameplay.

“The target system is pretty straightforward. We created a device that holds a reference to a prop of our choice, along with a collider radius. The internal logic manages the target's state—whether it's active or not—and includes functions for spawning, despawning, and handling what happens when the target is hit. This code is barebones so a creator can extend it for their island’s needs.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

arcade_target_device := class(creative_device):
    @editable
    Prop<private>:creative_prop = creative_prop{}
    
    @editable
    ColliderRadius<public>:float = 150.0

    var Active<private>:logic = true

    OnBegin<override>()<suspends>:void=
        Despawn()

    IsActive<public>()<transacts><decides>:void=
        Active?
        
    Spawn<public>():void=
        Prop.Show()
        set Active = true

    Despawn<public>():void=
        Prop.Hide()
        set Active = false

    Hit<public>(Agent:agent):void=
        # Add particle effects, sound effects, etc
        Despawn()

The minigame kicks off when the player steps on a trigger and ends when a timer runs out. 

using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { Physics }

arcade_shooter_minigame_device := class(creative_device):

    @editable
    BeginMinigameTrigger:trigger_device = trigger_device{}

    @editable
    EndGameTimer:timer_device = timer_device{}

    @editable
    FireTrigger:input_trigger_device = input_trigger_device{}
    
    @editable
    WeaponGranter:item_granter_device = item_granter_device{}
    
    @editable
    Targets:[]arcade_target_device = array{}

    var FireTriggerCancellable:?cancelable = false

    OnBegin<override>()<suspends>:void=
        BeginMinigameTrigger.TriggeredEvent.Subscribe(BeginMinigame)
        EndGameTimer.SuccessEvent.Subscribe(EndMinigame)

    BeginMinigame<private>(MaybeAgent:?agent):void=
        BeginMinigameTrigger.Disable()

        # Give all players a gun to use
        for(Player:GetPlayspace().GetPlayers()):
            WeaponGranter.GrantItem(Player)

        # Enable the fire trigger and listen for fire events
        FireTrigger.Enable()
        set FireTriggerCancellable = option { FireTrigger.PressedEvent.Subscribe(OnFirePressed) }

        # Spawn all targets
        for (Target:Targets):
            Target.Spawn()

        # Start the timer
        EndGameTimer.Start()

    EndMinigame<private>(MaybeAgent:?agent):void=
        BeginMinigameTrigger.Enable()
        
        # Disable the fire trigger and remove the event callback
        FireTrigger.Disable()
        if (EventCancellable := FireTriggerCancellable?):
            EventCancellable.Cancel()
        
        # Despawn any targets that still remain
        for (Target:Targets):
            Target.Despawn()

        # Reset the timer for the next time the minigame is played
        EndGameTimer.Reset()

    BulletRaycast<private>(GunAimDirection:vector3, GunPosition:vector3, Target:arcade_target_device)<transacts><decides>:vector3=
        # Execute a ray-sphere cast to see if we hit the target
        TargetTranslation := Target.GetTransform().Translation
        HitDistance := RaySphereTest[GunPosition, GunAimDirection, TargetTranslation, Target.ColliderRadius]
    
        # If the target is hit, reconstruct the hit position that will be returned by this function
        HitPosition := GunAimDirection * HitDistance + GunPosition
        option{HitPosition}?

    OnFirePressed<private>(Agent:agent):void=
        if (FortChar := Agent.GetFortCharacter[]):
            PlayerTranslation := FortChar.GetTransform().Translation
            CameraRotation := FortChar.GetViewRotation()

            # Iterate through all active targets to see if any were hit
            for (Target : Targets, Target.IsActive[], HitPosition := BulletRaycast[CameraRotation.GetLocalForward(), PlayerTranslation, Target]):
                Target.Hit(Agent)

In the OnBegin function, we assign BeginMinigameTrigger to our logic to start the minigame as well as setting EndGameTimer’s completion event to the logic that ends it. 

Once it starts, we grant all players a gun and enable an input trigger that listens for when they fire. When they press “fire”, it runs the raycast logic we set up earlier to check if they hit any active targets. If a target is hit, we trigger the Hit(agent) function on the target. From there you can add any additional logic you need, such as custom scoring or integration with any other game mechanics.”

Visualizing Logic with Debug Draws

Derrick dives into how debug draws can help when developing. “Debug draws are incredibly valuable when it comes to visualizing the logic in your code, particularly for something as intricate as ray-sphere collisions. In our case, you could use them to visually trace the ray’s path and define the boundaries of the sphere within the game environment. This kind of visualization lets you see exactly where the ray intersects the sphere or if it misses entirely, making it much easier to debug and refine your collision logic.

For example, you can draw the ray with DrawDebugLine and the sphere with DrawDebugSphere. By doing so, you get instant visual feedback right in the game world, which helps confirm that your collision detection is functioning properly.”

Bringing it all together 

Derrick tells us how to bring everything together in the level, especially when setting up player input and devices for the minigame, “We set up all of the devices in the level and hooked them together.

The first item we set up was the input trigger for the player’s fire action. To do that, add an Input Trigger device to your scene. Set “Input Type” to “Standard Action”, and “Standard Input” to “Fire”. This will make the input trigger when any player presses the fire button.

Next, you’ll need an Item Granter to give the player a weapon to shoot the targets. I chose a rifle, but you can pick whatever fits your theme best. After that, you need to create a Trigger Device and a Timer Device. Both of these devices work well with their default settings, but you might want to adjust the timer duration to suit the experience you're crafting.

Derrick goes on to talk about the fun part - targets to shoot at! 

“Create an Arcade Target Device which you can find wherever your Arcade Target Device logic exists within your project. Disable “Visible in Game” so the terminal mesh is not rendered. Also, find a prop to be the visual representation of your target and parent it underneath the Arcade Target Device. Adjust the prop so that the center point is aligned with the origin of the device’s mesh. In this example, I’ve chosen a disco ball and you can see it aligned to the center of the bottom of the console mesh which is the pivot point. With the Arcade Target Device selected, set “Prop” to the prop you created and set a collider radius to a value that would encapsulate the prop.

Then, select the prop and set the property “Can be Damaged” to false. This ensures the default shooting logic in Fortnite doesn’t damage and destroy the prop. Our Verse logic is handling the destruction effects already! Duplicate the device and prop as often as you like and place them around your map as you see fit.”

We ask Canfield about the final inclusion, “That’s the Arcade Shooter Minigame device. Create an instance by dragging it from the Content Browser wherever you saved the Verse file in your project. Again, set “Visible in Game” to false to hide the default terminal mesh. Set BeginMinigameTrigger to the trigger created earlier, EndGameTimer to the timer created, FireTrigger to the input trigger, and WeaponGranter to the weapon granter we set up. Then for Targets, add every copied target to this array. You may want to click the lock icon in the top-right corner of the Details Panel so it doesn’t change to show the properties of the arcade targets if you drag and drop references into the Targets array.”

He concludes, “You can now jump into a session and play through the minigame. Step on the trigger to equip yourself with a gun and show all of the targets. Pull out your weapon and shoot the targets before your time runs out! If you follow these instructions you’ll have a fully functioning arcade-style shooter! The minigame is barebones, ready to be expanded upon with whatever fits the creator's needs – a custom scoring system, special effects, custom meshes for your targets, and more!” 

Finally, we asked how the concert was received by both the audience and your team. Herr tells us, "We were unsure how people would react at first, but the feedback was incredible. It was especially meaningful to see the response from fans in a number of languages across social media platforms, particularly during the closing dance-off and in the epilogue. The climactic scenes of the experience celebrated unity and empowerment, and to see people across the world connect with all the love and care we poured into this concert was so rewarding."

Montes adds, "As a Latina artist, it was personally significant for me. Being able to share this project with my family, especially in a Spanish-speaking context, was really special. The emotional impact extended beyond the audience – it resonated with us as creators."

Previous
Previous

Meet the Magnopians: Sian Adeoye

Next
Next

AJ Sciutto speaks to Meta about the creation of Alo Moves XR