Modifying vertices of a mesh during runtime

Unity Community,
I have seen several instances of how to modify the vertices within a mesh but I have been stumped for the better part of the day trying to make a script work properly. For a tower defense game, the laser turrets have a super ability where they all point to a single laser turret and add their energy (think Deathstar). I was originally utilizing a line renderer with no issues but it significantly increased the draw call. Now I am utilizing a dynamically generated plane as the laser which allows me to benefit from batching. Everything worked great up until the activation of the super ability. The two vertices which are supposed to represent the position of the turret in super mode appear to be correct as shown in the graphic. I have debug log information along with a screenshot to demonstrate the problem. What am I missing with the vertices modification which prevents the ‘support turret’ from shooting at the Super Laser on the left?

//LaserTurrets is the reference to the Super Laser
public void LaserSupport(GameObject SuperTurret){

//Muzzle gameobject is the position just at the front of the barrel.
Vector3[] vert = new Vector3[]{
   new Vector3(Muzzle.transform.localPosition.x+(LineWidth/2),0,Muzzle.transform.localPosition.z), //0 

   new Vector3(SuperTurret.transform.position.x+(LineWidth/2),SuperTurret.transform.localPosition.y,SuperTurret.transform.position.z),  //1

   new Vector3(SuperTurret.transform.position.x-(LineWidth/2),SuperTurret.transform.localPosition.y,SuperTurret.transform.position.z), //2
            
new Vector3(Muzzle.transform.localPosition.x-(LineWidth/2),0,Muzzle.transform.localPosition.z),//3
        };

        Debug.Log ("Value of Vert0: " + vert[0]);
        Debug.Log ("Value of Vert1: " + vert[1]);
        Debug.Log ("Value of Vert2: " + vert[2]);
        Debug.Log ("Value of Vert3: " + vert[3]);

        int[] tris = new int[]{
            0,1,2,
            0,2,3
        };
       
        Vector3[] normals = new Vector3[]{
            new Vector3(-1,0,1), //0
            new Vector3(1,0,1),  //1
            new Vector3(1,0,-1), //2
            new Vector3(-1,0,-1),//3
        };
       
        Vector2[] uv = new Vector2[]{
            new Vector2(0,0),
            new Vector2(1,0),
            new Vector2(1,1),
            new Vector2(0,1)
        };
       
        Mesh mesh = new Mesh ();
        mesh.vertices = vert;
        mesh.normals = normals;
        mesh.uv = uv;
        mesh.triangles = tris;
       
        mesh.RecalculateNormals ();
       
        if(!GetComponent<MeshFilter>()){
            gameObject.AddComponent<MeshFilter>();
        }
        if(!GetComponent<MeshRenderer>()){
            gameObject.AddComponent<MeshRenderer>();
        }
       
        gameObject.GetComponent<MeshRenderer> ().material = LineMaterial;
        this.GetComponent<MeshFilter> ().renderer.enabled = true;
        gameObject.GetComponent<MeshFilter> ().mesh = mesh;
    }

The super turret is currently shooting the enemies while the ‘support turret’ is shooting off into nowhere.

Vertex positions need to be in local space, you are using the worldspace position of the superturret
muzzle.transform.InverseTransformPoint(superturret.position)

1 Like

I tested out a few different ways of setup and am now at a new problem which I had before.

    //LaserTurrets is the reference to the Super Laser
    public void LaserSupport(GameObject SuperTurret){
        //Transform SuperTurretLocal = SuperTurret.transform;
        //Vector3 SuperTurretWorld = SuperTurret.transform.InverseTransformPoint (SuperTurretLocal.transform.position);
        //Muzzle gameobject is the position just at the front of the barrel.
        Vector3[] vert = new Vector3[]{
            new Vector3(Muzzle.transform.localPosition.x+(LineWidth/2),0,Muzzle.transform.localPosition.z), //0
            new Vector3(SuperTurret.transform.localPosition.x+(LineWidth/2),SuperTurret.transform.localPosition.y,SuperTurret.transform.localPosition.z),  //1
            new Vector3(SuperTurret.transform.localPosition.x-(LineWidth/2),SuperTurret.transform.localPosition.y,SuperTurret.transform.localPosition.z), //2
            new Vector3(Muzzle.transform.localPosition.x-(LineWidth/2),0,Muzzle.transform.localPosition.z),//3
        };

        Debug.Log ("Value of Vert0: " + vert[0]);
        Debug.Log ("Value of Vert1: " + vert[1]);
        Debug.Log ("Value of Vert2: " + vert[2]);
        Debug.Log ("Value of Vert3: " + vert[3]);

The commented out code where I used InverseTransformPoint demonstrated the same results as using SuperTurret.transform.localPosition. The laser is now pointing in the correct direction but is too small. The second screenshot shows where I moved the laser out from under the mesh which was hiding it. Within the reference it says that it can be influced by scale. Is this my new problem?

Thanks for helping me troubleshoot this error. I had a feeling it was an issue with the coordinate system and I feel like I am close to resolution.

Finally got it to work properly! Thanks for pointing me in the correct direction with this. The scaling of some parent objects were throwing off the values but I was able to pass in a variable which allowed me to calculate the length of the laser beam. Results are perfect!

    //LaserTurrets is the reference to the Super Laser
    public IEnumerator LaserSupport(GameObject SuperTurret, float LaserLength){

        //Muzzle gameobject is the position just at the front of the barrel.
        Vector3[] vert = new Vector3[]{
            new Vector3(Muzzle.transform.localPosition.x+(LineWidth/2),0,Muzzle.transform.localPosition.z), //0
            new Vector3(SuperTurret.transform.localPosition.x+(LineWidth/2),SuperTurret.transform.localPosition.y,LaserLength),  //1
            new Vector3(SuperTurret.transform.localPosition.x-(LineWidth/2),SuperTurret.transform.localPosition.y,LaserLength), //2
            new Vector3(Muzzle.transform.localPosition.x-(LineWidth/2),0,Muzzle.transform.localPosition.z),//3
        };

Thanks again for the help!