Component added at runtime throws null reference

The prefab tagged “Player” has the ShipWeapons() script added to it through the editor. The Vitals() script is added to the object when it is instantiated. Attempting to GetComponent the runtime-added script throws null reference, but referencing the editor-added component does not. Can someone explain what’s going on here? Line 54 throws an exception, but line 55 does not.

WeaponFire.cs:

using UnityEngine;
using System.Collections;

public class WeaponFire : Photon.MonoBehaviour {
	
	private float weapLife = 0.75f;
	private float timeExisted = 0.0f;
	private float weapVel = 1000.0f;
	//weapon explosion
	//weapon impact
	public GameObject firedBy {get; set;}
	
	private Vector3 vel;
	private Vector3 oPos;
	private Vector3 nPos;

	// Use this for initialization
	void Start () {
		nPos = transform.position;
		oPos = nPos;
		vel = weapVel * transform.forward;
		timeExisted = 0.0f;
	}
	
	// Update is called once per frame
	void Update () {
		timeExisted += Time.deltaTime;
		if(timeExisted >= weapLife){
			//The weapon has met or exceeded the maximum life setting, so destroy it over the network:
			if(firedBy != null)
			{
				if(firedBy.GetPhotonView().isMine)
				{
					PhotonNetwork.Destroy(gameObject);
					return;
				}
			}

			return;
		}
		nPos += transform.forward * vel.magnitude * Time.deltaTime;
		Vector3 dir = nPos - oPos;
		float dist = dir.magnitude;
		if (dist > 0){
			RaycastHit hit;
			if(Physics.Raycast(oPos, dir, out hit, dist)){
				if (hit.transform != firedBy && !hit.collider.isTrigger){
					if(firedBy != null)
					{
						if(firedBy.GetPhotonView().isMine)
						{
							if(hit.collider.gameObject.tag == "Player")
							{
								hit.transform.gameObject.GetComponent<Vitals>().takeDamage(10);
								hit.transform.gameObject.GetComponent<ShipWeapons>().TestFunction(10);
								Debug.Log("Collided object was a player!");
							}
							else
							{
								Debug.Log("Collided object wasn't a player!");
							}
							PhotonNetwork.Destroy(gameObject);
							return;
						}
					}
				}
			}
		}
		oPos = transform.position;
		transform.position = nPos;
		
	}
	
	void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
		
		if(stream.isWriting) {
			stream.SendNext(transform.position);
			stream.SendNext(transform.rotation);
		}
		else {
			transform.position = (Vector3)stream.ReceiveNext();
			transform.rotation = (Quaternion)stream.ReceiveNext();
		}
	}
}

In case you need, here is the code which adds the Vitals() script to the Player object at runtime (In a global script attached to an empty “Scripts” game object in scene):

	void SpawnPlayer() {
		GameObject playerShip = PhotonNetwork.Instantiate( this.shipStyle, Random.onUnitSphere * 2f, Quaternion.identity, 0 );
		Camera.main.GetComponent<MainShipCamera>().target = playerShip.transform;
		playerShip.AddComponent<PlayerMovement>();
		playerShip.AddComponent<WeaponController>();
		playerShip.GetComponent<WeaponController>().SetParent(playerShip);
		playerShip.AddComponent<Vitals>();
	}

Okay so in case anyone else is running into similar issues, I believe I figured out what the issue is.

In my script, I’m instantiating the player’s ship over the network when the player joins a game. Just after instantiating that object, I’m adding some components to the ship (this needs to be done this way for certain things like camera and player controls, otherwise everybody’s controls affect everybody else’s ships).

The problem was that I was only adding these components locally, so each player only had references to their own dynamically added components. As a result, when I attempted to access another player ship’s “Vitals” component, I had no reference to it. I haven’t worked out a solution exactly yet, but I’m thinking I will have to switch this around a bit and have each ship detect it’s own collisions and inflict damage to itself, rather than the other way around that I was trying.