2D raycasting C# help

I’ve created a script which I attach to an empty game object, the idea of the script is to cast 2 rays which will hit the ground in my game, I will then use the location of the 2 hit’s and the origin of the game object to draw a triangular mesh. The mesh is to represent a vision cone from an enemy which travels along the top of the screen.

Here is the error
(it’s occuring on line 42: “vertexTwo.x = hitPointLeft.transform.position.x;”)

ERROR:
“NullReferenceException: Object reference not set to an instance of an object
rayCast.generateMesh () (at Assets/Scripts/Cloud Monster/rayCast.cs:42)
rayCast.Update () (at Assets/Scripts/Cloud Monster/rayCast.cs:34)”

Here is the script:

using UnityEngine;
using System.Collections;

public class rayCast : MonoBehaviour {

	//Set up public ints for angle to rayCast at
	public int leftAngle = 0;
	public int rightAngle = 0;
	//Create two vector2's to represent the directions of the two rayCasts; 
	Vector2 directionLeft = new Vector2 ();
	Vector2 directionRight = new Vector2 ();
	//Create two rayCast2D's to represent the collision locations of the rayCasts which will be updated each frame
	RaycastHit2D hitPointLeft = new RaycastHit2D ();
	RaycastHit2D hitPointRight = new RaycastHit2D ();


	//Set the directions up
	void Start () {
		//Always keep the y values at -100 (i.e. well below the stage),
		//then we can just update the x values to change where the cone is "looking"
		directionLeft.x = this.transform.rotation.x - leftAngle;
		directionLeft.y = this.transform.rotation.y - 100;
		directionRight.x = this.transform.rotation.x + rightAngle;
		directionRight.y = this.transform.rotation.y - 100;
	}

	//Update the left/right hitPoint variables with the new collision location
	//After I've got this set up I'll add in updating the rayCast direction each frame as well.
	void Update () {
		//This puts the  if the rayCast is hitting something, then puts the coordinates of the collision into the rayCast2D objects
		hitPointLeft = Physics2D.Raycast (this.transform.position, directionLeft);
		hitPointRight = Physics2D.Raycast (this.transform.position, directionRight);
		//Run the generateMesh function to update the mesh position
		generateMesh ();
	}


	void generateMesh () {
		Debug.Log (hitPointLeft.transform);
		//Create a vector3 to represent the 2nd vertex of the triangle
		Vector3 vertexTwo = new Vector3();
		vertexTwo.x = hitPointLeft.transform.position.x;
		vertexTwo.y = hitPointLeft.transform.position.y;
		vertexTwo.z = 0; //z = 0 because we're 2D
			
		//Create a vector3 to represent the 3rd vertex of the triangle
		Vector3 vertexThree = new Vector3();
		vertexThree.x = hitPointRight.transform.position.x;
		vertexThree.y = hitPointRight.transform.position.y;
		vertexThree.z = 0;  //z = 0 because we're 2D
			
		//Create a vector3 array to store the vertex locations
		Vector3[] meshVerts = new Vector3[3];
		meshVerts[0] = this.transform.position;
		meshVerts[1] = vertexTwo;
		meshVerts[2] = vertexThree;
			
		//Apply the vertex array to the mesh
		Mesh visionCone = new Mesh();
		visionCone.vertices = meshVerts;
		visionCone.RecalculateBounds();
			
		//Add the mesh to a meshFilter attached to the game object
		this.gameObject.GetComponent<MeshFilter> ().mesh = visionCone;
		Graphics.DrawMeshNow(this.gameObject.GetComponent<MeshFilter>().mesh, this.transform.position, this.transform.rotation);
	}

	//This will be run each frame and will remove the previous frames mesh
	//STILL NEEDS DOING!
	void garbageCollection () {

	}
}

Anyone got any ideas?

Are those raycasts getting hits?

Yes, I’ve tried logging the RaycastHit2D.point to the debug log and it would appear they are getting hits (the vector2 for the hit point changes as the various components of my scene move around indicating that the ray casts are hitting something).

I’ve also used debug.drawRay() to check that my rays are casting in the correct direction, so I’m 99% sure that my rays are hitting stuff.

