Previously functional script now mysteriously does not invoke Start or Update methods

As per title, this script was working perfectly until another team member committed some other changes that did not affect this script in any way. Now for some reason, the Start and Update methods are not called. Here is the script in its entirety:

using UnityEngine;
using System.Collections;

public class foot_target_behaviour : MonoBehaviour {

public float distanceInFrontWhenWalking = 0.2F;
public float distanceInFrontWhenRunning = 0.1F;
[HideInInspector]
public string animationEventName;
[HideInInspector]
public string currentPlayingAnimation = "idle";
public float stepDownTolerance = 0.1F;
public float stepUpTolerance = 0.35F;
public GameObject player;
float objectiveSlopeAngle;
RaycastHit hit;
CustomCharacterController cc;
Camera cam;
AudioSource sound;
public AudioClip footstepSound;
public AudioClip stumbleSound;
Vector3 vectorToGround = Vector3.zero;
Animator anim;
[HideInInspector]
public TerrainInfo footstepTerrain;
bool isGrounded;
bool isInFront = false;

// Use this for initialization
void Start () {
	cc = player.GetComponent<CustomCharacterController> ();
	sound = GetComponent<AudioSource> ();
	vectorToGround = Vector3.down * cc.GetComponentInParent<CapsuleCollider> ().height / 2F + Vector3.up * cc.stepUpTolerance;
	anim = cc.GetComponentInChildren<Animator> ();
	cam = cc.GetComponentInChildren<Camera> ();
	transform.position = player.transform.position;
	SettleToGround ();
}

// Update is called once per frame
void Update () {
	transform.rotation = cc.transform.rotation;
	// vector that is orthogonal to hit.normal and vector3.up
	// rotate around this
	transform.RotateAround(transform.position, Vector3.Cross(Vector3.up, hit.normal), Vector3.Angle(hit.normal, Vector3.up));
}

void SettleToGround() {
	int layerMask = 1 << 8;
	if (Physics.Raycast(transform.position, Vector3.down, out hit, 100, layerMask)) {
		if (hit.distance < (stepDownTolerance + stepUpTolerance) * 2) {
			isGrounded = true;
			transform.position += Vector3.down * hit.distance;
			objectiveSlopeAngle = Vector3.Angle (hit.normal, Vector3.up) * Mathf.Deg2Rad;
		} else {
			isGrounded = false;
		}
	}
}

public void HandleStep() {
	isInFront = true;
	if (cc.IsGrounded()) {
		sound.pitch = 1.0f + Random.Range (-0.1f, 0.1f);
		sound.volume = 1.0f + Random.Range (-0.2f, 0.0f);
		sound.PlayOneShot (footstepSound);
		float speedStumbleMultiplier = 1 + Mathf.Pow ((cc.rigidbody.velocity.magnitude / (cc.sprintSpeed)), 5);
		float angleStumbleChance = 1000;
		int layerMask = 1 << 8;
		if (Physics.Raycast(transform.position, Vector3.down, out hit, 100, layerMask)) {
			objectiveSlopeAngle = Vector3.Angle (hit.normal, Vector3.up) * Mathf.Deg2Rad;
			footstepTerrain = hit.collider.GetComponentInParent<TerrainInfo>();
			if (footstepTerrain != null) {
				angleStumbleChance = Mathf.Max (1, footstepTerrain.SlopeStumbleConstant - footstepTerrain.SlopeStumbleCoefficient * Mathf.Pow (ObjectiveSlopeAngleDeg (), footstepTerrain.SlopeStumbleExponent));
			}
		}
		float lookingAtFeetMultiplier = Mathf.Min (Mathf.Max (5.5F - 0.05F * Vector3.Angle (Vector3.down, cam.transform.forward), 0.25F), 4F);
		if (Random.Range (0.0f, 1.0f) < (speedStumbleMultiplier / (angleStumbleChance * lookingAtFeetMultiplier))) {
			sound.pitch = 1.0f;
			sound.volume = 1.0f;
			sound.PlayOneShot (stumbleSound);
			cc.Stumble();
		} else {
			sound.pitch = 1.0f + Random.Range (-0.1f, 0.1f);
			sound.volume = 1.0f + Random.Range (-0.2f, 0.0f);
			sound.PlayOneShot (footstepSound);
			cc.StableStep();
		}
	}
}

public float TimeToLanding () {
	//float currentAnimationTime = 0;
	//float timeToMyEvent = 1;
	//float timeToLoop = 2;

	//if (timeToMyEvent > currentAnimationTime) {
	//	return timeToMyEvent - currentAnimationTime;
	//} else {
	//	return timeToLoop - currentAnimationTime + timeToMyEvent;
	//}
	if (currentPlayingAnimation == "walking") {
		return 0.6F;
	} else if (currentPlayingAnimation == "running") {
		return 0.25F;
	}
	return 1F;
}
public float ObjectiveSlopeAngleRad() {
	return objectiveSlopeAngle;
}

public float ObjectiveSlopeAngleDeg() {
	return objectiveSlopeAngle * Mathf.Rad2Deg;
}

public void DetermineTarget() {
	transform.position = cc.rigidbody.transform.position + vectorToGround + cc.rigidbody.transform.forward * (currentPlayingAnimation == "running" ? distanceInFrontWhenRunning : distanceInFrontWhenWalking) + cc.rigidbody.velocity * TimeToLanding() / anim.speed;
	SettleToGround ();

}

public bool IsGrounded() {
	return isGrounded;
}

public void MoveToBack () {
	isInFront = false;
}

public bool IsInFront() {
	return isInFront;
}

}

