Unity c# how to properly use GetComponent [duplicate] - c#

This question already has answers here:
How to access a variable from another script in another gameobject through GetComponent?
(3 answers)
Closed 25 days ago.
I am in no way a coding novice but I just picked up unity and I'm trying "get it"
My question involves this code. it is not part of an active project. it is simply an attempt to understand the system
private SpriteRenderer beans2;
public Sprite beanimmage;
// Start is called before the first frame update
void Start()
{
beans2 = gameObject.GetComponent<SpriteRenderer>();
beans2.sprite = beanimmage;
}
from what I understand this code allows me to manipulate the SpriteRenderer of the game object this code is attached to by assigning it to beans2 and then changing the Sprite of beans2 to beanimmage and works fine in the system
My question is -
Is their a way to assign beans2 to the spriterenderer of a diffident game object? The object i have this code attached to is just a game object called test is their a way to assign the beans2 variable to the SpriteRenderer of my test2 object instead ?
something like this ?
beans2 = test2.gameObject.GetComponent<SpriteRenderer>();
beans2 = gameObject.test2.GetComponent<SpriteRenderer>();

The GetComponent() Function is apart of every gameobject so to get components on other gameobjects you need to reference that gameobject in a variable, something like this:
public GameObject test2;
private SpriteRenderer test2Renderer;
public Sprite beanImage;
void Awake()
{
test2Renderer = test2.GetComponent<SpriteRenderer>();
test2Renderer.sprite = beanImage;
}
Alternatively, you can just get the component of the test2 object from the inspector because you are using public variables. To do this make a sprite renderer variable field and make it public so it is shown in the inspector, then drag the test2 object into the field and it will automatically get the sprite renderer component off that object.
Finally, you could also just do this with one field. This method would be used when you only want to access the GameObject and nothing else:
public GameObject test2;
public Sprite beansImage;
void Awake
{
test2.GetComponent<SpriteRenderer>().sprite = beansImage;
}
Any way works and you should do it the second way if you want to work with public variables and rely on the inspector but if you only need the gameobject then go with method 3. Method 1 is probably the best way to do it so you can change the sprite later if you want.

Related

