- Home /
Inheritance Confusion
I'm trying to inherit from an Enemy class to a Guard class but NOTHING IS INHERITING! How does this all work??? I've been at this for hours. I just keep coming up with UnsignedReferenceExceptions and things aren't working. Here's my code:
// Enemy.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Enemy : MonoBehaviour
{
protected NavMeshAgent navMeshAgent = null;
public List<GameObject> pathNodes = new List<GameObject>();
protected int currentPathNodeIndex = 0;
public float pathNodeDistanceThreshold = 1.0f;
public GameObject player = null;
public float aggroRadius = 5.0f;
public int delayRange = 0;
public float timer = 0.0f;
// Use this for initialization
void Start ()
{
delayRange = Random.Range(2, 10);
navMeshAgent = gameObject.GetComponent<NavMeshAgent>();
if (navMeshAgent == null)
{
navMeshAgent = gameObject.AddComponent<NavMeshAgent>();
}
if (pathNodes.Count <= 0)
{
Debug.LogError("This sytem requires that at least one path node blah blah blah....");
}
player = GameObject.FindWithTag("Player");
}
// Update is called once per frame
void Update ()
{
if (player == null)
{
return;
}
if (navMeshAgent == null)
{
return;
}
if (pathNodes.Count <= 0)
{
return;
}
}
}
// Guard.cs
// Here, Guard isn't inheriting the Player so he can't find him
//Why? Shouldn't the Enemy grab the object with the tag, "Player" and therein allowing Guard to use it?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Guard : Enemy
{
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
if (Vector3.Distance(gameObject.transform.position, player.transform.position) <= aggroRadius)
{
navMeshAgent.destination = player.transform.position;
}
else
{
navMeshAgent.destination = pathNodes[currentPathNodeIndex].transform.position;
if (Vector3.Distance(gameObject.transform.position, navMeshAgent.destination) <= pathNodeDistanceThreshold)
{
timer = timer + Time.deltaTime;
if (timer >= delayRange)
{
timer = 0.0f;
currentPathNodeIndex++;
delayRange = Random.Range(2, 10);
}
if (currentPathNodeIndex >= pathNodes.Count)
{
currentPathNodeIndex = 0;
}
}
}
}
}
Why isn't this working? Also, how do I put prefabs into lists at runtime? I need to do that so I can create new PathNodes and Enemy is able to grab those nodes and put them in the list. Any help would be appreciated. Inheritance just confuses me greatly......
Answer by GameVortex · Dec 06, 2013 at 10:15 AM
Unity will only call the first Start() and Update() functions it find starting from the Child. So in your case the Start() and Update() in Guard will be used but not the ones in Enemy. Your player object never gets a value because the value is set in the Start() function in the Enemy which does not get called. A solution would be to add base.Start() and base.Update() in the Guard functions:
void Start ()
{
base.Start();
}
void Update()
{
base.Update();
}
Remember to change the Start() and Update() functions in Enemy to be either public or protected so that Guard has access to them.
Great. That did it. But I still get some warnings that say something about Guard.Start() hiding Enemy.Start() or something. It doesn't affect the program, but I don't know if that will come to bite me in the future. But thank you very much for the help. $$anonymous$$akes more sense now. Now, do you know of any way to make it so PathNodes that are created at runtime are programatically referenced in the pathNodes list? It doesn't let me use FindWithTag() with Lists, so I don't know what to do. Thanks again!
You're not overriding Start and Update properly. If you want to declare methods overridable you should add virtual to that method and change the modifier to protected to make it visible for derived classes. Declare the overriding method with an override
In Enemy:
virtual protected void Start () ...
In Guard:
override protected void Start ()
{
base.Start();
}
Oh I see. Thank you. It's still a bit confusing, but I'll figure it all out later. Thanks again.