I found a way to get around this issue in the code, but I would like to understand why this is happening because I want to learn C# well. I´ve searched a lot and could simplify the problem, here's the simplified code:
/*MyCustomComponent.cs, this is attached to a game object in the scene*/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MyCustomComponent : MonoBehaviour {
void Start () {
Test testInstance = new Test();
Debug.Log (testInstance);
Debug.Log (testInstance == null);
Debug.Log (testInstance.Equals(null)); //Also tried the same with Equals()
Debug.Log (testInstance.value);
}
}
/*Test.cs*/
using UnityEngine;
using System.Collections;
public class Test : Object {
public int value = 7;
public Test(){
}
}
Console Output:
null
true
7
Why is this happening? How can be possible an Object is null but returns a property value?
Because Unity.Object works in a very peculiar way, basically it contains data regarding the managed object while pointing to the native object (crudely speaking).
Let's make an example: you create a new object inheriting from MonoBehaviour. Now you have two objects, one on the native side and one on the managed side. You can access the instanceID propriety of the managed object thanks to the fact that MonoBehaviour inherits from Unity.Object. Basically, the latter is used to show all the relative data of the object in the Inspector.
Now, you want to Destroy this game object by calling the same named method. The native object is actually destroyed, but the managed object is not, since all managed objects can only be destroyed by the garbage collector. It's at this point that Unity.Object becomes null: it's a trick of the Unity engine uses in order to avoid that you try to access a native object which doesn't exist anymore. Eventually, when the GC is called, this Unity.Object will be destroyed too.
And this is why you should never create an Unity object which inherits directly from Unity.Object, but only from MonoBehaviour or ScriptableObject.
Related
I have a Serializable object that I'm trying to store a method to be called. From this object, I would like to define a method from ScriptA to be called in ScriptB from SerializableScript.
The Serializable script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "NewFieldInput", menuName = "Data/New Field Input Scene")]
[System.Serializable]
public class CallInput {
public (some type) callMethod; // this is the confusing part
}
I would then have ScriptA have a method that will be called in ScriptB by referencing the value of callMethod passed into scriptB.
There are multiple solutions to your problem and it depends on the rest of your structure what would be the best to use.
UnityEvent where you create an event and add your target methods as listeners. In all other cases I would use C# events or actions instead but UnityEvents can be subscribed in editor.
You could create a base class that implements all the methods you want to call and inherit all your classes from that.
Basically the same but you create an Interface and add that to all classes you are calling.
It comes down to whether you want to only call your own code which you can modify or external code too. If the latter is the case you should go with option 1.
There are many more ways to do this but these came to mind first.
This is a super basic question, i'm sure, but I can't find an answer. So I notice that whenever another script is referenced at the top of a class you have to drag it into the Unity inspector slot as well or else it will return a null reference exception. For Example:
public class ExampleClass : MonoBehaviour
{
public ScriptExample1 scriptexample1;
public void Method()
{
scriptexample1.score++;
}
}
However, if the script is referenced as a method parameter you do not have to drag it into the inspector slot. For Example:
public class ExampleClass : MonoBehaviour
{
public void Method(ScriptExample2 scriptexample2)
{
scriptexample2.score++;
}
}
Can someone please explain to me why ScriptExample1 needs the script to be dragged into the inspector slot and ScriptExample2 doesn't?
Thank you,
Object references need to come from somewhere.
When you define a public field, Unity lists it in the inspector window, where dragging a component will set that reference for you through the designer.
Another way to initialize a field's reference is to fetch a component in your OnStart callback, and explicitly set it - this works by traversing the GameObject components and finding one of the correct type (not finding the component might throw an error right there, or leave the field null to blow up later, I'm not sure):
public SomeComponent someComponent;
public void OnStart()
{
someComponent = GetComponent<SomeComponent>();
}
caveat: air-code from memory for illustrative purposes
When you receive a component as a method parameter, you're deferring the responsibility of this initialization to the caller: if the caller does not initialize it or otherwise passes a null reference, consuming it will throw a NullReferenceException all the same.
I'm very new to coding, so apologies if any terminology is wrong. The code is trying to change a bool from false to true (it will do something more significant later, but I'm having issues doing this which is much simpler). I'm doing this in unity if that changes anything.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimalPositionalUpdates : MonoBehaviour
{
public PositionArrays ScripBeingAcessed;
// Use this for initialization
void Start()
{
//Find where the position is going to be input
int ArrayPosition = ScripBeingAcessed.FoodPosition.Length + 1;
PositionArrays.PositionBeingUpdated = transform.position;
}
// Update is called once per frame
void Update ()
{
}
}
Second Script (the one that I'm trying to influence)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PositionArrays : MonoBehaviour {
public bool PositionInProcess = false;
public Vector3 PositionBeingUpdated;
public Vector3[] FoodPosition = new Vector3[0];
// Use this for initialization
void Start () {
}
public void ArrayPosUpdate()
{
PositionInProcess = true;
}
// Update is called once per frame
void Update ()
{
}
}
Any help would be appreciated. As far as I know, there is some issue with me trying to use a static method like an instance??? Idk where it starts being static, and putting static in the method declaration for both only causes the same error to appear again referencing different components.
The error Is on line 16 of the first script.
Full error message
"CS0120 An object reference is required for the non-static field, method, or property 'PositionArrays.PositionBeingUpdated' 16 Active"
Obviously you are lacking fundamentals of OOP and delved into Unity development right away. You can do this, but I guess that programming in Unity will Taint your C# if you did not learn it properly. Having said that, you could certainly do it, but I'd suggest learning proper C# first and then use that sometimes uncommon Unity style.
There is some confusion around how the fields of your class are used, so let me explain: Usually, a class is a blueprint of sorts of which you can create instances. All of these instances adhere to that blueprint, which tells you exactly how you can use those instances (this is sometimes called implicit interface) and which data they contain (this is where Unity is somewhat sloppy). An instance bundles up the data with the methods you use to access and manipulate the data and you "always" need an instance to access these members, usually through a variable.
In your case, this variable is ScripBeingAcessed. This is the variable that holds your instance (at least if you did not forget to assign it) and therefor, you'd need the variable to access the field PositionBeingUpdated
void Start()
{
//Find where the position is going to be input
int ArrayPosition = ScripBeingAcessed.FoodPosition.Length + 1;
ScripBeingAcessed.PositionBeingUpdated = transform.position;
}
On static
Besides the members of a class that form the actual blueprint to create instances from, there are members that are accessed through the class itself. These are called static members. Anyway, since they are not bound to an instance, static members that contain any data will be the same regardless of where you access them from. This may be fine, if the static members are private (only instances of that class can access it) but I'd avoid it otherwise, since this creates a global state, which is not safe of being manipulated from other classes and can thus lead to hard to debug errors.
Odd question here - I have a gameobject with a class object attached. I instantiate the gameobject, and assign the class object with data from an existing class.
I then instantiate a second gameobject with the exact same class object attached and assign it the same data as the first object. If I modify the class attached to the first gameobject, it is different to the class attached to the second object, even though they both reference (or should) reference the same original class.
Can anyone think why this would happen?
if you make the variables you want to persist in the class your adding static, it will use the same instance for both cases, modifying both when you mod one.
check out this enemy class from unity3d's own dev pages
https://unity3d.com/learn/tutorials/topics/scripting/statics
using UnityEngine;
using System.Collections;
public class Enemy
{
//Static variables are shared across all instances
//of a class.
public static int enemyCount = 0;
public Enemy()
{
//Increment the static variable to know how many
//objects of this class have been created.
enemyCount++;
}
}
They are different instances of the same class, they don't reference the same class.
You should write a duplicate method to duplicate the values
I navigated the site and found no topic that asked (or gave) specific examples of static's utility on C#. I am a beginner and wanted to find given cases in which the usefulness of statics are proved, in order to go further than the conceptual understanding of what a static class/method/etc is. I know only of one or two examples, such as being able to create a method that produces an object or a value when ran, but keep that one value "for ever", by the means of removing the new values created (when the script runs again) if a value has been created before. The code for that is this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MusicPlayerScript : MonoBehaviour {
static MusicPlayerScript instance = null;
// Use this for initialization
void Start () {
if (instance != null)
{
Destroy(gameObject);
print("Duplicate self-destructing");
} else
{
instance = this;
GameObject.DontDestroyOnLoad(gameObject);
}
}
// Update is called once per frame
void Update () {
}
}
What other examples could anybody give me? Thank you!
That's an easy one. If you have something to do that is not directly related to a specific object of the class you want to group it into, you define a static method. For example if you need a very specific helper function that acts on one of your properties but not on the whole object.
A static member variable allows you to define for example a singled-out object of your class. For example if your class is "Scene" and you want an all-encompassing Scene-object named World, you would define static Scene World.
In many ways statics can be considered what has been known as globals in older programming languages. What makes them less dangerous than globals is proper namespace resolution. You don't see them everywhere unless you know how to get to them, ie. on which namespace path.