Author Topic: Object reference not set to an instance  (Read 4724 times)

Rhithik

  • Guest
Object reference not set to an instance
« on: June 20, 2013, 09:20:30 PM »
Hello Aren. I've watched your Making a game from scratch with TNet video and I am trying to integrate updating the players position into the game when I click.

I instantiate the player over the network and spawn him in (like you did in the video) and when I click to walk I receive this error:

  1. NullReferenceException: Object reference not set to an instance of an object
  2. TNObject.Execute (System.String funcName, System.Object[] parameters) (at Assets/TNet/Client/TNObject.cs:326)
  3. TNObject.FindAndExecute (UInt32 objID, System.String funcName, System.Object[] parameters) (at Assets/TNet/Client/TNObject.cs:382)
  4. TNManager.OnForwardedPacket (System.IO.BinaryReader reader) (at Assets/TNet/Client/TNManager.cs:751)
  5. TNet.GameClient.ProcessPacket (TNet.Buffer buffer, System.Net.IPEndPoint ip) (at Assets/TNet/Client/TNGameClient.cs:659)
  6. TNet.GameClient.ProcessPackets () (at Assets/TNet/Client/TNGameClient.cs:603)
  7. TNManager.Update () (at Assets/TNet/Client/TNManager.cs:763)

This is part of my script for walking:

  1. void Update() {
  2.                 if(Input.GetKeyDown(KeyCode.Mouse0) && !MenuManager.isBlocking && !DialogManager.isBlocking) {
  3.                         tno.Send("SetNewPosition", TNet.Target.AllSaved);
  4.                 } else {
  5.                         if(transform.position != hit.point) {
  6.                                 tno.Send("MoveToPosition", TNet.Target.AllSaved);
  7.                         }
  8.                 }
  9.         }
  10.         [RFC]
  11.         void SetNewPosition() {
  12.                 Ray ray = camera.ScreenPointToRay(Input.mousePosition);
  13.                 Physics.Raycast(camera.transform.position, ray.direction, out hit, 1000.0f);
  14.                 dir = hit.point - transform.position;
  15.                 float angle = Vector3.Angle(dir, transform.forward);
  16.                 Vector3 k = Vector3.Cross(transform.forward, dir);
  17.                 k.Normalize();
  18.                 rot = k[1] * (angle * 2.5f);
  19.                        
  20.                 characterController.Move(gravityPower * Time.deltaTime);
  21.                 transform.Rotate(Vector3.up * rot * Time.deltaTime);
  22.                 characterController.Move(dir.normalized * Time.deltaTime * smooth);
  23.         }
  24.        
  25.         [RFC]
  26.         void MoveToPosition() {
  27.        // Define direction to move
  28.         dir = hit.point - transform.position;
  29.         // Get rotation smoothly
  30.         float angle = Vector3.Angle(dir, transform.forward);
  31.         Vector3 k = Vector3.Cross(transform.forward, dir);
  32.         k.Normalize();
  33.         rot = k[1] * (angle * 2.5f);
  34.         // Apply Gravity
  35.         characterController.Move(gravityPower * Time.deltaTime);
  36.         // Apply Rotation
  37.         transform.Rotate(Vector3.up * rot * Time.deltaTime * 5);
  38.         // Move towards direction (dir) normalized
  39.         characterController.Move(dir.normalized * Time.deltaTime * smooth);
  40.         }

I do have the player referenced in the TNManager script as well when instantiating the player.

Thanks for any help.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Object reference not set to an instance
« Reply #1 on: June 21, 2013, 02:44:20 AM »
What's on line 326 of TNObject for you? Our lines differ as that's just a bracket for me.

Rhithik

  • Guest
Re: Object reference not set to an instance
« Reply #2 on: June 21, 2013, 09:56:07 AM »
  1. for (int b = 0; b < parameters.Length; ++b)
  2. {
  3.      if (b != 0) types += ", ";
  4.      types += parameters[b].GetType().ToString();
  5. }

326 is the very top line of the loop.

This lies within the Execute() function.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Object reference not set to an instance
« Reply #3 on: June 21, 2013, 10:01:56 AM »
Interesting. You can wrap that in a null check like so:
  1.                                         if (parameters != null)
  2.                                         {
  3.                                                 for (int b = 0; b < parameters.Length; ++b)
  4.                                                 {
  5.                                                         if (b != 0) types += ", ";
  6.                                                         types += parameters[b].GetType().ToString();
  7.                                                 }
  8.                                         }
...but the question is why are you getting that? Did you have parameters at some point and joined a persistent channel? Make sure to delete server.dat save file.

Rhithik

  • Guest
Re: Object reference not set to an instance
« Reply #4 on: June 21, 2013, 02:40:14 PM »
That sure did fix it. I did not have any parameters either. But I did delete the server.dat file. Everything works as it should it seems. Thanks!

Rhithik

  • Guest
Re: Object reference not set to an instance
« Reply #5 on: June 21, 2013, 02:54:48 PM »
Actually I can walk correctly but now when another player joins the server each player can control each other. And they aren't synchronized on each screen, as in, they aren't even remotely close to the same position on one screen to another.

