- Home /
Cannot seem to get a reference to a script component to work, despite many different attempts and a lot of work
Updated with latest code as per aldonoletto's instructions...
Current errors:
Assets/Scripts/invaderMovement.cs(16,97): error CS0119: Expression denotes a type', where a
variable', value' or
method group' was expected
Assets/Scripts/invaderMovement.cs(16,84): error CS1502: The best overloaded method match for UnityEngine.GameObject.GetComponent(System.Type)' has some invalid arguments Assets/Scripts/invaderMovement.cs(16,84): error CS1503: Argument
#1' cannot convert object' expression to type
System.Type'
I really appreciate this and hope it puts more than just me out of their misery in the future!
=================
Hi there,
I've spent about 6 hours on this problem, so before anyone flames me, says RTFM (or similar), or closes the thread, hear me out.
I have read MANY posts (over 30), spent a LONG time looking at similar questions and watching videos but cannot get this to work. I have read the documentation over countless times and it is NOT helping, so please just don't just post a link to the manual and/or scripting reference for GetComponent or whatever.
Everything that I've tried has given me an error. You can see that I've done this from scratch myself so I am NOT lazy, I am just learning.
I'm making a simple Space Invaders game, and I have one script for the invaders movement (below) and another script on an empty gameObject (invadersControllerObject) called invaderController.
Inside invaderController there are 3 static public booleans (movingLeft, movingDown, InvadersCanMove).
The code in the invaderMovement script (below) uses these to determine how the invaders should move. The reason I did it this way is so that all aliens move synchronously as a block (i.e. when one invader reaches the margin then they ALL move down one line and head back to the other side of the screen, and do it in 'steps' rather than smoothly).
I have had all types of errors, but the current one is:
"Assets/Scripts/invaderMovement.cs(53,60): error CS0176: Static member `UnityEngine.GameObject.Find(string)' cannot be accessed with an instance reference, qualify it with a type name instead"
...and similar when it encounters a call on a boolean.
I am obviously missing something simple here, but I can't find it. Is anyone able and willing to help me?
Many thanks, code below.
using UnityEngine; using System.Collections;
public class invaderMovement : MonoBehaviour {
//Time between Invader 'steps'
public float invaderSpeed;
//How far invaders move left or right
public float invaderMoveStep;
//How far invaders move vertically
public float invaderVertStep;
//Margin for invaders to keep from the edge of the screen
public float invaderMargin;
//Establishing connection to invaderController Script on invaderControllerObject for use in co-routine.
invaderController invaderCont = GameObject.Find("invaderControllerObject").GetComponent(invaderController);
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//If InvadersCanMove is true, the InvaderMove function will be called.
//InvadersCanMove is set to false to prevent multiple firings of the InvaderMove function
if (invaderController.InvadersCanMove){
StartCoroutine ("InvaderMove");
invaderController.InvadersCanMove = false;
}
}
//Function to move invaders. Called within update.
//It's not a function technically, it's a co-routine. This is so I can use the WaitForSeconds command.
//InvadersCanMove is reset to true so that the InvaderMove function can be called again.
IEnumerator InvaderMove (){
//Convert relative position of invader into 'proper' screen coordinates and assign it to a new construct - invaderPos
Vector3 invaderPos = Camera.main.WorldToScreenPoint(transform.position);
//Checks to see if it's time to move down
//If it is, moves down one step, then tests which margin it's at.
//Moves one step out of margin and sets direction for travel
//If it's NOT time to move down, are we travelling left or right?
//Moves accordingly by one step.
yield return new WaitForSeconds(invaderSpeed);
if (invaderCont.movingDown) {
transform.Translate (Vector2.up * -invaderVertStep);
//Stop invader moving down after this step
invaderCont.movingDown = false;
//If I don't move it out of the margin then invader keeps going down due to Update loop check.
//This should move it one step from margin
//Right margin
if (invaderPos.x > (Screen.width-invaderMargin)){
yield return new WaitForSeconds(invaderSpeed);
transform.Translate (Vector2.right * -invaderMoveStep);
invaderCont.movingLeft = true;
}
//Left margin
if (invaderPos.x < invaderMargin){
yield return new WaitForSeconds(invaderSpeed);
transform.Translate (Vector2.right * invaderMoveStep);
invaderCont.movingLeft = false;
}
} else {
if (invaderCont.movingLeft){
transform.Translate (Vector2.right * -invaderMoveStep);
} else {
transform.Translate (Vector2.right * invaderMoveStep);
}
}
//Reset variable for Update to fire again.
invaderCont.InvadersCanMove = true;
//If it's in the margins, it's time to move it down a row.
//Right margin
if (invaderPos.x > (Screen.width-invaderMargin)){
if (!invaderCont.movingLeft){
invaderCont.movingDown = true;
}
}
//Left margin
if (invaderPos.x < invaderMargin){
if (invaderCont.movingLeft){
invaderCont.movingDown = true;
}
}
}
}
Answer by aldonaletto · May 31, 2013 at 04:00 PM
You're using gameObject, which is a reference to the GameObject to which this script is attached, and should instead use GameObject, which is the GameObject class name:
invaderController invaderCont = GameObject.Find("invaderControllerObject").GetComponent(invaderController);
SIDENOTE: searching for an object by name is a slow operation - it would be much better to find the object and its script only once at Start:
invaderController invaderCont; // declare this variable outside any function
void Start(){
// assign to it only once at Start:
invaderCont = GameObject.Find("invaderControllerObject").GetComponent(invaderController);
}
Cheers.
I have sorted the typo and put that statement in start so it reads:
void Start () {
invaderController invaderCont = GameObject.Find("invaderControllerObject").GetComponent(invaderController);
}
But now I have:
Assets/Scripts/invader$$anonymous$$ovement.cs(25,105): error CS0119: Expression denotes a type', where a
variable', value' or
method group' was expected
Assets/Scripts/invader$$anonymous$$ovement.cs(25,92): error CS1502: The best overloaded method match for UnityEngine.GameObject.GetComponent(System.Type)' has some invalid arguments and... Assets/Scripts/invader$$anonymous$$ovement.cs(25,92): error CS1503: Argument
#1' cannot convert object' expression to type
System.Type'
All for that line (line 25 is where I'm attempting to make the reference)
And...
Assets/Scripts/invader$$anonymous$$ovement.cs(61,21): error CS0103: The name `invaderCont' does not exist in the current context
Every time I'm trying to access the boolean.
You should declare invaderCont outside any function: this makes it a member variable, a variable visible to everybody in this script instance and which retains its value while the instance exists.
The error messages probably are consequence of the first error. If you still have errors after fixing the variable invaderCont, edit your question and post the last script version - or simply post the code lines right after the error messages: we don't know to which code the errors are referencing after these changes.
So, for posterity, THIS is how that code should have looked:
//Declaring variable
invaderController invaderCont;
// Use this for initialization
void Start () {
//Connecting variable invaderCont to invaderController script component
invaderCont = GameObject.Find("invaderControllerObject").GetComponent<invaderController>();
}
I saw something in another post about using the general method for GetComponent with a reference to the docs. I still don't get it, but it removed my errors.
But now only 1 of my invaders ever moves, even though this script is attached to each one.
:-(
I would recommend you to have a look at this http://unitygems.com/script-interaction1/.
Ok, GetComponent(invaderController) is JS stuff - in C# you must use the generic version GetComponent< invaderController>() ins$$anonymous$$d.
Answer by fafase · May 31, 2013 at 03:54 PM
Well I would like not to but RTFM since gameObject.Find should be GameObject.Find line 48.
And I was ironic, you just did not see the typos. That happens when you stay too long in front of the computer.
Cheers for quick response.
Ironically, that's something that I only changed recently because I've been reduced to more 'random' tweaking, having exhausted all my avenues of logical inquiry.
Unfortunately, it doesn't solve my problem! I now have this error:
Assets/Scripts/invader$$anonymous$$ovement.cs(25,35): warning CS0219: The variable invaderCont' is assigned but its value is never used Followed by: Assets/Scripts/invader$$anonymous$$ovement.cs(61,21): error CS0103: The name
invaderCont' does not exist in the current context
..for each reference to the bools.
Am I correct to declare it in Start()? $$anonymous$$y understanding is that .Find is an expensive operation and shouldn't be run in update or a frequently used function. Or am I having problems because my main bit of action is in a co-routine rather than a function?
$$anonymous$$any thanks for patience.
You should declare invaderCont outside any function: this makes it a member variable, a variable visible to everybody in this script instance and which retains its value while the instance exists.
Okay, moved it to the top where the other variables are declared:
public class invader$$anonymous$$ovement : $$anonymous$$onoBehaviour {
//Time between Invader 'steps'
public float invaderSpeed;
//How far invaders move left or right
public float invader$$anonymous$$oveStep;
//How far invaders move vertically
public float invaderVertStep;
//$$anonymous$$argin for invaders to keep from the edge of the screen
public float invader$$anonymous$$argin;
//Establishing connection to invaderController Script on invaderControllerObject for use in co-routine.
invaderController invaderCont = GameObject.Find("invaderControllerObject").GetComponent(invaderController);
But now I have:
Assets/Scripts/invader$$anonymous$$ovement.cs(16,97): error CS0119: Expression denotes a type', where a
variable', value' or
method group' was expected
...which I must admit I REALLY don't understand (despite having done my homework!), and the CS1502 and CS1503 errors from before.
We're getting there, but this has been the story of my life today...
Just declare the variable outside any function, and assign to it inside Start - C# doesn't allow code outside functions. Take a look at my answer
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Why do I have to call ToString() when fetching a String from another script? 2 Answers
I'm having problems with referencing other scripts. 2 Answers
enemy attack not recognizing players stats 1 Answer
How to get a variable value from another script(C#)? 1 Answer