GetComponent() fails when called in Awake() or Start()

I am trying to get a CanvasGroup in Start. For most of my panels/canvases it works however for one it doesn’t and the value remains Null. CanvasGroup is a required component.
Could this be a bug?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

[RequireComponent(typeof(CanvasGroup))]
public class PanelFader : MonoBehaviour 
{
	const float DEFAULT_FADE_OUT_TIME = 0.3f;
	const float DEFAULT_FADE_IN_TIME = 0.3f;

	public bool useDefaultFadeIn = true;
	[Range(0, 5.0f)]
	public float customFadeIn;
	public bool useDefaultFadeOut = true;
	[Range(0, 5.0f)]
	public float customFadeOut;

	private CanvasGroup _canvasGroup;

	// For some reason this fails to get the component in Start and sometimes fail in Awake
	void Start()
	{
		_canvasGroup = GetComponent<CanvasGroup> ();
	}

	public void FadingSetActive(bool active)
	{
//		I have to uncomment the line below to guarantee it gets the component
//		_canvasGroup = GetComponent<CanvasGroup> ();
//		Debug.Log ("Canvas group: " + this + " - " + _canvasGroup);
		_canvasGroup.DOKill ();

		if(active)
		{
			gameObject.SetActive (true);
			_canvasGroup.alpha = 0;
			_canvasGroup.DOFade (1, useDefaultFadeIn ? DEFAULT_FADE_IN_TIME : customFadeIn).SetEase(Ease.InCubic);
		}
		else
		{
			_canvasGroup.alpha = 1;
			_canvasGroup.DOFade (0, useDefaultFadeOut ? DEFAULT_FADE_OUT_TIME : customFadeOut).SetEase(Ease.InCubic)
			.OnComplete (() => {
				gameObject.SetActive (false);
				_canvasGroup.alpha = 1;
			});
		}
	}
}

Well you most likely call your “FadingSetActive” method from another script before Start has run. Are you sure you actually tried Awake? Though even Awake can fail if you call “FadingSetActive” from the Awake or OnEnable callback of another script if the execution order is the wrong way around. Since we don’t know from where you actually call the “FadingSetActive” method we can’t really pinpoint your problem.

Just start debugging your issue. Add Debug.Log statements in Awake / Start and inside your FadingSetActive method That way you see in which order those are executed and you get a stacktrace for each call which should help identifying where each call comes from.

As a general advice:

  • Use Awake to initialize local references and the object itself.
  • Use Start to actually pass data / information between different components

All Awake methods will be completed once the first Start method is called.