Player trail issues (TRON)

Hello, I recently made a topic about the rotation of my player’s trail wich is solved. But I’m now encountering several issues :
1 - The game’s fps drops over time due to trail generation, but I want it to stay until the player dies.
2 - I tried tweaking my script to directly remove the trail when dying but it still delays the removal.
3 - I added a jump to the player but the trail is jerky and I want it to be “clean” :


This is the script I’m using for the trail generation (I tweaked it a bit but it’s still from him : https://www.youtube.com/watch?v=BIKYK8qbdG0) :

using System.Collections.Generic;
using UnityEngine;

public class TrailMeshGenerator : MonoBehaviour
{
    [SerializeField] Transform followPos;
    [SerializeField] float height = 1f;
    [SerializeField] float width = 0.001f;
    [SerializeField] float destroyTrailAfterSecond;
    [SerializeField] Material trailMaterial;
    [SerializeField] float spawnDelay = 0.01f;
    public TimerScript timer;
    public float yAngleRotation;
    public DeathScript death;


    bool firstTime = true;
    GameObject trail;
    MeshFilter meshFilter;
    MeshCollider meshCollider;
    List<Vector3> verticesDef;
    List<int> triangleDef;
    bool isEven = true;
    int x;
    float currentSpawnTrailTime = 0;


    const string addMeshstrName = "AddMesh";

    public void SetFollowPos(Transform pos)
    {
        followPos = pos;
    }

    void Start()
    {
        if (followPos == null)
        {
            Debug.LogError("followPos is not assigned in TrailMeshGenerator.");
            return;
        }

        meshFilter = GetComponent<MeshFilter>();
        if (meshFilter == null)
        {
            Debug.LogError("MeshFilter is missing in TrailMeshGenerator.");
            return;
        }

        InvokeRepeating(addMeshstrName, 0, spawnDelay);
    }


    public void AddMesh()
    {
        MonoLine();
        /*if (currentSpawnTrailTime > destroyTrailAfterSecond)
        {
            RemoveMesh();
        }*/
        if (death.isAlive == false)
        {
            RemoveMesh();
        }
    }

    void Update()
    {
        currentSpawnTrailTime += Time.deltaTime;

        if (timer.isO == true)
        {

            if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow))
            {
                // Rotation à gauche
                transform.Rotate(0f, -yAngleRotation, 0f);
            }

            if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow))
            {
                // Rotation à droite
                transform.Rotate(0f, yAngleRotation, 0f);
            }
        }
    }



    private void MonoLine()
    {


        Vector3[] vertices = null;
        int[] triangles = null;

        var backward = followPos.transform.position - (followPos.transform.forward);


        if (firstTime)
        {
            vertices = new Vector3[]
            {
            backward + (followPos.transform.right * -width),
            backward - (followPos.transform.right * -width),
            backward - (followPos.transform.right * -width) + followPos.transform.up * height,
            backward + (followPos.transform.right * -width) + followPos.transform.up * height,
            };

            triangles = new int[]
            {
            0, 2, 1,
            0, 3, 2,
            };

            trail = new GameObject();
            trail.tag = "Head Trails";
            trail.layer = LayerMask.NameToLayer("Trail");

            meshFilter = trail.AddComponent<MeshFilter>();
            trail.AddComponent<MeshRenderer>().material = trailMaterial;

            meshCollider = trail.AddComponent<MeshCollider>();
            meshCollider.sharedMesh = meshFilter.mesh;

            verticesDef = new List<Vector3>();
            triangleDef = new List<int>();

            foreach (var v in vertices)
                verticesDef.Add(v);
            foreach (var t in triangles)
                triangleDef.Add(t);

            meshFilter.mesh.vertices = vertices;
            meshFilter.mesh.triangles = triangles;

            isEven = false;
            firstTime = false;

            x = 4;
            return;

        }

        if (isEven)
        {
            verticesDef.Add(backward + (followPos.transform.right * -width));
            verticesDef.Add(backward - (followPos.transform.right * -width));
            verticesDef.Add(backward - (followPos.transform.right * -width) + followPos.transform.up * height);
            verticesDef.Add(backward + (followPos.transform.right * -width) + followPos.transform.up * height);

            //left face
            triangleDef.Add(x - 4); //0
            triangleDef.Add(x - 1); //3
            triangleDef.Add(x);     //4

            triangleDef.Add(x - 4); //0
            triangleDef.Add(x);     //4
            triangleDef.Add(x + 3); //7

            //top face
            triangleDef.Add(x - 4); //0
            triangleDef.Add(x + 3); //7
            triangleDef.Add(x + 2); //6

            triangleDef.Add(x - 4); //0
            triangleDef.Add(x + 2); //6
            triangleDef.Add(x - 3); //1

            //right face
            triangleDef.Add(x - 3); //5
            triangleDef.Add(x + 2); //10
            triangleDef.Add(x + 1); //9

            triangleDef.Add(x - 3); //5
            triangleDef.Add(x + 1); //9
            triangleDef.Add(x - 2); //6

            isEven = false;

        }
        else
        {
            verticesDef.Add(backward + (followPos.transform.right * -width) + followPos.transform.up * height);
            verticesDef.Add(backward - (followPos.transform.right * -width) + followPos.transform.up * height);
            verticesDef.Add(backward - (followPos.transform.right * -width));
            verticesDef.Add(backward + (followPos.transform.right * -width));

            //left face
            triangleDef.Add(x - 4); //0
            triangleDef.Add(x + 3); //7
            triangleDef.Add(x);     //4

            triangleDef.Add(x - 4); //0
            triangleDef.Add(x);     //4
            triangleDef.Add(x - 1); //3

            //top face
            triangleDef.Add(x - 2); //2
            triangleDef.Add(x - 1); //3
            triangleDef.Add(x);     //4

            triangleDef.Add(x - 2); //2
            triangleDef.Add(x);     //4
            triangleDef.Add(x + 1); //5

            //right face
            triangleDef.Add(x - 3); //5
            triangleDef.Add(x - 2); //6
            triangleDef.Add(x + 1); //9

            triangleDef.Add(x - 3); //5
            triangleDef.Add(x + 1); //9
            triangleDef.Add(x + 2); //10

            isEven = true;
        }
        x += 4;

        meshFilter.mesh.vertices = verticesDef.ToArray();
        meshFilter.mesh.triangles = triangleDef.ToArray();

        meshCollider.sharedMesh = meshFilter.mesh;

        // Debug.Log(x +" bounds->" +meshFilter.mesh.bounds.size.magnitude);

    }

    private void RemoveMesh()
    {
        // Remove 4 vertices
        verticesDef.RemoveRange(0, 4);

        // Remove 18 triangles
        triangleDef.RemoveRange(triangleDef.Count - 18, 18);

        // Clear the mesh
        meshFilter.mesh.Clear();

        // Set vertices and triangles
        meshFilter.mesh.vertices = verticesDef.ToArray();
        meshFilter.mesh.triangles = triangleDef.ToArray();

        // Update x
        x -= 4;
    }
}

I greatly appreciate any help :slight_smile:

Maybe not accessing object.transform.right a million times per frame if you can calculate and store it once would speed up the mesh generator considerably.
Consider using Burst jobs for the generator. Seems like a very burstable operation, and could speed everything up a hundred times (no kidding).

The jerkiness could come from the fact that you are using a rigidbody without interpolation, which means its position update is desynced from the Update(). For the most stable results, I’d suggest to update the trail from FixedUpdate (so you don’t get gaps or straight lines if there’s a long frame for whatever reason), but enabling the interpolation could do the trick.

Also, consider using native arrays for mesh updating. There’s a lot of unnecessary allocation and array copying from place to place in your code. Use Mesh.SetVertexBufferData instead.

No idea what you mean by the delayed removal.

I couldn’t figure out how to use bursts lol but I looked for using interpolation and using Fixed Update and this is the result : https://www.youtube.com/watch?v=7U8cCT9ZpUs

As you can see, the camera bugs and I couldn’t properly jump nor turn. But the jump trails are actually a little smoother.

Also, you can see at the end that the trail takes way too long to disappear