Access script from another script not working - c#

I am trying to access a function, with a bool parameter, from one script to another and just can't get it to work. I have been looking around to try to understand what i am doing wrong.
Here is the script i am calling:
public class MainScript : MonoBehaviour {
public void ManageBoxCollider2D (bool shouldColliderBeEnabled) {
print (">>>>>>>>>>>>>>>>ManageBoxCollider2D: " + shouldColliderBeEnabled);
}
}
I am trying to call it from this script:
public class Sidebar1_Script : MainScript {
public MainScript mainScript;
void Start () {
mainScript.ManageBoxCollider2D (true);
}
}
There is a lot of other stuff in the scripts as well but this is what matters for this question
In the "Sidebar1_Script" I am trying to access "ManageBoxCollider2D" in "MainScript" but it does not work.
I do get the following message:
Object reference not set to an instance of an object
...which i do understand but can't figure out what i am doing wrong.
I would appreciate some help how to do this.
Thanks

It's because unity doesn't know what script that is. If you see in the inspector you're gonna find that public variable MainScript is still empty, also you can't assign scripts in the inspector (I don't know why though, when you drag it there it won't fit in).
Instead change your Sidebar1_Script like this:
public GameObject obj;
void Start () {
MainScript main = obj.gameObject.GetComponent<MainScript>();
main.ManageBoxCollider2D(true);
}
And then assign the game object of obj in the inspector (drag the game object to the public variable).

Related

Unity: Singleton script needs to be re-attached to gameobject on Editor relaunch to avoid null error?

I'm having a problem with my singleton class scripts I'd like to get your help with.
The script ultimately works, but every time I launch the Unity Editor I need to remove and re-attach the scripts to my gameobject to avoid null exception errors:
NullReferenceException: Object reference not set to an instance of an object
Any ideas why? I'm thinking I'm not initialising properly, but don't know where to go from there.
Here's a simplified singleton code attached as a component:
using UnityEngine;
public class Conductor : MonoBehaviour
{
public static Conductor Timing { get; private set; }
[SerializeField] private double bpm; // beats per minute
private void Awake()
{
if (Timing != null && Timing != this)
Destroy(this);
else
Timing = this;
}
public double Bpm
{
get { return bpm; }
set
{
bpm = value;
}
}
}
and I call the code in another script as follows e.g.
Conductor.Timing.Bpm;
Thanks in advance!
best, Rob
I found my answer 1 minute after posting the question lol:
[ExecuteAlways]
at the top of the class seemed to fix it. I also put the script in question before the default execution time in script execution order

Create a master script to manage other scripts

I'm working on creating a master script in Unity to control the other scripts. I'm stuck at one part which is the master script can call function from the others.
For example below is script B
public class B
{
void Test()
{
Dosomething;
}
}
Script A will be the master one that control script B. Is there any way that you can call Test() in script B like A.Test()?
I tried interface but then I still have to create another Test() function inside script A. This will be troublesome if I include more scripts with more functions.
Any advice would be appreciated.
This is from the Unity tutorials. Should be a good start...
public class UsingOtherComponents : MonoBehaviour
{
public GameObject otherGameObject;
private AnotherScript anotherScript;
private YetAnotherScript yetAnotherScript;
private BoxCollider boxCol;
void Awake ()
{
anotherScript = GetComponent<AnotherScript>();
yetAnotherScript = otherGameObject.GetComponent<YetAnotherScript>();
boxCol = otherGameObject.GetComponent<BoxCollider>();
}
void Start ()
{
boxCol.size = new Vector3(3,3,3);
Debug.Log("The player's score is " + anotherScript.playerScore);
Debug.Log("The player has died " + yetAnotherScript.numberOfPlayerDeaths + " times");
}
Okay, so the first things you should be aware about is that you really cant use static classes and functions in unity. That has something to do with every component on a gameobject essentially being a script the is instanced. So simply typing "using ScriptB" on the top and the calling the function like "ScriptB.Test();" really wont do anything.
What you need to do is to pass in a Script B reference as a variable in to Script A and then assign either drag it in editor or assign it via Script A. But in any case both scripts have to be in the same scene and assign to any game objects that are in that scene (they dont have to be on the same one)
So the final solution would look like this:
public class A
{
public B refToB;
void Start()
{
//we call the function here
refToB.Test();
}
}
public class B
{
public void Test(){
//we can do something here :)
}
}
Only thing for this to work is thet you need to assign the variable refToB through the inspector panel in the editor. A simple drag and drop action.
Hope it helps :)

Instantiated prefab should call a function from the main script?