Now because the Start method is never called, the cc variable is null, so as soon as the HandleStep method is called, there is a null exception. Things I have tried:

  • Ensuring that the player variable is still pointing to the right object (it is)
  • Ensuring that the player objects were not changed in any way that would affect the setting of the cc variable in the Start method (they weren’t)
  • Debug logging in the Start and Update methods (the logging does not execute)
  • Destroying this object in the Start method and then pausing the game to see if it was destroyed (it wasn’t)
  • Ensuring that the class name and the file name are still the same (they are)
  • Deleting and recreating the class and re-applying it (didn’t work)
  • Ensuring that this class is still inheriting MonoBehaviour (it is)
  • Moving the script to the same folder as all the other scripts (no difference)
  • Posting on Unity Answers (results pending)
  • Closing Unity and MonoDevelop and re-opening both (no difference)
  • Nuking the code repository and re-getting from Github (no difference)
  • Debug.Log(cc); in the HandleStep method (it outputs “null”)
  • Rebuilding the solution (no difference)
  • Adding the two relevant scripts to the execution order with the foot_target_behaviour script after the CustomCharacterController script (no difference)
  • Removing the MonoBehavior inheritance and re-adding it (couldn’t build due to all the things that broke when I did it)
  • Manually invoking the Start method from the HandleStep method (null exceptions gone, but now it is complaining about trying to play disabled sounds; the sounds are not disabled)
  • See below for final “fix”

That’s strange, it doesn’t seem like anything within the script is causing the problem. First, I would go into the editor’s menu and hit “Assets->Sync MonoDevelop Project” to reset the solution in case something odd happened in the commit. If that doesn’t work the only other thing I can think of is to check the script execution order (Edit->Project Settings->Script Execution Order) to see if anything funky is going on there. Good luck!

Here’s how I “fixed” it:

TL;DR I recreated the script and the game objects that use it from scratch.

  1. Copied the contents of the script to the clipboard.
  2. Deleted the script from the Unity editor.
  3. Deleted the two objects that used the script (left foot and right foot).
  4. Created a new cube.
  5. Renamed it Left foot
  6. Resized it to a foot size.
  7. Removed the collider and renderer components.
  8. Added an audio source component.
  9. Added a new script on it called FootTargetBehaviour.
  10. Edited the script in MonoDevelop.
  11. Pasted the clipboard contents to the script.
  12. Renamed foot_target_behaviour to FootTargetBehaviour.
  13. Saved the script.
  14. Renamed all references to foot_target_behaviour to FootTargetBehaviour throughout the solution.
  15. Rebuilt the solution.
  16. Set up the audio files in the inspector.
  17. Added the player object in the inspector.
  18. Copied this object.
  19. Renamed the copy Right foot.
  20. Added Left foot and Right foot to the public variables on the player object as before.
  21. Ran the game.
  22. Rejoiced when it worked.
  23. Remained completely perplexed as to why this happened in the first place.