Hi together,
i have completed the course and started again with an own project.
Cause of the typ of game the enemies will have to be put randomly together as in the course BUT they have their own startCoordinates each in the Enemy Script.
Everything works but it keeps calling:
NullReferenceException: Object reference not set to an instance of an object
Pathfinder.GetNewPath (UnityEngine.Vector2Int coordinates) (at Assets/Game/Pathfinding/Pathfinder.cs:55)
EnemyMover.RecalculatePath (System.Boolean resetPath) (at Assets/Game/Scripts/EnemyMover.cs:49)
EnemyMover.OnEnable () (at Assets/Game/Scripts/EnemyMover.cs:19)
UnityEngine.Object:Instantiate(GameObject, Transform)
ObjectPool:PopulatePool() (at Assets/Game/Scripts/ObjectPool.cs:38)
ObjectPool:Awake() (at Assets/Game/Scripts/ObjectPool.cs:18)
From my pov i have to search for an not assigned GameObject and have added Debug.Log´s in the ObjectPool Script before and after Line 18:
using System;
using System.Collections;
using UnityEngine;
public class ObjectPool : MonoBehaviour
{
[SerializeField] GameObject[] enemyTyps;
[SerializeField] [Range(0, 50)] int poolSize = 10;
[SerializeField] [Range(0.1f, 30f)] float spawnTimer = 1f;
GameObject enemy;
GameObject[] pool = new GameObject[0];
void Awake()
{
PopulatePool();
}
void Start()
{
StartCoroutine(SpawnEnemy());
}
void PopulatePool()
{
pool = new GameObject[poolSize];
for (int i = 0; i < poolSize; i++)
{
enemy = enemyTyps[UnityEngine.Random.Range(0, enemyTyps.Length)];
Debug.Log(enemy);
Debug.Log(pool[i]);
Debug.Log(this);
pool[i] = Instantiate(enemy,transform);
pool[i].SetActive(false);
Debug.Log(enemy);
Debug.Log(pool[i]);
Debug.Log(this);
}
}
void EnableObjectInPool()
{
for(int i = 0; i < pool.Length; i++)
{
if(!pool[i].activeInHierarchy)
{
pool[i].SetActive(true);
return;
}
}
}
IEnumerator SpawnEnemy()
{
while (true)
{
EnableObjectInPool();
yield return new WaitForSeconds(spawnTimer);
}
}
}
The Only Object wich is null before the instantiation is pool[i]
Now i don´t have a clue how to solve it cause this pool array is empty before its filled during Awake() within the PopulatePool() function.
I hope anybody can follow my case and is able to help.
Does the other references to the other scripts matter for this NullRef Error? Or am I wrong and the issue is maybe elsewhere? I hadn´t offen the fact that there where so many references to code in an NullRef so i m just a lil bit kicked back.
pathfinder.cs
public class Pathfinder : MonoBehaviour
{
Vector2Int startCoords;
public Vector2Int StartCoordinates { get { return startCoords; } }
[SerializeField] Vector2Int destinationCoords;
public Vector2Int DestinationCoordinates { get { return destinationCoords; } }
Node startNode;
Node destinationNode;
Node currentSearchNode;
//Queues List with FirstIn FirstOut (FIFO)
Queue<Node> frontier = new Queue<Node>();
Dictionary<Vector2Int, Node> reached = new Dictionary<Vector2Int, Node>();
Vector2Int[] directions = { Vector2Int.right, Vector2Int.left, Vector2Int.up, Vector2Int.down };
GridManager gridManager;
Dictionary<Vector2Int, Node> grid = new Dictionary<Vector2Int, Node>();
void Awake()
{
startCoords = StartCoordinates;
Debug.Log(startCoords);
gridManager = FindObjectOfType<GridManager>();
if (gridManager != null)
{
grid = gridManager.Grid;
startNode = grid[startCoords];
destinationNode = grid[destinationCoords];
}
}
void Start()
{
GetNewPath();
}
//Overloading GetNewPath() Method, copy Method and setup parameters ==>Lookat Instantiate and its many possible parameters
public List<Node> GetNewPath()
{
//gridManager.ResetNodes();
//BreadthFirstSearch(startCoords);
//return BuildPath();
// get rid of above and just call new GetNewPath with startCoords parameter
return GetNewPath(startCoords);
}
public List<Node> GetNewPath(Vector2Int coordinates)
{
gridManager.ResetNodes();
BreadthFirstSearch(coordinates);
return BuildPath();
}
void ExploreNeighbors()
{
List<Node> neighbors = new List<Node>();
foreach (Vector2Int direction in directions)
{
Vector2Int neighborCoords = currentSearchNode.coordinates + direction;
//Debug.Log(neighborCoords);
if (grid.ContainsKey(neighborCoords))
{
neighbors.Add(grid[neighborCoords]);
}
}
foreach (Node neighbor in neighbors)
{
if(!reached.ContainsKey(neighbor.coordinates) && neighbor.isWalkable)
{
neighbor.connectedTo = currentSearchNode;
reached.Add(neighbor.coordinates, neighbor);
frontier.Enqueue(neighbor);
}
}
}
void BreadthFirstSearch(Vector2Int coordinates)
{
startNode.isWalkable = true;
destinationNode.isWalkable = true;
frontier.Clear();
reached.Clear();
bool isRunning = true;
frontier.Enqueue(grid[coordinates]);
reached.Add(coordinates, grid[coordinates]);
while(frontier.Count > 0 && isRunning)
{
currentSearchNode = frontier.Dequeue();
currentSearchNode.isExplored = true;
ExploreNeighbors();
if (currentSearchNode.coordinates == destinationCoords)
{
isRunning = false;
}
}
}
List<Node> BuildPath()
{
List <Node> path = new List<Node>();
Node currentNode = destinationNode;
path.Add(currentNode);
currentNode.isPath = true;
while(currentNode.connectedTo != null)
{
currentNode = currentNode.connectedTo;
path.Add(currentNode);
currentNode.isPath = true;
}
path.Reverse();
return path;
}
public bool WillBlockPath(Vector2Int coordinates)
{
if(grid.ContainsKey(coordinates))
{
bool previousState = grid[coordinates].isWalkable;
grid[coordinates].isWalkable = false;
List<Node> newPath = GetNewPath();
grid[coordinates].isWalkable = previousState;
if(newPath.Count <= 1)
{
GetNewPath();
return true;
}
}
return false;
}
public void NotifyReceivers()
{
//calls RecalculatePath() to any listening Gameobjects and its children
BroadcastMessage("RecalculatePath", false, SendMessageOptions.DontRequireReceiver);
}
}
enemymover.cs
public class EnemyMover : MonoBehaviour
{
[SerializeField][Range(0f, 5f)] float speed = 0.5f;
List<Node> path = new List<Node>();
Enemy enemy;
GridManager gridManager;
Pathfinder pathfinder;
void OnEnable()
{
ReturnToStart();
RecalculatePath(true);
}
void Awake()
{
enemy = GetComponent<Enemy>();
gridManager = FindObjectOfType<GridManager>();
pathfinder = FindObjectOfType<Pathfinder>();
}
void RecalculatePath(bool resetPath)
{
Vector2Int coordinates = new Vector2Int();
if (resetPath)
{
if (enemy.StartCoordinates != null)
{
coordinates = /*pathfinder.*/enemy.StartCoordinates;
//Debug.Log(coordinates);
}
else coordinates = new Vector2Int(10, 6);
}
else
{
coordinates = gridManager.GetCoordinatesFromPosition(transform.position);
}
StopAllCoroutines();
path.Clear();
//Debug.Log(coordinates);
path = pathfinder.GetNewPath(coordinates);
StartCoroutine(FollowPath());
}
void ReturnToStart()
{
transform.position = gridManager.GetPositionFromCoordinates(/*pathfinder.*/enemy.StartCoordinates);
}
void FinishPath()
{
enemy.StealGold();
gameObject.SetActive(false);
}
IEnumerator FollowPath()
{
for(int i = 1; i < path.Count; i++)
{
Vector3 startPosition = transform.position;
Vector3 endPosition = gridManager.GetPositionFromCoordinates(path[i].coordinates);
float travelPercent = 0f;
transform.LookAt(endPosition);
while (travelPercent < 1f)
{
travelPercent += Time.deltaTime * speed;
transform.position = Vector3.Lerp(startPosition, endPosition, travelPercent);
yield return new WaitForEndOfFrame();
}
}
FinishPath();
}
}
Many thanks in advance for any help on this issue.
Greets Chris