Reputation: 31
Im trying to use the Awake method without attaching it to an object, but it never initializes the class. It was supposed to initialize the class so that it could run an OnEnable method that added a subscriber to an event, but it did nothing. The only thing that works is attaching the script to a game object, but I don't want to do that, I tried changing the acmes modifier from private to protected virtual and a bunch more...
This is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovementAnimationParameterControl : MonoBehaviour
{
private Animator animator;
private void Awake()
{
animator = GetComponent<Animator>();
}
private void OnEnable()
{
EventHandler.MovementEvent += SetAnimationParameters;
Debug.Log("Enable. Im running, its not me");
}
private void OnDisable()
{
EventHandler.MovementEvent -= SetAnimationParameters;
Debug.Log("Im running its not me");
}
private void SetAnimationParameters(float xInput, float yInput, bool isWalking)
{
animator.SetFloat(Settings.xInput, xInput);
animator.SetFloat(Settings.yInput, yInput);
animator.SetBool(Settings.isWalking, isWalking);
}
}
Upvotes: 2
Views: 4398
Reputation: 2292
It was supposed to initialize the class so that it could run an OnEnable method that added a subscriber to an event, but it did nothing. The only thing that works is attaching the script to a game object
When you create a class that inherits from MonoBehaviour
(Aka a 'Unity Script'. You're creating a script that allows the use of certain functions at runtime, such as OnEnable
and OnAwake
among others.
It might not seem too intuitive, but MonoBehaviour
actual inherits indirectly from GameObject
. The reason for this is because GameObject
is the "target" of all of these methods like Update()
for example.
Without an actual GameObject
for your MonoBehavior
to access it's properties at runtime, your script wont do anything.
The best example would be from your code.
Take the OnAwake()
method for example
private void Awake()
{
animator = GetComponent<Animator>();
}
What this method does is set the field animator
to the reference of Animator
. That reference is found using the inherited method called GetComponent
. Get component is an inherited method from the MonoBehaviour
class, which like a russian nesting doll, is inherited from GameObject
.
So what you're really doing is saying "hey GameObject that this script is attached to, please give me your Animator component, if you have one."
This is where we see the issue at hand, that without an actual GameObject
to access none of the methods like OnAwake()
or even the method calls contained within will work, since they all(or most) come from GameObject
not actually from MonoBehavior
.
There is also another major obstacle to overcome specifically with the events like OnEnable()
, OnAwake()
, Start()
etc.. This issue comes from how Unity processes scripts during runtime. Only scripts with a actual GameObject
is ever scheduled to have it's components scripts to run.
Think of it like a big pile of paper work on some body's desk. This big pile of paperwork consists of all of the scripts on all gameobjects in the scene. Unity has to pull a sheet of paperwork(a script) from the pile, run it's contents, and put it in the done pile on the opposite side of the desk. With this analogy, a script that doesn't have any attached GameObject
, would be a sheet a paper with no name on it. Unity will look at this paper and say "This doesn't even have a name on it, I'm not even going to look at it" and then proceeds to throw it in the trash because it's not a script that any GameObject
needs to run - and that's all Unity cares about. This is because it would be inefficient to look at any scripts that no GameObject
needs.
Upvotes: 3