Void is being called when its not supposed to

Updated on July 14, 2017 in [A] Unity Scripting
Share on Facebook0Tweet about this on TwitterShare on Google+0Share on Reddit0
7 on July 13, 2017

My function is called one time at the start of the scene and after that its fine, but its not supposed to call at the start of the scene. tried some stuff but with no success;(

 

This is the interact script

 

 
public class Interactable : MonoBehaviour
{
 [HideInInspector]
 public NavMeshAgent playerAgent;
 private bool hasInteracted;
 
void Update()
 {
 if (!hasInteracted && playerAgent != null && !playerAgent.pathPending)
 {
 if (playerAgent.remainingDistance <= playerAgent.stoppingDistance)
 {
 Interact();
 EnsureLookDirection();
 hasInteracted = true;
 }
 }
 }
 
 public virtual void Interact()
 {
 Debug.Log("Interacting with base class.");
 }

 

This is the script being called at the start of the scene

 

 
public class NPC : Interactable
{
 
public override void Interact()
 {
 Debug.Log("Interacting with NPC.");
 ShowDialogue();
 }
 

 

  • Liked by
Reply
6 on July 13, 2017

So I’m not an expert in base code sets, still learning them myself (even so late in my studies), but I think that’s one of the effects of the use of virtual/override functions.
 
As far as I know, one of the general purpose of using child classes is to differentiate specifics while keeping generalizations. For example, all food objects might have a weight for inventory purposes, but ‘fruit’ could be a child class for food, and all fruit have seeds to plant more fruit. But then, apples are edible, while coconuts generally aren’t, so you have more child classes.
 
When the base class ‘Interactable’ calls Interact(), because it has a child class with an override Interact() it calls that instead, (Because it is overridden). So what I’ve been seeing in my experience by other programmers is that in any child class, they start out with base.Interact() (or similar) so that the base class still gets called every time. So yours should be:

public class NPC : Interactable
{
public override void Interact()
 {
base.Interact();
 Debug.Log("Interacting with NPC.");
 ShowDialogue();
 }

that would be standard practice as far as I can tell.
So, If you don’t want that happening at the start of the scene, only call Interact when a trigger is tripped and calls it from a separate location.
I know there is a good unity tutorial about this… HERE it is.
It’s been a while since I’ve watched it though, so take my advice with a grain of salt.

Devoted
on July 13, 2017

Upon reflection, generally all of what I said seems to already be understood by you, so what might be happening then is in your conditions are being met at the beginning of the scene… But that doesn’t quite make sense either, because if it was called within your update if conditions, it would also be setting hasInteracted to true, making it inaccessible later on as you say it is…
Is it possible that there is an awake or start function that is calling Interact() externally?

Devoted
on July 13, 2017

Also, THIS was the actually tutorial I was trying to find.

on July 13, 2017

this just makes it so the base interaction hapends on the start of the scene, i cant want it to be called when i start the scene, and i dont find out why its called

on July 13, 2017

but i fixed it by adding a bool to “void Awake” so the “hasInteracted” is true at the start

Devoted
on July 14, 2017

ok. interesting. 
The other option is to look at the debug.log statement in the console. It shows you the path of where everything originates from. If you share a screen shot of the unity console that shows your debug statement, I can kind of try to explain how each statement contains information on where functions originate from.

on July 14, 2017

Your hasInteracted variable has inverted meaning. So, this is what is happening:

!hasInteracted && playerAgent != null && !playerAgent.pathPending

Assuming:

  • hasInteracted = false – which means player did not interact with something and there is not need for 
  • playerAgent is set to object
  • playerAgent.pathPending = false

You would have:

!false AND true AND !false 

which really is:

true AND true AND true

which evaluates as true. You could remove ! from hasInteracted to maintain logical flow and set it back to false. Then it makes perfect sense hasInteracted = true or hasInteracted = false – which means “has interacted” or “hasn’t interacted”.

 

Why? While compiler doesn’t care about this, you as human might – it’s you who is going to read it later, fix bugs add more functionality. If you loose clarity at the beginning and assume that things just work – you get lost.

 

Also in case of complex boolean equations it is really helpful to do the math (yes it is math :)) on the paper and see if this is what you need.

 

Additionally I would recommend you to set value of variable when you declare it – never rely that compiler implementation never changes. You can do it like so:

private bool hasInteracted = false;

Show more replies
  • Liked by
Reply
Cancel