Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Zoom377 · Nov 29, 2014 at 07:02 PM · networkingnullreferenceexception

Strange GameObject null reference only in RPC

Hi.

I am working on a multi-player Frisbee simulator and I am having trouble working out why I am getting a Null Reference to a GameObject only in a RPC.

Code description:

I am using an authoritative server system. Every player who joins uses Network.Instatiate() to create their own player, but everything else is server side. I have a script (FrisbeeThrow.cs) that is disabled on all clients on Awake() so it only runs on the server. This is the problematic script that calculates who possesses the Frisbee and updates the position of the Frisbee.

In FrisbeeThrow.cs I use a GameObject reference (frisbeeOwner) to store which player has the Frisbee. If a clients player GameObject gets within range they will pick the Frisbee up and frisbeeOwner is set to point to that player GameObject.

Problem:

If the server wants to throw the Frisbee, a local method will be called and the frisbeeOwner reference will be set to null so the script knows that nobody is carrying the Frisbee. This works 100% correctly and the server can repeatedly throw and collect the Frisbee any amount of times, and there are no null references. If a client wants to throw the Frisbee, the client executes the code-

 networkView.RPC("ClientThrowFrisbee", RPCMode.Server, cameraTransform.position, cameraTransform.forward);

-and the RPC method defined in FrisbeeThrow.cs is called. I have spent hours placing Debug.Log() statements throughout the script and I have enabled full network log information in the console, and am certain that the RPC is called correctly.

The problem is that I get a null reference exception when trying to use the frisbeeOwner reference, only in the RPC.

Just so you know, the parameters passed in the RPC are the clients position and look direction at the time of mouse click, to provide a more accurate experience for clients.

Things I have tried:

  • Checking on both client and server that ALL unnecessary components are disabled (cameras, audio listeners, scripts ETC)

  • Lots of Debug.Log() statements

  • Creating a new RPC with a different name and removing the parameters

  • Checking all the network views are set up correctly

  • Numerous other tiny things

    Additional information:

  • All other global variables are not null in the RPC, only frisbeeOwner is null

  • I am using the default unity networking system

  • I am fairly new to unity networking, so I could have a misunderstanding of some basic concept, (although I have done lots of research and am quite confident)

  • ClientClick.cs is what the client uses to remotely request to throw the frisbee.

  • ClientClick.cs belongs to the same prefab GameObject that FrisbeeThrow.cs belongs to.

    Scripts:

