use a class in another script

Good morning all,

I am creating multiple cameras, with positions and rotations as follows:

 foreach (CameraParam cam in camerasInJson.cameras)
        {
         
             var rgbd_cam = Instantiate(prefab); // Instantiate a camera clone in each iteration
                   
       
             rgbd_cam.name = cam.camera_name; // giving to json name to object name
             rgbd_cam.fieldOfView = cam.HFOV;
             rgbd_cam.tag = cam.camera_name; // Tag the camera
             rgbd_cam.transform.parent = cam_parent.transform; // each camera take "cam_parent" as parent
             cam_parent.name = "RIG"; // naming the cam_parent as "RIG"
             cam_parent.transform.position = new Vector3 (0,25, 10); // Define the position of our RIG in the world cs of unity”
             pos = ExtractPosition(cam.projection_matrix); // Extract our position from the 4x4 transformation matrix
             rgbd_cam.transform.localPosition = pos; // set the position of camera relative to the RIG parent
             rot = ExtractRotation(cam.projection_matrix); // set the rotation relative to the RIG parent from our transformation matrix.
             rgbd_cam.transform.localRotation =rot; // set the rotation of camera relative to the RIG parent
             rgbd_cam.GetComponent<AudioListener> ().enabled  =  false; //disable the listener

             //define the RGB texture as child of cam.
            
             var rgbtexture_cam = Instantiate(rgbd_cam);
             rgbtexture_cam.transform.parent = rgbd_cam.transform;
             rgbtexture_cam.name = cam.camera_name +"_rgb";
             rgbtexture_cam.transform.localPosition = pos;
             rgbtexture_cam.tag=cam.camera_name+"rgb";

           
            // define the depth texture as child of cam
             var depth_cam= Instantiate(rgbd_cam);
             depth_cam.transform.parent = rgbd_cam.transform;
             depth_cam.name = cam.camera_name +"_depth";
             depth_cam.transform.localPosition = pos;
             depth_cam.tag=cam.camera_name +"depth";
             depth_cam.gameObject.AddComponent <DepthPostprocessing>();

                       
           
         }

I’m trying to compact my code to create a camera class that can do all of this, and then instantiate rgbd camera objects.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraRGBD : MonoBehaviour




{
   
  private Camera camRGBD;
  private GameObject cam_parent;

   
    public CameraRGBD (string mycamRGBDname,string mycamTAGname,int theHFOV, string parentcam_name , Vector3 mycam_pos,Quaternion mycam_rot)
{
  var rgbd_cam = Instantiate(camRGBD);
  rgbd_cam.name = mycamRGBDname;
  rgbd_cam.tag = mycamTAGname;
  rgbd_cam.fieldOfView=theHFOV;
  rgbd_cam.transform.parent = cam_parent.transform;
  cam_parent.name = parentcam_name;
  cam_parent.name = mycamTAGname;
  rgbd_cam.transform.localPosition = mycam_pos;
  rgbd_cam.transform.localRotation =mycam_rot;
   rgbd_cam.GetComponent<AudioListener> ().enabled  =  false;


}  

}

And on my main code I modify as follows:

foreach (CameraParam cam in camerasInJson.cameras)
        {
         
         
           
         CameraRGBD camrgbd;
          camrgbd = new CameraRGBD(cam.camera_name,cam.camera_name, cam.HFOV, "RIG" ,pos,rot);
          pos = ExtractPosition(cam.projection_matrix);
          rot = ExtractRotation(cam.projection_matrix);
         
           
         }

But I have the following error :

Any help ?

The answer is always the same
 ALWAYS. It is the single most common error ever.

In this case you’re passing null to an Instantiate() call somewhere, which doesn’t change the problem at all.

Don’t waste your life spinning around and round on this error. Instead, learn how to fix it fast
 it’s EASY!!

Some notes on how to fix a NullReferenceException error in Unity3D

  • also known as: Unassigned Reference Exception
  • also known as: Missing Reference Exception
  • also known as: Object reference not set to an instance of an object

http://plbm.com/?p=221

The basic steps outlined above are:

  • Identify what is null
  • Identify why it is null
  • Fix that.

Expect to see this error a LOT. It’s easily the most common thing to do when working. Learn how to fix it rapidly. It’s easy. See the above link for more tips.

This is the kind of mindset and thinking process you need to bring to this problem:

https://discussions.unity.com/t/814091/4

Step by step, break it down, find the problem.

Here is a clean analogy of the actual underlying problem of a null reference exception:

https://discussions.unity.com/t/840647/7

How are you assigning anything to “camRGBD” or “cam_parent”? They will just be null by default unless you assign something to them.

Additionally, don’t use constructors with MonoBehaviour derived classes. Bad Things can happen.

Why not use a function instead of a class? You are not storing the CameraRGBD instances anywhere, so I am not sure what the point of using a class here is.

2 Likes

Actually @bobisgod234 , that’s almost certainly an issue
 even IF the private fields were public or marked for serialization, the ctor() happens a) in another thread, and b) long before the serialized data is reinjected into the fields.

OP: stop using ctors() for MonoBehaviours.

2 Likes

From what I understand is that the camRGBD object does not reference anything. So it returns a null object, which makes sense I understand.

But normally, doing a Resources.Load on the camRGBD should solve the problem, right? However, always the same thing.

