Class globals not present Inspector

Followed this tutorial on Flocking and advanced AI. If you fast forward to 32:51 his AI class has Boids (another class he named Boides) with an arrow and all the globals he made public.

I pretty much followed this step by step and for some reason in my Inspector Boids says:

“Boids None(Boids)”

As if I am supposed to apply a gameobject to it or something. It’s like not reading that it’s a class. I made everything public too. When I start game it gives me a Null reference exception (Object reference not set to an instance of an object) (at this line in my code:

“boids.Update(this);”

Also I get a MonoBehavior warning "using the new keyword this is not allowed. MonoBehaviours can only be added using AddComponent.

This I kind of get, but it works in his tut?

and in my globals in my AI class (original class) I have “Boids boids = new Boids();” the same as he put it.

So something is def wrong with “boids” but I don’t know why or what I am doing wrong when I pretty much followed it to a tee.

AI.cs

using UnityEngine;
using System.Collections;

[System.Serializable]
public class AI : MonoBehaviour {
	/*
	 * ***CLEAN CODE - Naming Conventions***
	 * 
	 * privates = _firstwordSecondword
	 * 
	 * constants = CAPITALS_WITH_UNDERSCORE
	 * 
	 * publics = lowercase
	 * 
	 * properties = EveryWordFirstLetterUpperCase
	 * 
	 * ***Seperate different data types***
	 * 
	 * */
	private AIState _state;

	private float _timer = 0;
	private float _currentSpeed;
	public float CurrentSpeed {get { return _currentSpeed; } set { _currentSpeed = value; } }
	public float turnSpeed = 10; //10 is 2-4 frames per turn, anything above 10 is too fast might crash
	public float walkSpeed = 5;
	public float runSpeed = 10;
	public float distanceUntilFade; //fading between walking and running
	public float fadeSpeed; //how quickly you fade between walking and running
	//flocking algorithm
	public Boids boids = new Boids();

	public bool usingAStar; //if true do not go to Wander, and if false do not go to AStarWander
	public bool Idle { get; set; } //public to everything, except Unity editor. 

	private const float DISTANCE_FROM_SELF_FOR_RANDOM = 4f;
	private const float DISTANCE_UNTIL_GO_TO_IDLE = 1f;//kind of the same thing as making it public and removing private const so you only have to edit the number once in the code.

	private Vector3 _randLoc = Vector3.zero; //creates new vector3 sets each axis to 0 first

	// Use this for initialization
	public void Start ()
	{
		_currentSpeed = runSpeed;
	}
	
	// Update is called once per frame
	public void Update () 
	{

		switch (_state)  //if state is...
		{
		case AIState.Idle:

			_timer -= Time.deltaTime; //if coming into idle will reset timer
			if(!Idle) //if not already idle, set timer so we are idle
			{
				_timer = Random.Range (0f, 2f);
				Idle = true;
			}



			if(_timer <= 0)
			{
				_state = usingAStar ? AIState.AStarWander : AIState.Wander; //c code, if usingAStar is true state = AStar.Wander, if false state = Wander
				Idle = false;

			}
			break;

		case AIState.AStarWander:
			break;

		case AIState.Wander:
			if(_randLoc == Vector3.zero)
			{
				_randLoc = new Vector3(Random.insideUnitCircle.x, 
				                       transform.position.y, 
				                 		Random.insideUnitCircle.y)
										* DISTANCE_FROM_SELF_FOR_RANDOM;


				//avoid non-floor level randoom location
				_randLoc.y = transform.position.y;

				transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (_randLoc - transform.position), Time.deltaTime * turnSpeed); //doesnt need normalized vector, just a direction
			

				/*if(Vector3.Distance (_randLoc, transform.position) <= distanceUntilFade) //if our distance is less than how far we want to be away until we fade, then fade to walk, otherwise fade to run.
					_currentSpeed = Mathf.Lerp (_currentSpeed, walkSpeed, Time.deltaTime * fadeSpeed); //Quat.Slerp = smooth lerp, lerp = linear interprelate
					//lerp = go from this to this over this amoutn of time
					//slerp = smooth lerp, think of a curve. -|_ not much of  a curve, but it enters a turn and exits a turn
					//Lerp gives you smoother since i am only changing 1 in the entrance/exits, creates a smoother turn.  
					//Lerp would be .2 .4 .5 .6 .7 .8 .9 Slerp would be .23 .3454 .356..etc 
					//For turning use Slerp
				else
					_currentSpeed = Mathf.Lerp (_currentSpeed, runSpeed, Time.deltaTime * fadeSpeed);*/ 

				_currentSpeed = Mathf.Lerp (_currentSpeed, 
				 	Vector3.Distance (_randLoc, transform.position) <= distanceUntilFade ? walkSpeed : runSpeed,
					Time.deltaTime * fadeSpeed);

				if(Vector3.Distance (transform.position, _randLoc) <= DISTANCE_UNTIL_GO_TO_IDLE) 
				{
					_randLoc = Vector3.zero;
					_state = AIState.Idle;
				}
			
			}
			break;
		}


		boids.Update(this);

		//Movement Controller 
		if (!Idle) rigidbody.AddRelativeForce (Vector3.forward * _currentSpeed);


		if(rigidbody.velocity.magnitude > _currentSpeed * .3f && _currentSpeed > walkSpeed) //if walk speed is low enough it will simply stop you without the && and after
			rigidbody.velocity = transform.forward * _currentSpeed;

		//Steering Controller
		if(Physics.Raycast(transform.position, transform.forward, 2))
		{
			var direction = transform.right; //var in c# is an anonymous variable, we don't know what it is yet. kind of like a template in c++?

			if(Physics.Raycast (transform.position, (transform.forward + transform.right).normalized, 2)) //if ai is going up and right (your current position and ur position going forward and right
				//finds us a normalized vector when going up and right
			{
				direction = -direction;

				if(Physics.Raycast (transform.position, (transform.forward - transform.right).normalized, 2)) //there's no transform.left, so we take negative right 
					direction = -transform.forward; //negative transform.forward would be at this point backward right, meaning left 
			}
			transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), Time.deltaTime * turnSpeed); //rotate by turn speed by timedelttime times turnSpeed
		}

	
	}
}