I want something like this.
ComponentTest.cs - This script is attached to a empty game object in the scene.
public class ComponentTest : MonoBehaviour {
public GameObject boxPrefab;
void Start () {
GameObject temp = Instantiate(boxPrefab, new Vector3(0,0,0), Quaternion.identity) as GameObject;
temp.GetComponent<PrefabBox> ().go = gameObject.GetComponent<ComponentTest>().Yes();
}
public void Yes(){
print("yes");
}
}
and PrefabBox.cs - This script is attached to the prefab.
public class PrefabBox : MonoBehaviour {
public GameObject go;
void Start () {
go ();
}
}
I get this as error:
The member `PrefabBox.go' cannot be used as method or delegate
First of all, the go object is declared as a GameObject but then you assign a function to it and then call it like a function.
It looks like you want Closures in which you can store functions to variables and call them in the way you do.
This post covers it: http://answers.unity3d.com/questions/494640/capturing-a-variable-in-a-closure-behaves-differen.html
Seems the data type needs to be Action but best to read up on it to grasp it properly.
Good luck.

C#:Unity:Having trouble reference Rigidbody2d from different script

My scene has a main character, a balloon and a tether. I have a spring joint 2d connected to the balloon and I want to be able to change the connected body to the object the player clicks on. So far I have the following 2 scripts, one for the balloon and one for the connecting body:
Balloon:
using UnityEngine;
using System.Collections;
public class BalloonTethering : MonoBehaviour {
public SpringJoint2D theSpringJoint;
public Rigidbody2D theTether;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
theSpringJoint.connectedBody = theTether;
}
}
Connecting Body:
using UnityEngine;
using System.Collections;
public class TetherAny : MonoBehaviour {
public GameObject mainBalloon;
public Rigidbody2D iAmATether = new Rigidbody2D();
// Use this for initialization
void Start () {
mainBalloon.GetComponents<BalloonTethering>();
iAmATether = this.gameObject.GetComponents<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
}
void OnMouseDown(){
BalloonTethering.theTether = iAmATether;
}
}
I keep getting the following two errors on the TetherAny script:
(12,17): error CS0029: Cannot implicitly convert type 'UnityEngine.Rigidbody2D[]' to 'UnityEngine.Rigidbody2D'
(21,34): error CS0120: An object reference is required to access non-static member 'BalloonTethering.theTether'
If anyone could tell me where I'm going wrong it would be much appreciated :)
Thank you!
From the first error line I can tell that GetComponents() will return multiple Rigidbody2D object, not only one.
http://docs.unity3d.com/ScriptReference/Component.GetComponents.html
http://msdn.microsoft.com/en-us/library/aa288453%28v=vs.71%29.aspx
Use these two links to understand what is actually happening.
On the second one.. You are trying to access a member of a class of which you don't have the object to (that's not how you access other objects members)
http://msdn.microsoft.com/en-us/library/x9afc042.aspx
It seems to me that you should learn how to program the basics first, honestly. But that's just my opinion.
(12,17): error CS0029: Cannot implicitly convert type 'UnityEngine.Rigidbody2D[]' to 'UnityEngine.Rigidbody2D'
GetComponents returns a LIST of Rigidbodies. You cannot assign an entire list to one object. You need to use GetComponent, not GetComponents. Singular. The '[]' after Rigidbody2D in the error denotes that it is a list, not a single object.
(21,34): error CS0120: An object reference is required to access non-static member 'BalloonTethering.theTether'
This is because you never tell it what BalloonTethering you want it to reference. You need to use GetComponent() on the balloon object. There are other problems here, I'm surprised you aren't getting more errors. As soon as you attempt to access any of these variables there will be problems! I'll fix up the first script to get you on your way
using UnityEngine;
using System.Collections;
public class BalloonTethering : MonoBehaviour {
public SpringJoint2D theSpringJoint;
public Rigidbody2D theTether;
// Use this for initialization
void Start () {
theSpringJoint = this.gameObject.GetComponent<SpringJoint2D>();
}
// Update is called once per frame
void Update () {
}
}
You'll need to assign an object to theTether if you want anything to happen when you make it the connectedBody

NullReferenceException in Unity (C#)

I'm trying to add a Quest-object to a Person. It succeeds for one and gives a nullreferenceexception for the other, what am I doing wrong here?
P.S. The player and requestor are set in the Unity inspector.
public class GameCreator : MonoBehaviour {
private Quest quest;
public Player player;
public Requestor requestor;
void Start() {
quest = createQuest();
requestor.thisPerson.SetQuest(quest); //this is the problem
player.thisPerson.SetQuest(quest);
}
}
public class Player : MonoBehaviour {
public Person thisPerson;
void Start() {
thisPerson = new Person("Name");
}
}
public class Requestor: MonoBehaviour {
public Person thisPerson;
void Start() {
thisPerson = new Person("Name");
}
}
public class Person {
public Quest quest;
void SetQuest(Quest quest) {
this.quest = quest;
}
}
Any suggestions why this is going wrong?
Move your variable initialization in to Awake(), see the documentation for the following (paraphrased):
Awake is used to initialize any variables or game state before the
game starts.... and use Start to pass any information back and forth.
The way your GameCreator.Start() is written you are reliant on the arbitrary order in which Unity calls your scripts. GameCreator could be the first object called, in which case none of your other scripts have initialized their values.
Other possible errors:
You don't explicitly instantiate requestor, I'm going to assume this was done in Unity's Inspector.
You didn't include `createQuest()' which could be returning null.
As Jordak said, your Start methods can run in any possible order, so you can't rely on Start of some component in the other. You have several ways to address this issue:
You can move the basic initialization code to Awake(). However, this only allows you two levels of initialization, and can be insufficient in the future.
You can adjust script priority in the project settings. However, this is not really C# way, as this makes your code rely on logic that is not obvious from it.
Instead of initializing thisPerson field in the class initialization, create a public property to access it. (Public fields are bad practice in C# anyway). In this property, you can check if the field is null before returning it, and if it is, initialize it.

Categories