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”