I’m playing around with Properties (get and set) - just a learning exercise. I created a cube in my scene with a script attached on it named Cube.
This is my Cube script:
public class Cube : MonoBehaviour
{
private Vector3 position;
void Update()
{
position = this.transform.position;
}
public Vector3 Position {
get {
return position;
}
set {
position = value;
}
}
}
I have another empty game object with a script called GetPosition that gets the position of the cube and prints it to the log.
Here is my GetPosition script code:
public class GetPosition : MonoBehaviour
{
public Cube cube; // Drag Cube object in inspector window to this slot
void Update()
{
print(cube.Position);
}
}
In order for this to work, I had to add the ‘public Cube cube’ and drag the cube object in my scene to the GetPosition scripts inspector window. What if I wanted to programmatically add this object and it’s script class ‘Cube’ into my GetPosition script? I tried adding the following in the ‘Start’ method of the GetPosition script like this:
I have the cube tagged as ‘cube’ in the inspector. I get an error indicating that it cannot implicitly convert type ‘UnityEngine.GameObject’ to ‘Cube’. If I change the ‘public Cube cube’ to ‘GameObject cube’, it works, but then the ‘print(cube.Position)’ errors out in the Update method.
You’re missing something fundamental about how Unity is organized.
The fundamental unit of organization is the GameObject. GameObjects have many Components attached to them. Every GameObject has a Transform component, but you can also attach any number of other components to those GameObjects.
One type of Component you can attach is your very own custom MonoBehaviour class, such as your Cube, or GetPosition class. These components are attached to GameObjects in your scene.
When you call GameObject.FindGameObjectWithTag("cube");, what is returned is the GameObject, hence the name of the method “FindGameObjectWithTag”. If you want a reference to the Cube component that is attached to that Gameobject, you need to do this:.
void Start()
{
// Get the GameObject that our cube component is attached to, which we tagged "cube"
GameObject cubeGameObject = GameObject.FindGameObjectWithTag("cube");
// Get the Cube component that is attached to that GameObject
cube = cubeGameObject.GetComponent<Cube>();
}
Note in the inspector it is the GameObject that you are setting the tag on, not any particular component.
This is what it’s all about! Welcome. When I learn stuff in Unity I have the same face you do in your avatar.
Everything Praetor says above is spot on. Once you grasp that everything is a GameObject and the only thing differentiating them from each other is Components plugged into them, Unity starts to make a lot of sense, and you’ll be thinking of new ways to mix and match editor-based work (setting it up in advance) and adding stuff in code.
If you want more learning, Brackeys is a guy on Youtube who put out a ton of great tutorials. There’s plenty of others too, and you’ll soon see there are MANY different ways to get stuff done.
I appreciate it! I’ll take a look at Brackeys. I was starting down the Intermediate Scripting Unity lessons - first lesson was Properties I used to know a little more about Unity a few years back, but I had let other things get in the way that took me away from it…starting over it seems…
You can’t really “add” it to your GetPosition script. What you can do (as shown) is get a reference to that GameObject, and then to any of its Components, then get/set values and call methods on those Components, which include your scripts.
If you want, you can do everything in one line with dot notation. For example, this sets that object’s Position variable to 5: (note: just the variable, NOT the object’s actual position until you tell it explicitly):
Note that variables and methods have to be public for other scripts to access them. Also I’d avoid using “position” or “Position” as they are the same as the built-in names. I generally use “myPosition” or “tempPosition” etc. just to be sure things don’t clash. It’s also more immediately obvious (to me anyways) that it’s a custom variable.
While this is true, I think the closest Unity analogy would be a script that contains the logic to know what other scripts it needs attached at runtime.
Lets say you have an EnemyScript and it can choose how it moves at runtime.
If you had TrackedMovement and FlyingMovement scripts, the Enemy Script could decide to add an instance of either one:
gameObject.AddComponent<TrackedMovement>();
In the above, gameObject is a shortcut to the GameObject that the current script is on, and we’re saying “Add Tracked movement too!”
If instead it wanted FlyingMovement, it would just do that instead.
Even better, with interfaces it is possible for the enemy script to interoperate with any kind of movement (or other script that implements the movement interface) in a totally generic way.