- Home /
Pragma strict : GetComponent without knowing the name of the component
Hello,
I try to make my game iOS-compatible so I added #pragma strict
at the beginning of every script. That was going well, then I got an error I can't fix.
First, this is working well with pragma strict :
var pawnToDestroyScript : PawnScript ;
pawnToDestroyScript = pawnToDestroy.GetComponent("PawnScript");
pawnToDestroyScript.pawnBaseReset();
Then I try to get quite the same logic with this one, and here comes the problem :
static function NextStage(stageNumber : int) {
var stageToGo : String = "Level" + stageNumber;
var tempPlateauObj : GameObject = GameObject.Find("Plateau");
stageToGoScript : stageToGo = tempPlateauObj.GetComponent(stageToGo) as stageToGo;
stageToGoScript.InitLevel();
}
The error is "the name stageToGo does not denote a valid type ('not found')"
I tried with this form (as seen on other threads) :
var stageToGoScript : stageToGo = tempPlateauObj.GetComponent.<stageToGo>() ;
--> not working
I tried to add "`as stageToGo`" at the end as seen on other threads... --> not working
Then I tried to change the type of stageToGo :
var stageToGo : String
--> not working (it was, without pragma strict)
or
var stageToGo : MonoBehaviour
--> not working
or
var stageToGo : Component
--> not working, nor with GameObject, nor with GameObject.Component nor with Component.stageToGo (I know I'm a noob ;))
--> What is the type of my stageToGo variable ? It seems I cannot write " var stageToGoScript : stageToGo " since "stageToGo" is not the actual name of the component. The actual name of this component is formed of a string ("Level") and an integer (stageNumber). (Then I have several script attached to "Plateau", called "Level1", another one called "Level2", etc.)
So what can I do to respect pragma strict with this one ?
I'm new to programming, and I'm sure there are several ways to solve my probleme: I'm eager to learn, so any tip will be welcome :)
I realize that with all my unsuccessful tries, I forgot to say that this is the original version, working well without pragma strict :
static function NextStage(stageNumber : int) {
var stageToGo : String = "Level" + stageNumber;
var tempPla$$anonymous$$uObj : GameObject = GameObject.Find("Pla$$anonymous$$u");
var stageToGoScript = tempPla$$anonymous$$uObj.GetComponent(stageToGo) ;
stageToGoScript.InitLevel();
}
I still don't have any solution for my problem :/ I had to use a very bad solution, that is
var tempPla$$anonymous$$uObj : GameObject = GameObject.Find("Pla$$anonymous$$u");
if (currentStage == 2) {
var stageToGoScript2 : Level2 = tempPla$$anonymous$$uObj.GetComponent("Level2") ;
stageToGoScript2.InitLevel();
}
else if (currentStage == 3) {
var stageToGoScript3 : Level3 = tempPla$$anonymous$$uObj.GetComponent("Level3") ;
stageToGoScript3.InitLevel();
}
etc. I know this is awful...but it's temporary, until someone helps me (please) ;)
Why do you need every different stage to be a different type? Why can't you just make one 'level load' script, which is paramaterised for different levels? It seems like a very wasteful way to manage this (not to mention difficult to call from script!).
Thank you all for your comments and help.
I would have no problem if I would put every level parameters in a single script (ie load level script). But I don't want to have a single very big level script when I have 200 levels. So I need to call a single script for each level so this is sustainable on the long
@Eric5h5 :
Thank you for your advice about not using strings with GetComponent, I did not notice. And thanks for the re$$anonymous$$der about lowercase in variable name too. About your solution, I cannot use Send$$anonymous$$essage since the code does not allow me to find the right script (that is my 1st problem). $$anonymous$$aybe I could rename every function InitLevel() in InitLevel1, InitLevel2, etc. and use Broadcast$$anonymous$$essage but it seems risky and not very optimized for iPhone (?)
@DaveA :
Thank you about GetType, I did not try yet but I will. I don't want to use "Application.LoadLevel" because all my objects remain, the level script is the only things changing from one level to the other, so I don't want to have to deal with DontDestroyOnLoad, and keep memory of every parameter of the scene while my "level" only contains some pawns position and attributes.
@dan :
I did not find any direct solution but I did not try yet the solution by DaveA to use GetType. Ins$$anonymous$$d I changed my structure and each level is now a X$$anonymous$$L file, that I load as a TextAsset, so I can store every level in a separate file and add levels easily (and people who don't have unity can make levels in X$$anonymous$$L and test them... in theory because for now I cannot manage to have the game load external files)
Here's my new code for this if it can help you : (I have in the "Ressources" folder my xml named "xLevel1.xml", etc.)
public function LoadXmlLevel (levelNb : int) {
var levelName : String = "xLevel" + levelNb;
var levelTest : TextAsset = Resources.Load(levelName, TextAsset) as TextAsset;
if(levelTest != null)
{
var reader:XmlTextReader = new XmlTextReader(new StringReader(levelTest.text));
while(reader.Read())
{
if(reader.Name == "square")
{
var xCoord : int = parseInt(reader.GetAttribute("xCoord"));
var zCoord : int = parseInt(reader.GetAttribute("zCoord"));
var content : String = reader.GetAttribute("content");
CreateSquareX(xCoord, zCoord, content);
}
if(reader.Name == "camera")
{
var camNumber : int = parseInt(reader.GetAttribute("camNumber"));
}
}
lvl$$anonymous$$anager.SelectCamera(camNumber);
lvl$$anonymous$$anager.GameStart();
}
else { // if no xml file found, display a "more levels co$$anonymous$$g soon" message
lvl$$anonymous$$anager.interface$$anonymous$$oreCo$$anonymous$$gSoon = true ;
}
}
@Lockstrike: Send$$anonymous$$essage doesn't require finding scripts; that's kinda the point. All you need is a GameObject.
Answer by DaveA · Feb 19, 2012 at 03:27 AM
I played with this some last year, I think it was related to this: http://msdn.microsoft.com/en-us/library/w3f99sx1.aspx
So maybe try something like
tempPlateauObj.GetComponent(Type.GetType("Level3"))
But you may want to consider making all these 'level' types subclasses of, say, 'level', and then you can use vars of type 'level'. Although syclamoth's suggestion is probably less trouble.
Then again, if the intent is to literally change scenes (levels?) they you could use Application.LoadLevel("Level1") where Level1 would contain an object with a script with a Startup that initializes that level (and so on for other levels)
Answer by Eric5h5 · Feb 19, 2012 at 05:52 AM
I would bypass the issue and use SendMessage; it's for situations like this.
GameObject.Find("Plateau").SendMessage("InitLevel");
Just as a side note, you generally very rarely would want to use strings with GetComponent, and you don't need to cast or use extra variables or anything. e.g., instead of
var pawnToDestroyScript : PawnScript ;
pawnToDestroyScript = pawnToDestroy.GetComponent("PawnScript");
pawnToDestroyScript.pawnBaseReset();
Just do
pawnToDestroy.GetComponent(PawnScript).pawnBaseReset();
That's all you need, although you should follow the convention of using lowercase for variable names and uppercase for class and method names. (Should be "PawnBaseReset".)
Did you ever get a solution for this besides Send$$anonymous$$essage. I'm trying to also load up different scripts on the fly and pull data from them and run functions that return values. So far very frustrating and no solutions, but works fine without pragma strict.
Answer by steinbitglis · Feb 29, 2012 at 09:29 PM
Try this:
static function NextStage(stageNumber : int) {
var stageToGo : String = "Level" + stageNumber;
var tempPlateauObj : GameObject = GameObject.Find("Plateau");
stageToGoScript : MonoBehaviour = tempPlateauObj.GetComponent(stageToGo) as MonoBehaviour;
stageToGoScript.SendMessage("InitLevel");
}
If you don't like the SendMessage
call, you could make an interface for your level scripts.
interface ILevel {
function InitLevel();
}
class Level1 implements ILevel {
function InitLevel() {
Debug.Log("Level 1 initializing");
}
}
And then do:
static function NextStage(stageNumber : int) {
var stageToGo : String = "Level" + stageNumber;
var tempPlateauObj : GameObject = GameObject.Find("Plateau");
stageToGoScript : ILevel = tempPlateauObj.GetComponent(stageToGo) as ILevel;
stageToGoScript.InitLevel();
}