Sure
 given at a bare minumum:

  1. you actually executed the Resources.Load() code at all (I do NOT see a Resources.Load() above so I am skeptical)

  2. you executed Resources.Load() BEFORE you tried to use what it tried to load

  3. Resources.Load() succeeded (path correct, correct syntax, asset type correct, etc.)

etc. along with probably 57 more things

Then you still have more investigation to do to discover your error!

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?

Knowing this information will help you reason about the behavior you are seeing.

You can also put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

https://discussions.unity.com/t/839300/3

CameraRGBD is a MonoBehaviour but you have a constructor for it and you are creating one with new.

You can’t use constructors for MonoBehaviours and you cannot create them with the new keyword. They cannot exist without being attached to a GameObject. Either remove : MonoBehaviour from the class declaration or create the CameraRGBD the correct way: using AddComponent or Instantiate.

2 Likes

In my case, I currently have a main code where I instantiate several cameras, and where I specify the camera parameters each time. However, I find that a little ugly. What I’m trying to do is create a cameraRGBD class, where I define all the camera parameters, to end up instantiate just an object of my class in my main program.

From what I understand from your statements, we cannot use a constructor by inheriting from the monobehaviour. but at the same time if I remove the monobehaviour, I will not be able to use its properties.

Can I nest a class? or something like that and use a constructor?

Thank u all for ur answers

and my second question would also be: in c #, how can we call a class defined in a script from another class?

I am desperately coming back to you because I still cannot solve my problem. I always try to create a class like this;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;



public class CameraExtensions : MonoBehaviour
{
    public class CameraRGBD

    {
        // get camera from the main camera in the scene
        public Camera cam;
        public GameObject rig;
      
        public CameraRGBD (string camera_name,string camera_tag, int camera_HFOV, string rig_name, Vector3 position, Quaternion rotation)

        {
         
          cam = Resources.Load<Camera>("Assets/Resources/Main Camera.prefab");
          var RGBD_cam = Instantiate(cam);
          RGBD_cam.name = camera_name;
          RGBD_cam.tag = camera_tag;
          RGBD_cam.fieldOfView = camera_HFOV;
          RGBD_cam.transform.parent = rig.transform;
          rig.name = rig_name;

        }


    }
}

by nesting a new class.

the call in main program :

            CameraRGBD mycam = new CameraRGBD (cam.camera_name,cam.camera_name, cam.HFOV, "RIG", pos, rot);

but I get the following error

I looked for a solution on the forums, they say that I have not referenced my class, but I did a using cameraRGBD on my main program.
It’s been a few days already, if anyone can help me !

I just googled “C# nested class” and the first result shows you how to use nested classes: Nested Types - C# | Microsoft Learn

I still don’t understand why you don’t just use a function. Your code is going to throw null reference exceptions because you try to use “rig”, but never assign any value to it.

What is the reason in using a class+constructor over a good-old-fashioned function here?

the reason why I want to use classes and not functions is that afterwards I intend to add functions according to each type of camera (rgb or depth).

As for the rig which has a null reference, I made a resources.load as gameobject. I removed the monobehaviour as suggested in previous posts.

my current problem is that when I try to attach my camera to my gameobject which is the rig, I have the following error

var rig = Resources.Load("Assets/Resources/GameObject.prefab") as GameObject;
          Camera RGBD_cam = rig.AddComponent<Camera>();

The answer is always the same
 ALWAYS. It is the single most common error ever.

Don’t waste your life spinning around and round on this error. Instead, learn how to fix it fast
 it’s EASY!!

Some notes on how to fix a NullReferenceException error in Unity3D

  • also known as: Unassigned Reference Exception
  • also known as: Missing Reference Exception
  • also known as: Object reference not set to an instance of an object

http://plbm.com/?p=221

The basic steps outlined above are:

  • Identify what is null
  • Identify why it is null
  • Fix that.

Expect to see this error a LOT. It’s easily the most common thing to do when working. Learn how to fix it rapidly. It’s easy. See the above link for more tips.

This is the kind of mindset and thinking process you need to bring to this problem:

https://discussions.unity.com/t/814091/4

Step by step, break it down, find the problem.

Here is a clean analogy of the actual underlying problem of a null reference exception:

https://discussions.unity.com/t/840647/7

In this case, go to the documentation for the Resources.Load() and pay attention to how to use it. I can see above from your example code you are misusing it in at least two (2) fundamental ways. Go see the examples for yourself to see those misuses and to learn how to correct them.

Thank u, i see the problem.

and one last thing, if i want to attach a camera to an object with an AddComponent, what would be the correct syntax?

i tried this :

          Camera RGBD_cam = rig.gameObject.AddComponent(typeof(Camera)) as Camera;

That should work fine. Personally I always use the typed variant to keep the code more concise and avoid repeating the type a lot.

Camera newCam = gameObject.AddComponent<Camera>();

By doing this, i obtain :

I don’t know where you put that line of code, but that line won’t work in a non-monobehaviour class.

I did not include it as I was highlighting the AddComponent() version
 obviously use the rig reference as you do in your original code.

From what I understand is that there is a dilemma. You cannot instantiate an object of a class inheriting from a monobehaviour by doing a new. and in parallel if we do not inherit the monobehaviour, we lose certain properties, what is the solution to this problem?

What properties of MonoBehaviour do you need?

You can create MonoBehaviours easily enough with AddComponent or Instantiate.