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.
Related
I'm working on a game in C# and I'm a little confused on this point here. Each ship has an identical AI Class that handles moving my spaceships around. And then each ship has it's own class, and in that class is a non-static function that checks if its about to smash into anything. Each ship has a different implementation of this. I did not think to derive them all from a base class, although I see how that might have helped in this situation.
It's pretty easy for me to get a reference to the ships in the AI Class. This is Unity so I can just GetComponent and if the ship is null it doesn't exist. So I thought to keep it cleaner, instead of checking for null for all the ships each time I want to check collision that I would just add a function pointer in the AI class and set it to the collision detect method in the ship class. But I must not understand how delagates work in C#, is this even possible like is in C++? All the examples I've seen so far are static, or don't seem to be pointing to member methods.
As code example I thought something like this might work, but it complains that I am treating collisionDetected like a variable when it is a type. So I guess I'm not sure what I'm doing here.
private delegate bool collisionDetected(Vector3 direction, float maxDistance);
// Start is called before the first frame update
void Start()
{
//moveToTarget(target);
fighter = gameObject.GetComponent<FighterBot>();
if (fighter != null) {
collisionDetected = fighter.checkCollision;
}
A delegate is just a template for a method signature (similar to an interface for types).
You still need something using this delegate type like e.g.
public collisionDetected fighterCollisionDetected;
void Start()
{
//moveToTarget(target);
fighter = gameObject.GetComponent<FighterBot>();
if (fighter != null) {
fighterCollisionDetected = fighter.checkCollision;
}
}
And later on
if(fighterCollisionDetected?.Invoke(direction, distance))
{
...
}
I'd like to create a short static function which I could call from everywhere to add into a List of Transform (in Unity), here's what I got:
public class MultipableTargetCamera : MonoBehaviour
{
public List<Transform> targets;
public static void AddToCamera(Transform target)
{
targets.Add(target);
}
}
But I get an error message in Unity after saving my script "An object reference is required for the non-static field, method, or property 'MultipableTargetCamera.targets'".
I've tried many things and researched a lot but I can't find any solution that fits my needs.
I want to keep a List of Transform, I dont want use an array or to use a list of strings/ints.
Any ideas?
Your method is static while your field is not. To understand this, ask yourself: Imagine you initialize multiple of these objects, what is the right "targets" list?
Besides of the already commented fact that static can be considered bad practice in this case, the answer is:
You can not access a non-static class member in a static function of that class.
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.
I am attempting to create a 2D game in Unity. Essentially, there are multiple types of 'agents': enemies and players. Programmatically, both classes 'enemy' and 'player' derive from the agent class. Then, there are different types of enemies (such as flying, ground enemies, etc).
My issue is that I need to call the Update function on all derivatives of an enemy. This is because there is code that needs to run for all enemies, and other code that should only run for some enemies - all enemies need to know where the player is, but only some enemies need to fly.
I read somewhere that you can use the new keyword, then call the base update function. However, with multiple levels of subclasses this seems inefficient and clunky as you have to state "new" for each new instance.
Is there any better way to call Update, Start and FixedUpdate (functions that are automatically called) than how I have implemented this below? Thanks in advance.
public abstract class Agent : MonoBehaviour
{
public void Start(){
// Run start code for all types of 'players', including AI
}
}
public class Enemy : Agent
{
public new void Start()
{
base.Start();
// Run start code specific to all enemies
}
}
public class WalkerEnemy : Enemy
{
public new void Start()
{
base.Start();
// Run start code specific to walking enemies ONLY
// Invoking Enemy.Start() will result in a call of Agent.Start() as well
}
}
Thank You for your help. Whilst I would call myself 'intermediate' in my programming skills, I doubt my object oriented knowledge is as fluent as it could be. So if there is some fundamental idea that I am missing, please let me know :)
First of all, when using inheritance structure, you usually want to avoid using the new keyword. Instead you mark the methods of the base class which you want to change for inheriting classes with the virtual keyword (or abstract if the baseclass does not contain code). That way you can re-use the code in the baseclass or even remove it all together.
An approach which may be even better in your case is to make an abstract method which you call in your baseclass start method. That way, inheriting classes MUST implement the method. This will be forced by the compiler.
Example:
public abstract class Agent : MonoBehaviour
{
private void Start(){
// Your code needed for all inheriting classes here.
// Call the abstract method which is defined on inheriting classes
OnStarting();
}
protected abstract void OnStarting();
}
public class Enemy : Agent
{
protected override OnStarting()
{
// Your enemy code here.
}
}
public class WalkerEnemy : Enemy
{
protected override OnStarting()
{
base.OnStarting(); // Call the code from the Enemy class
// Your walker enemy code here.
}
}
Also as you might see, I made your Start method private. Since Unity calls this by itself. You do not want to call this yourself from anywhere in your application. The OnStarting methods are marked as protected, because they should only exist/ be used in the scope of this inheritance tree.
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.