I’m fairly sure my problem is actually in generating the mesh from the point data, I have tried logging the mesh vertex locations and it’s showing that the mesh has recieved the vertices correctly, so it would appear the mesh is just not rendering to the screen. I’ve heard about normals, so I’ve rotated the camera around to see if the normals were pointing the wrong way but still not seeing any rendered mesh :frowning:

Help me! :smile:

UPDATE:

I’ve removed the mesh renderer and mesh filter from the game object. I’m now adding them to the object when the script initializes.

I then found the following post which seems to be similar to the problem I’m having (Mesh created in code is not visible - Questions & Answers - Unity Discussions), I’ve basically copied and pasted the guys code into my own, replacing his hard coded vertex locations with my own procedural ones. I’ve left the .uv and .triangle properties the same as his own because I didn’t understand the documentation for them…

Now when I run my scene I’m seeing a purple mesh flicker around, it’s not reflecting the shape I had envisioned which is making me think my rays are not firing where I think they are. But at least I’m making some progress.

Here is my updated script:

using UnityEngine;
using System.Collections;

public class rayCast : MonoBehaviour {
	
	//Set up public ints for angle to rayCast at
	public int leftAngle = 0;
	public int rightAngle = 0;
	//Create two vector2's to represent the directions of the two rayCasts;
	Vector2 directionLeft = new 	Vector2 ();
	Vector2 directionRight = new Vector2 ();
	//Create two rayCast2D's to represent the collision locations of the rayCasts which will be updated each frame
	RaycastHit2D hitPointLeft;
	RaycastHit2D hitPointRight;
	
	
	//Set the directions up
	void Start () {
		//Always keep the y values at -100 (i.e. well below the stage),
		//then we can just update the x values to change where the cone is "looking"
		directionLeft.x = this.transform.rotation.x - leftAngle;
		directionLeft.y = this.transform.rotation.y - 100;
		directionRight.x = this.transform.rotation.x + rightAngle;
		directionRight.y = this.transform.rotation.y - 100;
		//Add the mesh to a meshFilter attached to the game object
		this.gameObject.AddComponent<MeshRenderer>();
		this.gameObject.AddComponent<MeshFilter>();
	}
	
	//Update the left/right hitPoint variables with the new collision location
	//After I've got this set up I'll add in updating the rayCast direction each frame as well.
	void Update () {
		//This puts the  if the rayCast is hitting something, then puts the coordinates of the collision into the rayCast2D objects
		hitPointLeft = Physics2D.Raycast (this.transform.position, directionLeft);
		hitPointRight = Physics2D.Raycast (this.transform.position, directionRight);
		//Run the generateMesh function to update the mesh position
		generateMesh ();
	}
	
	
	void generateMesh () {
		//Create a vector3 to represent the 2nd vertex of the triangle
		Vector3 vertexTwo = new Vector3();
		vertexTwo.x = hitPointLeft.transform.position.x;
		vertexTwo.y = hitPointLeft.transform.position.y;
		vertexTwo.z = 0; //z = 0 because we're 2D
		
		//Create a vector3 to represent the 3rd vertex of the triangle
		Vector3 vertexThree = new Vector3();
		vertexThree.x = hitPointRight.transform.position.x;
		vertexThree.y = hitPointRight.transform.position.y;
		vertexThree.z = 0;  //z = 0 because we're 2D
		
		//Create a vector3 array to store the vertex locations
		Vector3[] meshVerts = new Vector3[3];
		meshVerts[0] = this.transform.position;
		meshVerts[1] = vertexTwo;
		meshVerts[2] = vertexThree;
		
		//Apply the vertex array to the mesh
		Mesh visionCone = new Mesh();
		visionCone.vertices = new Vector3[] { this.transform.position, vertexTwo, vertexThree };
		visionCone.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1) };
		visionCone.triangles = new int[] { 0, 1, 2 };
		visionCone.RecalculateBounds();
		visionCone.RecalculateNormals();

		this.gameObject.GetComponent<MeshFilter>().mesh = visionCone;

	}
	
	//This will be run each frame and will remove the previous frames mesh
	//STILL NEEDS DOING!
	void garbageCollection () {
		
	}
}