How do you create a default player for an enemy AI script in Unity? [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
In Unity (C#), why am I getting a NullReferenceException and how do I fix it? [duplicate]
(1 answer)
Closed 1 year ago.
I have an enemy AI script working that basically follows my player. Right now I have a "public GameObject player" that I have to assign manually by dragging my player prefab onto the slot. But I want to have a lot of enemies in the scene, so I don't want to have to do this manually for each one. How Can I give the EnemyController script a default player to follow?
I have a PlayerManager which I use to pass the position of my player to the enemy with:
public class EnemyController : MonoBehaviour
{
Transform target;
// Start is called before the first frame update
void Start()
{
target = PlayerManager.instance.player.transform;
}
That part works fine. So my thinking was, just make a public variable for the player like this:
public GameObject player = PlayerManager.instance.player;
But that didn't work. I got this error: "NullReferenceException: Object reference not set to an instance of an object"
Thank you so much for any help you can provide!
With public GameObject player = PlayerManager.instance.player; your field is initialized before the call of EnemyController's constructor, and you provided no control over the value / definition state of PlayerManager.instance.player (PlayerManager or instance or player which can be null and is null in your case). So it's "too early" to use it.
Instead, you can use the event playerJoinedEvent in the PlayerInputManager to assign the enemy to the played which just joined with an event handler, which checks that PlayerManager and instance and player are not null and then assign the player to the target.

How can I blank the screen for 2 seconds (configurable) between playing a sequence of 360-degree videos in Unity

I have written a C# script in Unity to play a sequence of 360-degree videos of one-min duration each. The script works as expected, thanks to the support received on stackoverflow. I would now like to add a delimiter of a few seconds between each video playback, something like a blank screen which would help differentiate between the beginning and end of each video.
I tried using a GameObject with an Image on a Canvas and then setting it active after each video is played. However, it does not work as expected.
private GameObject gameobject;
gameobject = GameObject.FindGameObjectWithTag("Delimiter");
gameObject.SetActive(true);
Unfortunately, GameObject.FindWithTag(string tag) only returns active GameObjects. You cannot find an object that is disabled with this method. There are a few solutions:
Set the GameObject reference to public or add the [SerializeField] attribute, allowing you to configure it in the editor.
Start the GameObject as active and cache a reference to it before it becomes inactive. (in the awake method, or elsewhere)
Update edit for more clarification on #2:
All GameObjects run Awake() and Start() before they perform any other logic.
You could move your
private GameObject canvasObject;
to a class-level variable (instead of inside a method), and inside of the Awake() method, like this:
void Awake()
{
canvasObject = GameObject.FindWithTag("Delimiter");
}
Now you have a cached reference to your canvasObject, so you don't need to perform a GameObject.FindWithTag every time. Now you can have this method:
public void TurnOnImage()
{
canvasObject.SetActive(true);
}

How do I access other elements in my predefined structured object in C#/Unity?

I made a predefined object called FOOD. Inside is a GameObject that points to a PreFab GameObject. That GameObject is also attached to a collision script. My question is, how do I access other elements of my structure such as health, calories, etc, inside my collision script?
public class FOODS: ScriptableObject
{
public GameObject preFabFood;
//points to a prefab object that is attached to a collision script
int health;
int calories;
float height;
float width;
}
//this is the script that is attached to the GameObject preFabFood
void OnCollisionEnter2D(Collision2D c)
{
//how do I access elements such as height, weight, etc?
}
You have two problems.
1) The properties are private, meaning that they aren't visible to other classes. The default visibility on member fields is private.
2) The properties aren't in a script attached to your prefab.
Fixing #2 (as Soraphis) suggests is sort of the right thing to do, however, you would want to remove the public GameObject preFabFood; field from your FOODS class if you're attaching the FOODS class to the prefab instance (as you don't need to carry a copy of the instantiated object with the instantiation). Just keep this in mind as you adjust your code (the code you posted looks like one script, but I suspect its supposed to be more than one, and should in fact be at least 2).
As for fixing #1, you have to make them public or access them from the same script. If you directly attach your FOODS class to your instantiated prefab and that the FOODS class contains the OnCollisionEnter2D method, then everything's fine.
But as I suspect you've got two classes that you're showing here, you'll need to do this:
public int health;
public int calories;
public float height;
public float width;
And then use a GetComponent() call from to get the one script from the other. e.g.
FOODS foods = this.gameObject.GetComponent<FOODS>(); //gets the FOODS script attached to this game object.
//Functionally identical to GetComponent<FOODS>();
int hp = foods.health; //etc
Note that you should call GetComponent as little as possible, because it has a non-zero overhead, so caching the result as soon as possible (e.g. you could do it in Start() instead of every time at the top of OnCollisionEnter2D), but this is more of a general "be careful" flag, as over-use can cause frame rate issues.
My question is, how do I access other elements of my structure such as health, calories, etc, inside my collision script?
you can't. but you can solve it like this:
in your CollisionScript, change the GameObject PrefabFood to your scriptable object FOODS food
then in this class you can access things like so:
food.preFabFood // is the prefab
food.health // is the health variable
it seams like you're quite new to coding and i'd suggest learning the basics before, because this is basic programming and isn't really unity or even c# related.

How to edit variables in another game object.(Unity C#) [duplicate]

This question already has answers here:
Accessing a variable from another script C# [duplicate]
(3 answers)
Closed 4 years ago.
Do keep in mind that I am not good at Unity.
I have a Game Object with a variable called hp. I have another Game Object with a trigger collider. When the trigger runs, I want it to edit the variable hp but I don't know how to edit variables from another game object.
Please may I have some help.
In Unity, the OnTriggerEnter(Collider other) function is called when a collision is triggered.
In argument of the function, you get a collider named other, which is a reference to the collider script your object collided with. As any script in unity, you can call other.gameObject to retrieve the colliding gameObject. From then, you can use the GetComponent function to find a script on the object.
In your case, lets say you have an object on which you put this script:
public class Player : MonoBehaviour {
public float hp;
}
You need to create another script that handles the collision. Put this on the object that collides with your player
public class Obstacle : MonoBehaviour
{
public float damages;
private void OnTriggerEnter(Collider other)
{
if(!other.gameObject.HasComponent<Player>())
return;
var player = other.gameObject.GetComponent<Player>();
player.hp -= damages;
}
}

Unity3D C# - Text UI

I have the following piece of code. I referenced the text component in the editor to no_lives. The gamemanager (singleton) is being instantiated a scene before. The debug.log() shows 5 in the console. But when I try to set the text I get that the reference is not set to an instance of the object. Why is that?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class level1_script : MonoBehaviour {
public Text no_lives;
// Use this for initialization
void Start () {
no_lives = GetComponent<Text>();
}
// Update is called once per frame
void Update () {
int lives_n = gamemanager.lives_f ();
Debug.Log (lives_n);
no_lives.text = lives_n + " x";
}
}
Are you certain that Start() was called before Update and that the GetComponent is actually setting a value to no_lives?
If not then code defensively. Also lives_n needs to be converted to a string lives_n.ToString() + " x" or use a format.
void Update () {
int lives_n = gamemanager.lives_f ();
Debug.Log (lives_n);
if(no_lives != null) {
no_lives.text = string.Format("{0} x", lives_n);
}
}
EDIT:
But when I try to set the text I get that the reference is not set to
an instance of the object.
That's because when you do GetComponent<Text>‌​(), it will look for the instance of Text component on the-same GameObject your level1_script script is attached to.
You have two choices:
1.Attach Text component that GameObject your level1_script script is atached to then your current code should work.
2.If you already have the Text component attached to another GameObject, let's say an Object called "MyText", use GameObject.Find to find "MyText" then perform GetComponent on it to get the Text component.
no_lives = GameObject.Find("MyText").GetComponent<Text>‌​()
Edit:
Well, both Text and script are attached to the same object
prntscr.com/f7p7vx
It's likely attached to multiple GameObject and the other GameObject does not have the Text script attached to it.
Select the level1_script script, go to Assets --> Find References in Scene then remove the duplicated script from other objects.
As the script logs '5' in the debug log, it seems to me that the variable lives_n is used correctly.
My guess is that the component "no_lives" isn't filled (that's what is often causing the "reference is not set to an instance of the object" error)
I suggest that you try to add the script to the UI Text object in your scene, this way the script finds the "Text" component on that object.
It's important to know the differences between objects and components, because they're both essential parts of unity. Objects are "things" in your scene, like cubes, cameras and stuff like that. Components on the other hand are part of object and define the properties of that object. For example: a camera object has a camera component to make it a camera and to make it actually viewable by the user.
The GetComponent<>() method searches for a (in your case) Text component on the object the script is attached to.
Hope this helps!
(oh and don't forget to remove the script from the other object you've placed it on, in case this works. Otherwise you'll still get errors)

Categories