I am not sure what I am doing wrong. First time doing any network related gaming programming. You see my walk method as it is pretty straight forward. I have that script attached to my player. Any suggestions?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Object reference not set to an instance
« Reply #6 on: June 22, 2013, 05:58:53 AM »
Your MoveToPosition method uses mouse input inside -- which is obviously going to be different for every player. Every RFC is executed on each player separately.

You need to pass the final position instead.

Rhithik

  • Guest
Re: Object reference not set to an instance
« Reply #7 on: June 22, 2013, 05:00:51 PM »
OK so I tried to redo the entire script by passing the final position (I think). And I still have the same issue. It works perfectly when it is just one play on the server but more than two it goes crazy.

This script moves the player and updates the position on the network. (Well that's the goal)
  1. using UnityEngine;
  2. using TNet;
  3. using System.Collections;
  4.  
  5. public class GamePlayer : TNBehaviour {
  6.        
  7.         static public GamePlayer instance;
  8.         public float gravity = 20.0f;
  9.         public float speed = 15f;
  10.         private Vector3 gravityPower = Vector3.zero;
  11.         private Vector3 mDir = Vector3.zero;
  12.         private float mRot = 0f;
  13.         private CharacterController characterController;
  14.        
  15.         public Vector3 direction {
  16.                 set {
  17.                         tno.Send("OnSetTarget", Target.AllSaved, value);
  18.                 }
  19.                
  20.                 get {
  21.                         return mDir;
  22.                 }
  23.         }
  24.        
  25.         public float rotation {
  26.                 set {
  27.                         tno.Send("OnSetRotation", Target.AllSaved, value);
  28.                 }
  29.         }
  30.        
  31.         void Awake() {
  32.                 if(TNManager.isThisMyObject) {
  33.                         instance = this;
  34.                         characterController = GetComponent<CharacterController>();
  35.                         gravityPower.y = -gravity;
  36.                 }
  37.         }
  38.        
  39.         void Update() {
  40.                 characterController.Move(gravityPower * Time.deltaTime);
  41.                 transform.Rotate(Vector3.up * mRot * Time.deltaTime);
  42.                 characterController.Move(mDir.normalized * Time.deltaTime * speed);
  43.         }
  44.        
  45.         [RFC]
  46.         void OnSetTarget(Vector3 dir) {
  47.                 mDir = dir;
  48.         }
  49.        
  50.         [RFC]
  51.         void OnSetRotation(float rot) {
  52.                 mRot = rot;
  53.         }
  54.        
  55.         void OnNetworkPlayerJoin(Player p) {
  56.                 tno.Send("OnSetPosImmediate", p, transform.position);
  57.         }
  58.        
  59.         [RFC]
  60.         void OnSetPosImmediate(Vector3 pos) {
  61.                 transform.position = pos;
  62.         }
  63. }

This scripts finds the rotation and direction of the mouse click on the terrain.
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class ClickToMove : MonoBehaviour {
  5.         private RaycastHit hit;
  6.  
  7.         void Update() {
  8.                 if(Input.GetKeyDown(KeyCode.Mouse0) && !MenuManager.isBlocking && !DialogManager.isBlocking) {
  9.                         Ray ray = GamePlayer.instance.playerCam.ScreenPointToRay(Input.mousePosition);
  10.                         Physics.Raycast(GamePlayer.instance.playerCam.transform.position, ray.direction, out hit, 1000.0f);
  11.                         GamePlayer.instance.direction = hit.point - GamePlayer.instance.transform.position; //position
  12.                         float angle = Vector3.Angle(GamePlayer.instance.direction, GamePlayer.instance.transform.forward);
  13.                         Vector3 k = Vector3.Cross(GamePlayer.instance.transform.forward, GamePlayer.instance.direction);
  14.                         k.Normalize();
  15.                         GamePlayer.instance.rotation = k[1] * (angle * 2.5f); //rotation
  16.                        
  17.                 } else {
  18.                         if(GamePlayer.instance.transform.position != hit.point) {
  19.                                 // Define direction to move
  20.                         GamePlayer.instance.direction = hit.point - GamePlayer.instance.transform.position;
  21.                         // Get rotation smoothly
  22.                         float angle = Vector3.Angle(GamePlayer.instance.direction, GamePlayer.instance.transform.forward);
  23.                         Vector3 k = Vector3.Cross(GamePlayer.instance.transform.forward, GamePlayer.instance.direction);
  24.                         k.Normalize();
  25.                         GamePlayer.instance.rotation = k[1] * (angle * 2.5f);
  26.                         }
  27.                 }
  28.         }
  29. }

These are my two scripts. They are both attached to the player which each player has there own camera attached as well. I feel like it should work but it doesn't.

Thanks again for any help!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Object reference not set to an instance
« Reply #8 on: June 23, 2013, 10:11:46 AM »
What's "goes crazy"?

Your 'angle' setting doesn't make sense to me. All you need to do is get direction vector (which you do), set Y to 0, and normalize it. You then have a normalized directional vector on the flat plane. You can then calculate the angle by using Quaternion.LookDirection(dir).eulerAngles.y.

Also you are basically sending updates every single update... and if you have 1000 FPS that means 1000 updates per second. This is a massive overkill. You need to send things periodically -- every so often, or -- ideally -- when there is a significant change.

Rhithik

  • Guest
Re: Object reference not set to an instance
« Reply #9 on: June 23, 2013, 11:27:29 AM »
OK so I changed up the script so it doesn't update a million times per second but I also recorded a video to show off what goes wrong (The same issue I've been having). [30 seconds] http://www.youtube.com/watch?v=kJSYsFUIBGI