public enum AIState
{
	Idle,
	AStarWander,
	Wander
};

Boids.cs

using UnityEngine;
using System.Collections.Generic;
using System.Linq;

[System.Serializable]
public class Boids : MonoBehaviour {
	/*
	 * ***CLEAN CODE - Naming Conventions***
	 * 
	 * privates = _firstwordSecondword
	 * 
	 * constants = CAPITALS_WITH_UNDERSCORE
	 * 
	 * publics = lowercase
	 * 
	 * properties = EveryWordFirstLetterUpperCase
	 * 
	 * ***Seperate different data types***
	 * 
	 * */

	public string tagToSearch; //anything that has this tag, we will search for
	public float searchRadius; //obviously only searching within this radius
	public float seperationRadius;


	public AI leader;
	public List<AI> boidGroup = new List<AI>();

	public BoidState boidState = BoidState.Ignore;



	// Use this for initialization
	void Start () 
	{
	
	}
	
	// Update is called once per frame
	public void Update (AI ai) 
	{
		var goa = GameObject.FindGameObjectsWithTag (tagToSearch);

		/* foreach(var gameObject in goa)
		{
			if (Vector3.Distance (gameObject.transform.position, ai.transform.position) <= searchRadius)
			{
				if(gameObject.GetComponent<AI>() && !boidGroup.Contains(gameObject.GetComponent<AI>()))
				   boidGroup.Add (gameObject.GetComponent<AI>());
			}
		} SAME THING BELOW */ 

		foreach(var gameObject in goa.Where(gameObject => Vector3.Distance (gameObject.transform.position, ai.transform.position) <= searchRadius).Where(gameObject => gameObject.GetComponent<AI>() && !boidGroup.Contains(gameObject.GetComponent<AI>()))) {          
			boidGroup.Add(gameObject.GetComponent<AI>());
		}

		if(leader == null && boidGroup.Count > 0)
		{
			leader = boidGroup[Random.Range (0, boidGroup.Count)];
			foreach(var boid in boidGroup)
			{
				if(boid.boids.leader != leader && boid.boids.leader != null) leader = boid.boids.leader;
			}
		}

		if(leader == ai) //consolidating leader to 1 boid
		{
			boidState = BoidState.Ignore;
			foreach (var boid in boidGroup.Where (boid => boid.boids.leader != ai).Where (boid => boid.boids.leader == boid || boid.boids.leader == null)) {//if were not the leader, then if the leader is himself or null we will assign 
				//boid.boids.leader = ai;
				boid.boids.leader = ai;
				return;
			}
		}

		foreach(var boid in boidGroup) //for each boid were going to set their leader to our leader if we are not leader
			boid.boids.leader = leader;

		if(leader != null)
		{
			//ai.astar = null;
			if(boidState == BoidState.Ignore)
				boidState = 0;		
		}
		//else ai.aStar = null;

		ai.Idle = leader.Idle;

		switch(boidState)
		{
		case BoidState.Alignment:
			ai.transform.rotation = Quaternion.Slerp (ai.transform.rotation, leader.transform.rotation, Time.deltaTime * ai.turnSpeed);

			ai.CurrentSpeed = leader.CurrentSpeed;

			if(Vector3.Distance (ai.transform.position, leader.transform.position) <= seperationRadius /2)
				boidState = BoidState.Seperation;
			if(Vector3.Distance(ai.transform.position, leader.transform.position) >= seperationRadius)
				boidState = BoidState.Cohesion;
			break;
		case BoidState.Cohesion:
			ai.CurrentSpeed = ai.runSpeed;
			ai.transform.rotation = Quaternion.Slerp (ai.transform.rotation, Quaternion.LookRotation((leader.transform.position - leader.transform.forward * -1) - ai.transform.position), Time.deltaTime * ai.turnSpeed); 
			//1 behind leaders position, 1 minus our position ^
			if(Vector3.Distance (ai.transform.position, leader.transform.position) < seperationRadius - .5f) //making sure boids are within radius not on the line
				boidState = 0;
			break;
		case BoidState.Seperation:
			ai.CurrentSpeed = ai.runSpeed;
			ai.transform.rotation = Quaternion.Slerp (ai.transform.rotation, Quaternion.LookRotation(ai.transform.position  - ai.transform.position), Time.deltaTime * ai.turnSpeed);

			if(Vector3.Distance (ai.transform.position, leader.transform.position) >= seperationRadius /2) 
				boidState = 0;
			break;
		case BoidState.Ignore:
			break;
		}

		/*foreach(var boid in boidGroup)
		{
			if(Vector3.Distance (boid.transform.position, ai.transform.position) <= seperationRadius /2)
				ai.rigidbody.AddForce ((ai.transform.position - boid.transform.position).normalized * ai.runSpeed * Time.deltaTime); //if within radius it's walking or pushing away from other boids
		}*/

		foreach(var boid in boidGroup.Where (boid => Vector3.Distance (boid.transform.position, ai.transform.position) <= seperationRadius / 2)){
			ai.rigidbody.AddForce((ai.transform.position - boid.transform.position).normalized * ai.runSpeed * Time.deltaTime);
		}
	}
}

public enum BoidState
{
	Alignment = 0,
	Cohesion = 1,
	Seperation = 2,
	Ignore = -1
};

“using the new keyword this is not allowed. MonoBehaviours can only be added using AddComponent” is the issue.

You can’t construct “MonoBehaviour” classes in the same way you would other C# classes. They should be attached to GameObjects.

It doesn’t seem like you need Boids to inherit from MonoBehaviour. You could change your Boids script so it does not inherit from MonoBehaviour. This way you shouldn’t have a problem constructing it using new Boids().

If you do really need it to inherit from MonoBehaviour, try adding the Boids script onto the same GameObject that your AI script is attached to, then change AI to get the Boids component in Start (). You should also be able to set ‘boids’ in the inspector if it is attached to a GameObject; just drag the GameObject it is attached to into the Boids field on your AI script in the inspector.

public Boids boids;
...

void Start () {
       _currentSpeed = runSpeed;
       boids = GetComponent<Boids>();
}