GetComponent returning 0 in Unity Game Engine - unity3d

I´m having a unity problem with getting a variable from another script. I´m working in c#.
In this case I´m getting the health of the player to the GUI script, but the variable just returns 0. I tried to understand by searching for similar problems but i could not figure it out. Thanks! /PixzleOne
How the health is set in the player script in the monobehavior part:
public int health = 100;
How I tried to get the health in the GUI script:
int playerHealth;
public GameObject player;
void Update () {
playerHealth = player.GetComponent<playerScript>().health;
print (playerHealth); //Only for me to see if it returns anything.
}

You probably have the value changed in the inspector for the object. Inspector values will override script-defined values.
An important thing to note - if you previously declared your public variable (also referred to as an inspector variable) without a default value like so:
public int myValue;
then update it with a value in the script:
public int myValue = 1;
the inspector will not pick up the change. You'll have to change it in the inspector yourself. I remember this getting me stuck at one point when I first started with Unity.
When in doubt, check the inspector.

Related

How to disable the Tracked Pose Driver in a Unity VR Application?

I need to write a VR application that disables HMD positional tracking for a specific situation and then reenable it again.
In the UI it is a simple as ticking and unticking the TrackedPoseDriver shown in the picture below.
How can I do that via Scripting?
I assume I need to use the enabled property of a game object. But I don't know how to grab a hold of this GameObject (or Component).
EDIT: In case this was clear this is GameObject/Component associated to the main camera.
Ok. So I was able to do It.
What I did is I search MonoBehaviour Based Components on the camera and then cast it to a MonoBehaviour once I found the right one. And then used the enabled property. Like this:
Component[] components = Camera.main.GetComponents(typeof(MonoBehaviour));
bool found = false;
foreach(Component component in components) {
string name = component.ToString();
MonoBehaviour mb = (MonoBehaviour) component;
if (name.Contains(TRACK_POSE_DRIVER_NAME)){
mbTrackingPose = mb;
found = true;
break;
}
}
The unique string that the toString() method provided was somethign like (I don't have it on hand) "Main Camera (Unity.XR.TrackedPoseDriver)". So I just made sure that the string had the "TrackedPoseDriver" and stored that as a MonoBehaviour.
I hope this helps someone else.

How do you fire off the Cinemachine Impulse source without using the Collision one?

How do properly call GenerateImpulse() to implement Cinemachine's camera ImpulseListener (camera shake) via the ImpulseSource? I can get it working if I put a CollisionImpuleSource on the player, but I don't want that. I want to use the Impulse Source and then with code, determine when to shake.
I'm looking at the documentation https://docs.unity3d.com/Packages/com.unity.cinemachine#2.3/manual/CinemachineImpulseSource.html but not seeing how to properly make the ImpulseSource fire off.
I set a private...
public CinemachineVirtualCamera vCamera;
private CinemachineImpulseSource _impulseSource;
I can call the generateImpulse...
_impulseSource.GenerateImpulse();
but I don't see how to get the component
private void Start(){
_impulseSource = vCamera.GetCinemachineComponent<CinemachineImpulseSource>();
}
I get an error..
The type
'Cinemachine.CinemachineImpulseSource'
must be convertible to
'Cinemachine.CinemachineComponentBase'
in order to use it as parameter 'T' in
the generic method 'T
Cinemachine.CinemachineVirtualCamera.GetCinemachineComponent()'
but if I change the private too..
private CinemachineComponentBase _impulseSource;
that doesn't help. Need some guidance on how this should be referenced.
Think of the CinemachineImpulseSource as a component on a custom GameObject.
Attach the CinemachineImpulseSource Script Component to a new gameobject. You could probably add it to the same GO where the script from your question is attached to, did not test this though.
Configure the impulse source component according to your needs and reference it. If its on the same GameObject, create a public field just as with your camera reference and assign it in the inspector or get it using GetComponent<CinemachineImpulseSource>(). Then you can call GenerateImpulse() on it.
public CinemachineVirtualCamera vCamera;
public CinemachineImpulseSource ImpulseSource; // Assign in inspector
...
ImpulseSource.GenerateImpulse();

Best practice to to access components using scripts in Unity?

I am new to Unity so go easy on me. :)
I added an game object with a text field component (via TextMeshProUGUI) to my heads up display in my scene. I want to use this to display various statistics on it for debugging purposes during game play.
I then created a script which I added as a component to the same game object that holds my text component. Is this the best practice? Not sure how else I would get the script to execute.
Once I had my script created, I needed to find the text component as well as some other components in my scene so I could display the debug information. Below you can see how I did it... it feels a little dirty to be searching the entire scene to find these things. Would love some insight on how long-time Unity programmers go about this!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PlayerDebugStatistics:MonoBehaviour {
TextMeshProUGUI playerDebugStatisticsText;
PlayerCharacterController playerCharacterController;
Health playerHealth;
private void Start() {
// First find the object in the scene named "PlayerDebugStatisticsText" and then get it's TextMeshProUGUI component
this.playerDebugStatisticsText = GameObject.Find("PlayerDebugStatisticsText").GetComponent<TextMeshProUGUI>();
// Get the player character controller
this.playerCharacterController = GameObject.FindObjectOfType<PlayerCharacterController>();
// Get the player health from the player character controller
this.playerHealth = playerCharacterController.GetComponent<Health>();
}
void Update() {
// Update the text every frame
this.playerDebugStatisticsText.SetText(string.Format("{0:N2}", this.playerHealth.currentHealth));
}
}
3 ways
Create an inspector reference to the other object and access it from your script - a public or private (with [SerializeField]) attribute in your script - and drag the component in like in this video: https://youtu.be/dMgQOP7kdxg?t=425
Use the singleton pattern: https://www.youtube.com/watch?v=5p2JlI7PV1w
Use dependency injection - https://github.com/modesttree/Zenject
Your way isn't terrible if you don't do it in the Update() loop, and cache your objects (like it appears you are doing), but if you need that performance in Start(), the above options can help.

