- Home /
Can't get script to access other script/class (c#)
Hi. I have searched a lot and tried a lot of different things, but I can't for the life of me get this to work, though it seems to me that it should be easy, so it's driving me nuts. I am not a programmer, and I've probably bit over more than I can chew, but I hope you will help anyway.
Ok, so here's the problem. I read that it's good to make each script/class do one specific thing instead of multiple things, so I've split up the functionality. I'm trying to make a turn based game and on the start of every turn the player's cash should be updated, which involves three different script talking to each other, but I can't get it to work. My problem involves these three scripts: turnControl (my state machine), turnStart, and playerResources.
Here's some of turnControl
using UnityEngine;
using System.Collections;
public class turnControl : MonoBehaviour {
private turnStart turnStartScript = new turnStart ();
public enum TurnStates {
START,
PLAYERTURN,
ENEMYTURN,
LOSE,
WIN
}
public static TurnStates currentTurn;
// Use this for initialization
void Start () {
currentTurn = TurnStates.START;
}
// Update is called once per frame
void Update () {
Debug.Log (currentTurn);
switch (currentTurn) {
case (TurnStates.START) :
//Calculate income, cash
turnStartScript.CalculateFinances();
currentTurn = TurnStates.PLAYERTURN;
//Resolve combat
//Random events
break;
As you can see, the turnControl script calls a method from turnStart. Here's the method:
using UnityEngine;
using System.Collections;
public class turnStart : MonoBehaviour {
private playerResources playerResourcesScript = new playerResources ();
public void CalculateFinances () {
Debug.Log("CALCULATE");
playerResourcesScript.playerTotalCash += playerResourcesScript.playerTotalIncome;
}
}
As you can see that script then references playerResources. It's simply a script that holds the player resources:
using UnityEngine;
using System.Collections;
public class playerResources : MonoBehaviour {
public string playerName = "Player";
public int playerStartingCash;
public int playerTotalIncome;
public int playerTotalExpenses;
public int playerTotalCash;
public int playerTerritories;
void Awake () {
DontDestroyOnLoad(transform.gameObject);
}}
But I Just. Cannot. Get it to work! playerResources doesn't register the change. The log outputs "CALCULATE" so I know the CalculateFinances method is being called, but the numbers don't change. Oh, and some other script changes the player's income to e.g. 250, and that does seem to work, so the player's cash should go to 250 on the start of the turn. But it doesn't.
I'm aware that I'm not supposed the "new" keyword to create instancse of the other scripts when I'm using monobehavior (unity gives me some warnings aobut it), but I have tried everything! I have tried removing monobehavior, I've tried the AddComponent way... Here's some examples of lines I've tried:
GetComponent<playerResources>().playerTotalCash = 100;
var playerTotalIncome = gameObject.AddComponent<playerResources>().playerTotalIncome;
var playerResourcesScript = gameObject.AddComponent<playerResources>();
GameObject controller = GameObject.Find("gameControllerMap");
int test= GetComponent<playerResources>().playerTotalIncome;
controller.GetComponent<playerResources>().playerTotalCash += test;
It seems that this should be very simple but I've spent hours trying to fix this. Sorry about the long question, I hope it makes a least some sense. Please help a desperate man. Thank you. (Btw. some of the scipts here are a little cut up so they don't take up too much space, but the syntax should be ok, I'm not getting any errors at least (though some warnings, as mentioned)).
Answer by Linus · Nov 05, 2014 at 10:31 PM
//Creating the variable
private turnStart turnStartScript;
void Start(){
//Could also be in Awake
//GameObject.Find is not optimal, but used once at start of a game is perfectly fine
turnStartScript = GameObject.Find("nameofthegameobjectthathasthescript").GetComponent<turnStart>();
}
For game managers that there only eve one of I often do:
public class SomeGameManager : MonoBehaviour {
public static SomeGameManager instance;
void Awake(){
instance = this;
}
}
//Then anywhere in other scripts I can do
SomeGameManager.instance.somePublicVariable;
//or
SomeGameManager.instance.somePublicMethod();
Note that SomeGameManager.instance is not available in other scripts before after Awake
Unity is not out to get you, its not joking about not using new
Halleluja, it works!! Thank you very much! Can I ask you, you say that using GameObject.Find is not optimal, but fine to do once. Is there a more effecient way? Because I think I'm going to have a lot of scripts calling each other, so I would like to do it the correct/best way:)
Glad to help. By once I mean once at startup for each script that needs it. When game is starting player is expecting having to wait a little.
When not to use it is inside Update() meaning it will search for the GameObject every frame.
If the GameObject is a child of the GameObject you are using the reference in, you should do transform.Find only child objects are searched then. If its in a parent you could use transform.parent.GetComponent()
Other ways, you could have a public variable, and drag the GameObject onto it in the inspector. I even think Unity will grab the component type for you from that object. I prefer having the scripts find them, so I dont need to reconfigure them.
You could also have one component that holds a reference to the most used managers. So the .Find is only done once per game object.
Ah okay, I think I understand. Thanks again and thanks for the extra insights.
@Linus Sorry to bump this thread, but it's similar to a problem I'm having. I (try to) deal exclusively in C# scripts. I have imported the Vehicle from the Standard Assets. This time around, they elected to put the scripts that control the car into their own Namespace. Now my scripts cannot access it, or vice versa. Well, to be honest, I was able to access their script by calling it through it's full namespace, but I got sick of that, so I remove the Namespace from the scripts and now my scripts can access it directly such as:
CarUserControl[] Racers = GameObject.FindObjectsOfType<CarUserControl>();
The problem is, I can't go in the other direction! The CarUserControl script cannot access any of my other scripts. Lines like this:
Gauge myGauge = GameObject.Find("Game").GetComponent<Gauge>();
Won't even compile, as it cannot find the reference or namespace. These are all C# scripts (even in the same directory), now all in the same Namespace, but I cannot access them. $$anonymous$$aybe it would help if I accessed my scripts through their full namespace, but I don't know what that is for the main game namespace.
Any help?
Your answer
Follow this Question
Related Questions
Change and Access another scripts Variables 1 Answer
Accessing classes class from other script 2 Answers
Access others functions C# 2 Answers
Accessing another script from a class 3 Answers
Distribute terrain in zones 3 Answers