Did you try using a draw line to visually see the ray being cast?

yes, I’ve actually made several big steps forward. I’ve got it displaying the mesh to the screen correctly, but it seems as though it’s been translated and scaled down! I’ve no idea why the game object the script is attached to is translating because as you can see I’ve not entered any translations in my code… confused!

Here is the updated code:

using UnityEngine;
using System.Collections;

public class rayCast : MonoBehaviour {
	
	//Set up public ints for angle to rayCast at
	public int leftAngle = 0;
	public int rightAngle = 0;
	//Create two vector2's to represent the directions of the two rayCasts;
	Vector3 directionLeft;
	Vector3 directionRight;
	//Create two rayCast2D's to represent the collision locations of the rayCasts which will be updated each frame
	Ray leftRay;
	Ray rightRay;
	RaycastHit hitPointLeft;
	RaycastHit hitPointRight;

	//Set the directions up
	void Start () {
		//Always keep the y values at -100 (i.e. well below the stage),
		//then we can just update the x values to change where the cone is "looking"
		directionLeft = this.transform.rotation.eulerAngles;
		directionLeft.y -= 90;
		directionLeft.x -= 30;
		directionRight = this.transform.rotation.eulerAngles;
		directionRight.y -= 90;
		directionRight.x += 30;
		//Add the mesh to a meshFilter attached to the game object
		this.gameObject.AddComponent<MeshRenderer>();
		this.gameObject.AddComponent<MeshFilter>();
	}
	
	//Update the left/right hitPoint variables with the new collision location
	//After I've got this set up I'll add in updating the rayCast direction each frame as well.
	void Update () {
		directionLeft.x -= 1;
		directionRight.x += 1;
		leftRay = new Ray (this.transform.position, directionLeft);
		if (Physics.Raycast (leftRay, out hitPointLeft)) {
			
		}
		rightRay = new Ray (this.transform.position, directionRight);
		if (Physics.Raycast (rightRay, out hitPointRight)) {

		}
		Debug.DrawRay (this.transform.position, directionLeft);
		Debug.DrawRay (this.transform.position, directionRight);
		//Run the generateMesh function to update the mesh position
		generateMesh ();
	}
	
	
	void generateMesh () {
		//Create a vector3 to represent the 2nd vertex of the triangle
		Vector3 vertexTwo = hitPointLeft.point;

		//Create a vector3 to represent the 3rd vertex of the triangle
		Vector3 vertexThree = hitPointRight.point;
		

		//Apply the vertex array to the mesh
		Mesh visionCone = new Mesh();
		visionCone.vertices = new Vector3[] { new Vector3 (0, 0, 0), vertexTwo, vertexThree };
		visionCone.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1) };
		visionCone.triangles = new int[] { 0, 1, 2 };
		visionCone.RecalculateBounds();
		visionCone.RecalculateNormals();

		this.gameObject.GetComponent<MeshFilter>().mesh = visionCone;

	}
	
	//This will be run each frame and will remove the previous frames mesh
	//STILL NEEDS DOING!
	void garbageCollection () {
		
	}
}

Is it a child object?

Yes

Could the translations and scaling you’re seeing be related to the parent object being translated or scaled? That will also apply to child objects.

No because no translation is being applied to the parent object, not via script nor in any other way :frowning:

You could test this by creating a new empty scene, placing a new cube object to act as the ground (you’ll need to scale its x to be nice and wide so the rays have enough ground to hit), then you can create a totally empty game object above the ground and attach the script to it. Then click play and see what happens!

UPDATE:

Fixed it, here’s the updated code:

using UnityEngine;
using System.Collections;

public class rayCast : MonoBehaviour {
	
	//Set up public ints for angle to rayCast at
	public int coneAngle = 0;
	public int lookDistance = 0;
	public int lookSpeed = 0;
	public string direction = "left";	
	int distanceTravelled = 0;
	//Create two vector2's to represent the directions of the two rayCasts;
	Vector3 directionLeft;
	Vector3 directionRight;
	//Create two rayCast2D's to represent the collision locations of the rayCasts which will be updated each frame
	Ray leftRay;
	Ray rightRay;
	RaycastHit hitPointLeft;
	RaycastHit hitPointRight;