FrisbeeThrow.cs

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class FrisbeeThrow : MonoBehaviour
 {
 
     //Various properties to set in the editor
     public float distanceFromFace;
     public float height;
     public float checkRadius;
     public float throwPower;
     public float rotationSpeed;
     public float pickupDelay;
     public Camera fpsCamera;
 
     Messages messager; //Class I wrote that displays messages to the player
 
     GameObject frisbee;
     GameObject frisbeeOwner;
     GameObject frisbeeOwnerCamera;
 
     bool canPickUp = true;
     float nextPickUpAllowed = 0;
     List<NetworkPlayerGameobject> networkPlayers = new List<NetworkPlayerGameobject>();
 
 
 
     void Awake()
     {
         if (Network.isServer)
         {
             fpsCamera = GetComponentInChildren<Camera>();
             frisbee = GameObject.FindWithTag("Frisbee");
             messager = GameObject.Find("Messaging Object").GetComponent<Messages>();
             networkPlayers.Add(new NetworkPlayerGameobject(Network.player));
         }
 
         if (!networkView.isMine || Network.isClient) //Disable if client
         {
             enabled = false;
         }
 
     }
 
 
 
     void Update()
     {
         if (Input.GetMouseButtonDown(0))
         {
             //If mouse not locked
             //Throw frisbee
             if (Screen.lockCursor)
             {
                 if (Network.isServer)
                 {
                     ServerThrowFrisbee();
                 }
             }
         }
     }
 
     void FixedUpdate()
     {
 
 
         //Double check just in case client gets to this part
         if (Network.isServer)
         {
 
             //If frisbee is null, find it
             if (frisbee == null)
             {
                 frisbee = GameObject.FindWithTag("Frisbee");
             }
 
             //Determine whether the frisbee can be picked up again
             if (Time.time > nextPickUpAllowed)
             {
                 canPickUp = true;
             }
 
 
             //If everything exists and frisbee can be picked up
             if (frisbee != null && frisbee.rigidbody != null && canPickUp && frisbeeOwner == null)
             {
 
                 //Find all players near the frisbee
                 List<GameObject> playersInRange = new List<GameObject>();
                 Collider[] colliders = Physics.OverlapSphere(frisbee.transform.position, checkRadius);
                 playersInRange.Clear();
                 for (int i = 0; i < colliders.Length; i++)
                 {
                     if (colliders[i].CompareTag("Player"))
                     {
                         playersInRange.Add(colliders[i].gameObject);
                     }
                 }
 
                 //If atleast one player is near frisbee
                 if ((playersInRange != null) && (playersInRange.Count > 0))
                 {
                     //Set frisbee owner to the first player in list
                     frisbeeOwner = playersInRange[0];
                     frisbeeOwnerCamera = frisbeeOwner.transform.FindChild("Main Camera").gameObject;
                     TakeFrisbee();
                 }
             }
 
 
             //If somebody owns the frisbee
             if (frisbee != null && frisbee.rigidbody != null && frisbeeOwner != null)
             {
                 //Update its position so it follows the player
                 frisbee.transform.position = frisbeeOwnerCamera.transform.position
                         + frisbeeOwnerCamera.transform.forward * distanceFromFace +
                         frisbeeOwnerCamera.transform.up * height;
                 frisbee.transform.rotation = frisbeeOwnerCamera.transform.rotation;
             }
         }
     }
 
 
     //The server calls this function to throw the frisbee
     void ServerThrowFrisbee()
     {
 
         if (frisbee != null && frisbeeOwner != null && frisbeeOwner == gameObject)
         {
             //Set parameters of frisbee to allow flight
             Debug.Log("FRISBEE THROWN");
             frisbee.rigidbody.isKinematic = false;
             frisbee.rigidbody.detectCollisions = true;
             frisbee.rigidbody.velocity = frisbeeOwnerCamera.transform.forward * throwPower;
             frisbee.rigidbody.angularVelocity = frisbee.transform.TransformDirection(new Vector3(0, rotationSpeed, 0));
             frisbee.GetComponent<FrisbeeScript>().thrown = true;
             SetFrisbeePickupDelay();
             frisbeeOwner = null;
             frisbeeOwnerCamera = null;
         }
     }
 
 
 
 
     //This is the problematic function!
     //"frisbeeOwner" is null for some reason in this RPC
     [RPC]
     void ClientThrowFrisbee(Vector3 posAtThrow, Vector3 forwardAtThrow, NetworkMessageInfo msi)
     {
 
         messager.AddMessage("ClientThrowFrisbee() called");
 
 
         //This probably over complicated code determines whether the RPC sender owns the frisbee
         bool RPCSenderOwnsFrisbee = false;
         for (int i = 0; i < networkPlayers.Count; i++)
         {
             if (networkPlayers[i].networkPlayer == msi.sender && networkPlayers[i].networkPlayerGameObject == frisbeeOwner)
             {
                 RPCSenderOwnsFrisbee = true;
             }
         }
 
 
         if (frisbee != null && frisbeeOwner != null && RPCSenderOwnsFrisbee)
         {
             //Set parameters of frisbee to allow flight
             messager.AddMessage("Conditions passed");
 
             Debug.Log("FRISBEE THROWN");
             frisbee.transform.position = posAtThrow + forwardAtThrow * distanceFromFace;
             frisbee.transform.forward = forwardAtThrow;
             frisbee.rigidbody.isKinematic = false;
             frisbee.rigidbody.detectCollisions = true;
             frisbee.rigidbody.velocity = forwardAtThrow * throwPower;
             frisbee.rigidbody.angularVelocity = frisbee.transform.TransformDirection(new Vector3(0, rotationSpeed, 0));
             frisbee.GetComponent<FrisbeeScript>().thrown = true;
             SetFrisbeePickupDelay();
             frisbeeOwner = null;
             frisbeeOwnerCamera = null;
         }
         else
         {
             Debug.Log("frisbeeOwner is null!");
         }
     }
 
 
 
 
 
 
     //Changes some properties of the frisbee so it behaves nicely when picked up
     void TakeFrisbee()
     {
 
         frisbee.rigidbody.velocity = Vector3.zero;
         frisbee.rigidbody.angularVelocity = Vector3.zero;
         frisbee.rigidbody.isKinematic = true;
         frisbee.rigidbody.detectCollisions = false;
         frisbee.GetComponent<FrisbeeScript>().thrown = false;
 
     }
 
 
     //Sets a timer that prevents the frisbee from being picked up immediately after throw
     void SetFrisbeePickupDelay()
     {
         canPickUp = false;
         nextPickUpAllowed = Time.time + pickupDelay;
 
     }
 
 
     void OnPlayerConnected()
     {
 
         StartCoroutine("DelayedAdditionToNetworkPlayerList");
 
     }
 
     //All code below: Maps each GameObject to their NetworkPlayer, so the script can determine whether 
     //the person who is trying to throw the frisbee actually owns it
     IEnumerator DelayedAdditionToNetworkPlayerList()
     {
         yield return new WaitForSeconds(5);
         networkPlayers.Add(new NetworkPlayerGameobject(Network.player));
     }
 
     class NetworkPlayerGameobject
     {
 
         public NetworkPlayer networkPlayer;
         public GameObject networkPlayerGameObject;
 
 
         public NetworkPlayerGameobject(NetworkPlayer np)
         {
             networkPlayer = np;
             networkPlayerGameObject = FindNetworkPlayersGameObject(np);
         }
 
 
 
         GameObject FindNetworkPlayersGameObject(NetworkPlayer np)
         {
             GameObject[] listOfPlayerGameObjects = GameObject.FindGameObjectsWithTag("Player");
             for (int i = 0; i < listOfPlayerGameObjects.Length; i++)
             {
                 if (listOfPlayerGameObjects[i].networkView.owner == np)
                     return listOfPlayerGameObjects[i];
             }
 
             return null;
         }
 
     }
 
 
 }




ClientClick.cs

 using UnityEngine;
 using System.Collections;
 
 public class ClientClick : MonoBehaviour
 {
 
     public Transform cameraTransform;
 
     void Start()
     {
         cameraTransform = transform.FindChild("Main Camera");
     }
 
 
     void Update()
     {
         
         if (Input.GetMouseButtonDown(0))
         {
             if (Screen.lockCursor)
             {
                 if (!cameraTransform)
                 {
                     cameraTransform = transform.FindChild("Main Camera");
                 }
                 if (cameraTransform)
                 {
                     networkView.RPC("ClientThrowFrisbee", RPCMode.Server, cameraTransform.position, cameraTransform.forward);
                 }
             }
         }
     }
 }






Do you have any idea of how to fix this? Or even a suggestion of something I could try?

Thanks very much for your time.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Unity networking tutorial? 6 Answers

Server receives RPCs after RemoveRPCs and Destroy 0 Answers

Networking-multplayer issue 1 Answer

How can I use a GameObject to hold all references in a network game? 0 Answers

[Mirror Networking] NullReferenceException on player when trying to start server a second time 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges