How to keep 3D fig traces when animating with plotly frames

I am trying to create an animated basketball shot chart. This is what the court looks like originally.

I am trying to add frames to animate a shot path going into the hoop.

When I press play to view the animation, the court turns into this.

Is there a way to fix this so the court doesn’t lose the traces it originally had? It seems like the bigger the batch is, the more traces are removed until it just becomes a plain court with nothing on it.

This is the code for the fig and the frames. I would appreciate any help. Thanks

#code for creating the court
court = CourtCoordinates(season)
court_lines_df = court.get_coordinates()
# st.write(court_lines_df)
fig = px.line_3d(
    data_frame=court_lines_df,
    x='x',
    y='y',
    z='z',
    line_group='line_group_id',
    color='line_group_id',
    color_discrete_map={
        'court': 'black',
        'hoop': '#e47041',
        'net': '#D3D3D3',
        'backboard': 'gray',
        'free_throw_line': 'black',
        'hoop2':'#D3D3D3',
        'free_throw_line2': 'black',
        'free_throw_line3': 'black',
        'free_throw_line4': 'black',
        'free_throw_line5': 'black',
    }
)
fig.update_traces(hovertemplate=None, hoverinfo='skip', showlegend=False)
fig.update_traces(line=dict(width=6))
fig.update_layout(    
    margin=dict(l=20, r=20, t=20, b=20),
    scene_aspectmode="data",
    height=600,
    scene_camera=dict(
        eye=dict(x=1.3, y=0, z=0.7)
    ),
    scene=dict(
        xaxis=dict(title='', showticklabels=False, showgrid=False),
        yaxis=dict(title='', showticklabels=False, showgrid=False),
        zaxis=dict(title='',  showticklabels=False, showgrid=False, showbackground=False, backgroundcolor='#d2a679'),
    ),
    showlegend=False,
    legend=dict(
        yanchor='top',
        y=0.05,
        x=0.2,
        xanchor='left',
        orientation='h',
        font=dict(size=15, color='gray'),
        bgcolor='rgba(0, 0, 0, 0)',
        title='',
        itemsizing='constant'
    )
)
court_perimeter_bounds = np.array([[-250, 0, 0], [250, 0, 0], [250, 450, 0], [-250, 450, 0], [-250, 0, 0]])

# Extract x, y, and z values for the mesh
court_x = court_perimeter_bounds[:, 0]
court_y = court_perimeter_bounds[:, 1]
court_z = court_perimeter_bounds[:, 2]

# Add a square mesh to represent the court floor at z=0
fig.add_trace(go.Mesh3d(
    x=court_x,
    y=court_y,
    z=court_z,
    color='lightgray',
    opacity=0.5,
    name='Court Floor',
    hoverinfo='none',
    showscale=False
))


#code for adding frames
frames = []
num_points = 100

# Function to process shots in batches
def process_shots_in_batches(shotdf, batch_size=3):
    # Split shotdf into batches of size batch_size
    for batch_start in range(0, len(shotdf), batch_size):
        batch_end = min(batch_start + batch_size, len(shotdf))
        batch = shotdf[batch_start:batch_end]
        yield batch

# Generate frames for each batch
for batch in process_shots_in_batches(shotdf, batch_size=2):
    # For each batch, generate the frames with growing arcs for all shots in the batch
    for t in np.linspace(0, 1, 10):  # Adjust number of frames for smoothness
        frame_data = []
        
        # For each shot in the batch, generate its arc and add to the frame data
        for i, row in batch.iterrows():
            x1 = int(row['x'])
            y1 = int(row['y'])
            x2 = court.hoop_loc_x
            y2 = court.hoop_loc_y
            p2 = np.array([x1, y1, 0])
            p1 = np.array([x2, y2, 100])

            # Calculate the arc height based on shot distance
            if row['shotDist'] > 3:
                distance = calculate_distance(x1, y1, x2, y2)
                if row['shotDist'] > 50:
                    h = np.random.randint(275, 325)
                elif row['shotDist'] > 30:
                    h = np.random.randint(250, 300)
                elif row['shotDist'] > 25:
                    h = np.random.randint(200, 250)
                elif row['shotDist'] > 15:
                    h = np.random.randint(200, 250)
                else:
                    h = np.random.randint(150, 200)

            apex = np.array([0.5 * (x1 + x2), 0.5 * (y1 + y2), h])
            x, y, z = generate_arc_points(p2, p1, apex, num_points)

            # Calculate the portion of the arc to show for the current frame
            frame_x = x[:int(len(x)*t)]
            frame_y = y[:int(len(y)*t)]
            frame_z = z[:int(len(z)*t)]

            # Add the arc to the frame data
            frame_data.append(go.Scatter3d(
                x=frame_x, y=frame_y, z=frame_z,
                mode='lines', line=dict(width=6, color='green')
            ))

        # Add the frame with all 5 shots to the frames list
        frames.append(go.Frame(
            data=frame_data,
            # name=f'Frame_batch_{batch[0]["x"]}_{int(t*100)}'
        ))

# Add an initial empty trace (just for layout)
fig.add_trace(go.Scatter3d(x=[], y=[], z=[]))

# Add frames to the figure
fig.frames = frames

fig.update_layout(
    updatemenus=[
        dict(type="buttons",
             showactive=False,
             buttons=[
                 dict(label="Play",
                      method="animate",
                      args=[None, {"frame": {"duration": 100, "redraw": True}, "fromcurrent": True}]),
                 dict(label="Pause",
                      method="animate",
                      args=[[None], {"frame": {"duration": 0, "redraw": False}, "mode": "immediate"}])
             ])
    ],
    # scene=dict(
    #     xaxis_title="X",
    #     yaxis_title="Y",
    #     zaxis_title="Z",
    #     aspectratio=dict(x=1, y=1, z=0.5)
    # ),
    # title="3D Shot Animation with Growing Lines",
)