This is what I am puzzled about.


edit: My script. Made it a lot more simple.

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class ClickToMove : MonoBehaviour {
  5.  
  6.         void Update() {
  7.                 if(Input.GetKeyDown(KeyCode.Mouse0) && !MenuManager.isBlocking && !DialogManager.isBlocking) {
  8.                         Ray ray = GamePlayer.instance.playerCam.ScreenPointToRay(Input.mousePosition);
  9.                         Physics.Raycast(GamePlayer.instance.playerCam.transform.position, ray.direction, out GamePlayer.instance.hit, 1000.0f);
  10.                         GamePlayer.instance.direction = GamePlayer.instance.hit.point - GamePlayer.instance.transform.position; //position
  11.         }
  12.     }
  13. }
  14.  

  1. using UnityEngine;
  2. using TNet;
  3. using System.Collections;
  4.  
  5. public class GamePlayer : TNBehaviour {
  6.        
  7.         static public GamePlayer instance;
  8.         public Camera playerCam;
  9.         public float gravity = 20.0f;
  10.         public float speed = 15f;
  11.         public RaycastHit hit;
  12.         private Vector3 gravityPower = Vector3.zero;
  13.         private Vector3 mDir = Vector3.zero;
  14.         private float mRot = 0f;
  15.         private CharacterController characterController;
  16.        
  17.         public Vector3 direction {
  18.                 set {
  19.                         tno.Send("OnSetTarget", Target.AllSaved, value);
  20.                 }
  21.                
  22.                 get {
  23.                         return mDir;
  24.                 }
  25.         }
  26.        
  27.         public float rotation {
  28.                 set {
  29.                         tno.Send("OnSetRotation", Target.AllSaved, value);
  30.                 }
  31.         }
  32.        
  33.         void Awake() {
  34.                 if(TNManager.isThisMyObject) {
  35.                         instance = this;
  36.                         characterController = GetComponent<CharacterController>();
  37.                         gravityPower.y = -gravity;
  38.                 }
  39.         }
  40.        
  41.         void Update() {
  42.                 mDir = hit.point - transform.position;
  43.         //      transform.Rotate(Vector3.up * mRot * Time.deltaTime);
  44.                 if(transform.position != hit.point)
  45.                         characterController.Move(gravityPower * Time.deltaTime);
  46.                         characterController.Move(mDir.normalized * Time.deltaTime * speed);
  47.         }
  48.        
  49.         [RFC]
  50.         void OnSetTarget(Vector3 dir) {
  51.                 mDir = dir;
  52.         }
  53.        
  54.         [RFC]
  55.         void OnSetRotation(float rot) {
  56.                 mRot = rot;
  57.         }
  58.        
  59.         void OnNetworkPlayerJoin(Player p) {
  60.                 tno.Send("OnSetPosImmediate", p, transform.position);
  61.         }
  62.        
  63.         [RFC]
  64.         void OnSetPosImmediate(Vector3 pos) {
  65.                 transform.position = pos;
  66.         }
  67. }

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Object reference not set to an instance
« Reply #10 on: June 23, 2013, 03:39:26 PM »
Let's examine your Update function.
  1. void Update()
  2. {
  3.     mDir = hit.point - transform.position;
  4.     if(transform.position != hit.point) characterController.Move(gravityPower * Time.deltaTime);
  5.     characterController.Move(mDir.normalized * Time.deltaTime * speed);
  6. }
Your 'mDir' gets set every update. Regardless of whether this is a player-controlled GamePlayer, or another player's. The 'mDir' you set in the RFC call gets overwritten on the very next update.

Your 'direction' is not actually direction. It's just a delta vector. Direction implies a normalized vector.

For some reason you apply gravity only if the transform position is not equal to the hit position.

I'd look further, but 3 lines of code in the update already uncovers 3 issues... You really should debug your code more. I recommend commenting it thoroughly in english -- every single line. Use it to validate the flow of your logic.

wtfork

  • Guest
Re: Object reference not set to an instance
« Reply #11 on: July 04, 2013, 04:35:53 PM »
If that is happening to you is what happened to me, you're trying to send a Struct or some other object along as a parameter, and the type of object you're sending is not serializable. See: TNUnityTools.cs for a list of the types that it plays nice with. I was sending an array of Touch data but all I really needed was the Position, FingerId and Phase variables so I'm sending them along as individual arrays now (two floats since touch positions ignore Z, and two ints for the ID and Phase enum). Works perfectly.