	//Set the directions up
	void Start () {
		//Always keep the y values at -100 (i.e. well below the stage),
		//then we can just update the x values to change where the cone is "looking"
		directionLeft = this.transform.rotation.eulerAngles;
		directionLeft.y -= 90;
		directionLeft.x -= coneAngle;
		directionRight = this.transform.rotation.eulerAngles;
		directionRight.y -= 90;
		directionRight.x += coneAngle;
	}
	
	//Update the left/right hitPoint variables with the new collision location
	//After I've got this set up I'll add in updating the rayCast direction each frame as well.
	void Update () {
		if (direction == "left") {
			directionLeft.x -= lookSpeed;
			directionRight.x -= lookSpeed;
			distanceTravelled -= lookSpeed;
		}
		else if (direction == "right") {
			directionLeft.x += lookSpeed;
			directionRight.x += lookSpeed;
			distanceTravelled += lookSpeed;
		}
		if (distanceTravelled <= -lookDistance) {
			direction = "right";
		}

		else if (distanceTravelled >= lookDistance) {
			direction = "left";
		}

		leftRay = new Ray (this.transform.position, directionLeft);
		if (Physics.Raycast (leftRay, out hitPointLeft)) {
			
		}

		rightRay = new Ray (this.transform.position, directionRight);
		if (Physics.Raycast (rightRay, out hitPointRight)) {
			
		}

		Debug.DrawRay (this.transform.position, directionLeft);
		Debug.DrawRay (this.transform.position, directionRight);
		//Run the generateMesh function to update the mesh position
		generateMesh ();
	}
	
	
	void generateMesh () {
		//Create a vector3 to represent the 2nd vertex of the triangle
		Vector3 vertexTwo = hitPointLeft.point;
		
		//Create a vector3 to represent the 3rd vertex of the triangle
		Vector3 vertexThree = hitPointRight.point;

		GameObject newCone = new GameObject ("Cone");
		newCone.transform.position = new Vector3 (0, 0, 0);
		newCone.gameObject.AddComponent<MeshRenderer> ();
		newCone.gameObject.AddComponent<MeshFilter> ();
		newCone.gameObject.AddComponent<PolygonCollider2D> ();
		newCone.gameObject.AddComponent<visionCollision> ();
		newCone.gameObject.AddComponent<Rigidbody2D> ();
		newCone.gameObject.GetComponent<Rigidbody2D> ().gravityScale = 0;

		
		//Apply the vertex array to the mesh
		Mesh visionCone = new Mesh();
		visionCone.vertices = new Vector3[] { this.transform.position, vertexTwo, vertexThree };
		visionCone.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1) };
		visionCone.triangles = new int[] { 0, 1, 2 };
		visionCone.RecalculateBounds();
		visionCone.RecalculateNormals();

		newCone.gameObject.GetComponent<PolygonCollider2D>().points = new Vector2[] {  this.transform.position, vertexTwo, vertexThree };
		newCone.gameObject.GetComponent<PolygonCollider2D>().isTrigger = true;
		newCone.gameObject.GetComponent<MeshFilter>().mesh = visionCone;

		Destroy (newCone, 0.01f);
	}

	void generateCollider () {
		//Create a vector3 to represent the 2nd vertex of the triangle
		Vector2 vertexTwo = hitPointLeft.point;
		//Create a vector3 to represent the 3rd vertex of the triangle
		Vector2 vertexThree = hitPointRight.point;
		//Apply the vertex array to the mesh
		this.gameObject.GetComponent<PolygonCollider2D> ().points = new Vector2[] { new Vector2 (this.transform.localPosition.x, this.transform.localPosition.y), vertexTwo, vertexThree };
		this.gameObject.GetComponent<PolygonCollider2D> ().isTrigger = true;
	}

	//This will be run each frame and will remove the previous frames mesh
	//STILL NEEDS DOING!
	void garbageCollection () {

	}
}