Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Projectile Prediction System using a Mesh

Discussion in 'Made With Unity' started by coAdjoint, Apr 2, 2013.

  1. coAdjoint

    coAdjoint

    Joined:
    Jul 18, 2012
    Posts:
    162
    A couple of days ago I posted a video tutorial about mesh creation. I've had a request to make the code available so I show it off and put the code up here.

    Basically it's a mesh of the bounding volume of a projectile released with a small amount of uncertainty in the initial velocity (both magnitude and direction).

    For my application of this I don't actually render the mesh; instead I use a shader I found here to highlight the intersection between two meshes, so that the user can 'see' where a projectile would land. Useful for pulling off grenade tricks.

    Video here (feel free to check out my other videos :D)



    Code here (watch the video for an explanation of getting this up and running. Shouldn't take any time at all)

    Hope you like it, let me know if you have any problems

    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections.Generic;
    4.  
    5. [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
    6. public class MeshTesting : MonoBehaviour {
    7.    
    8.     private float distance;
    9.     private float height = 1.83f;
    10.     private int partNo = 30;
    11.     private int groundRes = 25;
    12.     private Vector2[] groundPos;
    13.     private float newVel;
    14.     private float[] ratio;
    15.     private float g = 9.81f;
    16.     private float initSpeed = 20f;
    17.     private float angle = 0f;
    18.     private float radius = 1f;
    19.     private int particleCounter = 0;
    20.  
    21.     private Mesh mesh;
    22.     private List<Vector3> vertices;
    23.     private int[] triangles;   
    24.     public Transform angleMeasurer;
    25.     private Transform _transform;
    26.     private MeshRenderer meshRenderer;
    27.    
    28.     //private bool isActive = true;
    29.    
    30.     public Transform cube;
    31.    
    32.     private Transform[,] cubeList;
    33.    
    34.     // Use this for initialization
    35.     void Start () {
    36.        
    37.         meshRenderer = GetComponent<MeshRenderer>();
    38.        
    39.         _transform = transform;
    40.         vertices = new List<Vector3>();
    41.         triangles = new int[groundRes*3*partNo*6];
    42.        
    43.         cubeList = new Transform[groundRes,3*partNo];
    44.        
    45.        
    46.         GetComponent<MeshFilter>().mesh = mesh = new Mesh();
    47.         mesh.Clear();
    48.         mesh.name = "TrajectoryMesh";
    49.  
    50.         float temp = 2* Mathf.PI / groundRes;
    51.         groundPos = new Vector2[groundRes];
    52.         ratio = new float[groundRes];
    53.            
    54.         angle = Mathf.Deg2Rad*45f; //angle = Mathf.Deg2Rad*AngleConvert(cam.eulerAngles.x);
    55.         distance = (Mathf.Tan (angle)+Mathf.Sqrt(Mathf.Pow(Mathf.Tan (angle),2f)+height*2f*(g / Mathf.Pow (Mathf.Cos(angle)*initSpeed,2f))))/(g/ Mathf.Pow (Mathf.Cos(angle)*initSpeed,2)); //distance = MidPoint (angle);
    56.                        
    57.         for(int i = 0; i < groundRes; i++)
    58.         {
    59.             float ang = i * temp;
    60.             groundPos[i] = new Vector2(radius*Mathf.Cos (ang),radius*Mathf.Sin (ang));
    61.             float addon = distance + groundPos[i].y;
    62.  
    63.             newVel = height+addon*Mathf.Tan (angle) < 0f ? initSpeed : Mathf.Sqrt(g*Mathf.Pow(addon/Mathf.Cos (angle),2f)/(2f*(height + addon*Mathf.Tan (angle))));
    64.  
    65.             ratio[i] = groundPos[i].x/addon;
    66.            
    67.             for(int j = 0; j < 3*partNo; j++)
    68.             {              
    69.                 float zed = (addon*(j))/partNo;
    70.                 float why = -g*Mathf.Pow (zed,2f)/(2f*Mathf.Pow(Mathf.Cos(angle)*newVel,2f)) + Mathf.Tan (angle)*zed; //float why = TrajectoryHeight(angle, zed, initSpeed);
    71.                 float ecks = ratio[i]*zed;
    72.                 //Debug.Log (instPos + " " + particleCounter);
    73.                 vertices.Add(new Vector3(ecks, why, zed));
    74.                 cubeList[i,j] = Instantiate(cube,  transform.TransformPoint(new Vector3(ecks,why,zed)),Quaternion.identity) as Transform;
    75.                 particleCounter++;
    76.             }          
    77.         }      
    78.        
    79.         mesh.vertices = vertices.ToArray();
    80.        
    81.         for(int i = 0; i < groundRes; i++)
    82.         {
    83.             triangles[3*i + 1] = i*90 + 1;
    84.             triangles[3*i + 2] = (i+1)*90 + 1;         
    85.             if(3*i+2 == 74) triangles[3*i+2] = 1;
    86.         }
    87.        
    88.         for(int j = 0, k = 0; j < 40; j++)
    89.         {
    90.             for(int i = 0; i < groundRes - 1; i++)
    91.             {
    92.                 triangles[74+ 6*k + 1] = 90*i + 1 + j;
    93.                 triangles[74+ 6*k + 2] = 90*i + 2 + j;
    94.                 triangles[74+ 6*k + 3] = 90*(i+1) + 2 + j;
    95.                 triangles[74+ 6*k + 4] = 90*(i+1) + 2 + j;
    96.                 triangles[74+ 6*k + 5] = 90*(i+1) + 1 + j;
    97.                 triangles[74+ 6*k + 6] = 90*i + 1 + j;
    98.                
    99.                 k++;
    100.             }          
    101.            
    102.             triangles[74+ 6*k + 1] = 90*24 + 1 + j;
    103.             triangles[74+ 6*k + 2] = 90*24 + 2 + j;
    104.             triangles[74+ 6*k + 3] = 2 + j;
    105.             triangles[74+ 6*k + 4] = 2 + j;
    106.             triangles[74+ 6*k + 5] = 1 + j;
    107.             triangles[74+ 6*k + 6] = 90*24 + 1 + j;
    108.             k++;
    109.         }
    110.        
    111.         mesh.triangles = triangles;
    112.         }  
    113.    
    114.     void Update()
    115.     {
    116.         if(meshRenderer.enabled)
    117.         {
    118.             float angle = Mathf.Atan((angleMeasurer.position.y - _transform.position.y)/(angleMeasurer.position.x - _transform.position.x));
    119.             vertices.Clear();
    120.            
    121.             int count = 0;
    122.            
    123.             distance = (Mathf.Tan (angle)+Mathf.Sqrt(Mathf.Pow(Mathf.Tan (angle),2f)+height*2f*(g / Mathf.Pow (Mathf.Cos(angle)*initSpeed,2f))))/(g/ Mathf.Pow (Mathf.Cos(angle)*initSpeed,2)); //distance = MidPoint (angle);
    124.    
    125.             for(int j = 0; j < groundRes; j++)
    126.             {
    127.                 float addon = distance + groundPos[j].y < 0 ? -(distance + groundPos[j].y) : distance + groundPos[j].y;
    128.                 float newVel = height+addon*Mathf.Tan (angle) < 0 ? initSpeed : Mathf.Sqrt(g*Mathf.Pow(addon/Mathf.Cos (angle),2f)/(2f*(height + addon*Mathf.Tan (angle))));
    129.                 ratio[j] = groundPos[j].x/addon;
    130.                
    131.                 for(int i = 0; i < 3*partNo; i++)
    132.                 {
    133.                     float zed = (addon*i)/partNo;
    134.                     float why = -g*Mathf.Pow (zed,2f)/(2f*Mathf.Pow(Mathf.Cos(angle)*newVel,2f)) + Mathf.Tan (angle)*zed; //float why = TrajectoryHeight(angle, zed, initSpeed);
    135.                     float ecks = ratio[j]*zed;
    136.                    
    137.                     cubeList[j,i].position = transform.TransformPoint(new Vector3(ecks,why,zed));
    138.                     vertices.Add(new Vector3(ecks,why,zed));
    139.                     count++;
    140.                 }          
    141.             }      
    142.            
    143.             mesh.vertices = vertices.ToArray();
    144.         }
    145.  
     
  2. DScarpelli

    DScarpelli

    Joined:
    Sep 23, 2010
    Posts:
    17
    This is great! Thanks for supplying the code too.
     
  3. poncho

    poncho

    Joined:
    Dec 10, 2010
    Posts:
    65
    I must add, after you have you vertices variable add the uvs

    Code (CSharp):
    1. private List<Vector3> vertices;
    2. private List<Vector2> uvs;
    then in Start method instantiate it after vertices, just for order

    Code (CSharp):
    1. vertices = new List<Vector3>();
    2.         uvs = new List<Vector2>();
    after filling your vertices list, you should be filling your uvs list

    Code (CSharp):
    1. vertices.Add(new Vector3(ecks, why, zed));
    2.                 uvs.Add(new Vector2(ecks, zed));
    then when you have you full list of vertices and uvs, you should let the mesh know them

    Code (CSharp):
    1. mesh.vertices = vertices.ToArray();
    2.         mesh.uv = uvs.ToArray();
    then let the mesh work a little with the info it got after the triangles are set

    Code (CSharp):
    1. mesh.triangles = triangles;
    2.         mesh.RecalculateNormals();
    3.         mesh.RecalculateBounds();
    4.         mesh.Optimize();
    and we are done in code.

    you will need a uv_checker to know what part of the texture you are using
    http://metaverse.mitsi.com/Secondlife/posts/uvmaps/images/uv_checker large.png

    you set the texture to a material and that material to your meshrenderer of the trajectory mesh





    and the result is this

    inside view


    outside view


    also, if you want the mesh to be showing from the outside, the triangle's vertices need to be in other order

    just change the value of the 2 by 3 and 5 by 6 in both cycles and thats it

    old code
    Code (CSharp):
    1. triangles[74+ 6*k + 1] = 90*i + 1 + j;
    2. triangles[74+ 6*k + 2] = 90*i + 2 + j;
    3. triangles[74+ 6*k + 3] = 90*(i+1) + 2 + j;
    4. triangles[74+ 6*k + 4] = 90*(i+1) + 2 + j;
    5. triangles[74+ 6*k + 5] = 90*(i+1) + 1 + j;
    6. triangles[74+ 6*k + 6] = 90*i + 1 + j;
    new code
    Code (CSharp):
    1. triangles[74+ 6*k + 1] = 90*i + 1 + j;
    2. triangles[74+ 6*k + 2] = 90*(i+1) + 2 + j;
    3. triangles[74+ 6*k + 3] = 90*i + 2 + j;
    4. triangles[74+ 6*k + 4] = 90*(i+1) + 2 + j;
    5. triangles[74+ 6*k + 5] = 90*i + 1 + j;
    6. triangles[74+ 6*k + 6] = 90*(i+1) + 1 + j;
    this is the result outside view when normals to the outside


    hope this helps anyone, and again, GREAT POST Tom!
     
    Last edited: Jun 24, 2014
  4. fahd

    fahd

    Joined:
    Aug 7, 2014
    Posts:
    31
    I want the user to add points to the screen and the application will automatic connect them together to create one mesh from these points on runtime is this possible especially that the user can add up to 100 point .