Unity3D Text not changing after being set in Start()

I have a Canvas (World Space Render mode) with a Text and a Button component displayed in a tridimensional space (it's a VR app). The canvas instantiated at runtime using a prefab.
I get a reference to the Text object using:
_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent<Text>();
I want to update the text at run-time using:
void Update()
{
_codeTextLabel.text = _codeText;
}
where _codeText is just a variable I update based on specific events.
The problem is that the Text gets updated only the first time, but if I try to change the variable nothing happens. I have tried several combinations and also the method _codeTextLabel.SetAllDirty() but it doesn't work.
The only way to update the text is to re-instantiate the prefab.
Are you instantiating your prefab before setting the values. If you are storing the _codeTextLabel reference before instantiating then your reference will point to the prefab not the runtime object. I can't see the rest of your code, so I can't say for sure. (I would have asked as a comment, but as I'm new I don't have the reputation to do so)
edit: I did a test to try and recreate your problem. I made the following script and it appears to work as expected. CanvasPrefab is a worldspace canvas with a UnityEngine.UI.Text component attached. (The script is attached on an empty game object in the scene btw)
public class ChangeText : MonoBehaviour
{
public GameObject CanvasPrefab;
private GameObject runtimeCanvas;
public string runtimeText = "something";
private Text textRef;
// Start is called before the first frame update
void Start()
{
runtimeCanvas = GameObject.Instantiate(CanvasPrefab);
textRef = runtimeCanvas.GetComponentInChildren<Text>();
}
// Update is called once per frame
void Update()
{
textRef.text = runtimeText;
}
}
as long as you did something wrong, It works absolutely so I guess there are several cases
Failed to do "_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent();"
'_codeTextLabel' lost reference from 'GameObject.
Doesn't change runtimeText' change at all
Subscription of events failed I mean, your updating scripts doesn't get proper event to update that text.
Without codes, this is only thing I can guess for yours so please check above I hope there is case among above.

gameObject.name is returning the script name, not the gameobject name

I have a script, LevelCube, which is attached to a gameobject in my scene. When the object is clicked, it calls a function in this script called PickCube()
Right now, I'm just trying to get the position of this gameobject in my scene.
Here is my function:
public void PickCube ()
{
Debug.Log (gameObject.name);
}
Curiously, the output of this log just says "LevelCube", the name of the script. I thought gameObject referenced the GameObject the script is attached to. What's going on here?
If it's any use, here is a pick of the editor. You can see InvertedSphere is highlighted. This is the gameobject I'm trying to get the position of.
Thanks to #Draco18 I realized I was supplying a different object which also has the LevelCube script to the onclick method in my event trigger. So it was calling my function for that object rather than my InvertedSphere.
Try gameObject.transform.name.
What you see in hierarchy is the name of the transform. If you use gameObject.name, it casts it to Object.name and you get the name of your current object.