I dont get why unity gives a compile error here - c#

I'm trying to change the text of a TMPro text box, but unity reports at 20,79 I need a }. I put in the bracket and 11 errors pop up. debug pls? I don't know much c# myself so I can't do it myself. pls, help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class tetxmeshpro : MonoBehaviour
{ int previoushealth = 100;
private TextMeshProUGUI textMesH;
// Start is called before the first frame update
void Start()
{
var Player; GameObject;
textMesH = GetComponent<TextMeshProGUI> ();
}
// Update is called once per frame
void Update()
{
if ((Player.GetComponent(playerScript).Health)) not == previoushealth;)
{
previoushealth = Player.GetComponent(playerScript).Health;
textMesH = previoushealth;
}
}
}

What exactly is
var Player; GameObject;
supposed to do? ;)
It seems you rather mean
GameObject Player;
Either way the Player is not a field so later in Update you don't have access to it either. You probably rather wanted a
[SerializeField] private GameObject Player;
on class level so you can reference your object in it. Or even better give it the correct type right away:
[SerializeField] private playerscript player;
This way you don't need the GetComponent later.
What is this
if ((Player.GetComponent(playerScript).Health)) not == previoushealth;)
This is c# not some Shell/Dos script -> use != and not not ==. Also if conditions don't end with a ; and there is a ) too much. And also GetComponent either is generic, then it is GetComponent<T>() or you pass in a type but then you have to cast it like ((T)GetComponent(typeof(T))).
If something it should rather simply be
if (Player.GetComponent<playerScript>().Health != previoushealth)
Your class should rather look like
public class tetxmeshpro : MonoBehaviour
{
int previoushealth = 100;
// Link these via the Inspector using drag&drop
[SerializeField] private TextMeshProUGUI _textMesH;
[SerializeField] private playerscript _player;
// Start is called before the first frame update
private void Start()
{
if(!_textMesH) _textMesH = GetComponent<TextMeshProGUI>();
}
private void Update()
{
if (_player.Health != previoushealth)
{
previoushealth = _player.Health;
textMesH = previoushealth;
}
}
}
Though, note that naming your class textmeshpro a) might lead to confusions with the existing TextMeshPro and also doesn't at all reflect the purpose of that class. I would suggest something like e.g. HealthDisplay or anything similar meaningful.

Related

I can't assign script from another object. Is there smth wrong?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeteorRangeController : MonoBehaviour
{
[SerializeField] PlayerController PlayerController; // It has to be script
[SerializeField] GameObject Player; // no problem with assigning this
[SerializeField] Transform playerTransform;
[SerializeField] Vector3 playerPos;
[SerializeField] bool canGo;
[SerializeField] GameObject meteor;
// Start is called before the first frame update
void Start()
{
playerTransform = Player.GetComponent<Transform>();
PlayerController= Player.GetComponent<PlayerController>(); //*The Problem Is Here*
//PlayerController Cannot Be Assigned
}
// Update is called once per frame
void Update()
{
print(PlayerController.IdleTime); //to test it I printed
playerPos = Player.transform.position;
//I tried to take idle time from Player controller here.
if (PlayerController.IdleTime > 2)
{
canGo = true;
}
else
{
canGo = false;
}
if (canGo == true)
{
transform.position = new Vector3(playerPos.x, playerPos.y, playerPos.z);
gameObject.SetActive(true);
Invoke("SetActiveFalse",2f);
}
}
void SetActiveFalse()
{
gameObject.SetActive(false);
meteor.SetActive(true);
Invoke("MeteorSetActiveFalse", 2f);
}
void MeteorSetActiveFalse()
{
meteor.SetActive(false);
}
}
I can't assign it.
I researched it but I couldn't find anything different.
I know it's a very easy question, also I assigned game object player, in it there is a script named PlayerController, and there is a variable named idle time please help me
Okay, that's my first try to answer on topic on Stack Overflow, so hope you will be patient to my mistakes.
Can you say, are you sure, that Player object has a PlayerController script on him?
I think you must use
var isControlSetted = Player.TryGetComponent<PlayerController>(out PlayerController);
instead of:
PlayerController= Player.GetComponent<PlayerController>();
Why? So, that can answer on question №1 and after it you can control the logic of working with it when (use AddComponent for example or throw an exception)
3. Okay, even that can't fix your problem if PlayerController setted on inheritor or ancestor of Player gameobject in gameobject hierarchy
I hope I helped you
Edited:
Okay, I was asked to make answer some clearly, so...
First of all, can you show PlayerController script, pls?
Secondary, why I'm asking to use TryGetComponent instead of GetComponent bcs as I commented below getting null value is not a good practice, but if you want - use it.
Let's look on script more closly
I refactored this pls look
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeteorRangeController
: MonoBehaviour
{
[SerializeField] PlayerController playerController;
[SerializeField] GameObject playerObject;
[SerializeField] Transform playerTransform;
// [SerializeField] Vector3 playerPos; we don't need this
// [SerializeField] bool canGo; and this
[SerializeField] GameObject meteorObject;
/// <summary>
/// Method that called once we use this or Awake for init our fields/props
/// </summary>
void Start()
{
playerTransform = playerObject.GetComponent<Transform>(); // there no need to use TryGetComponent bcs Transform is req. for every GO/MB
playerController= playerObject.GetComponent<PlayerController>(); // there you could use TryGC, but if you use RequireComponentAttribute that's ok
}
/// <summary>
/// Method that's calls every frame
/// </summary>
void Update()
{
if (playerController.IdleTime <= 2)
return;
transform.position = playerTransform.position;// i really can't understand what hepenning after this so i stop
gameObject.SetActive(true);
Invoke(nameof(SetActiveFalse),2f);
}
void SetActiveFalse()
{
gameObject.SetActive(false);
meteorObject.SetActive(true);
Invoke(nameof(MeteorSetActiveFalse), 2f);
}
void MeteorSetActiveFalse()
{
meteorObject.SetActive(false);
}
}
So, afterwards GO.GetComponent can return null only if the requested GO did not have a Monobehaviour script.
You can check similar question there https://forum.unity.com/threads/getcomponent-doesnt-works.516839/

How can I access a scene from another scenes script

I have a homework assigned and I need the make a sound and music volume thing and I want it to be used in other scripts too.
What I mean is :
enter image description here
So when I drag the slider value to 0.2 for example I want the audio source on the other scene to have volume 0.2, but I have no idea how thats made.
Thanks.
(I only have a plan but no code)
Also does anyone know why does it take forever to load when you save a script and go to unity:
enter image description here
A great way to do this is to use static variables that are actually defined for the class And can hold variables between scenes.
public class AudioManager
{
public static float MusicVolume = 1f;
public static float SoundVolume = .5f;
public void SetVolume(float value) => MusicVolume = value;
}
To call them, you just need to write the full name of the class before the variable name.
public class Player : MonoBehaviour
{
public AudioClip AudioClip;
public void Shot()
{
AudioSource.PlayClipAtPoint(AudioClip, transform.position, AudioManager.SoundVolume);
}
}
Remember that these are class variables will set in all instances of the same class. Also if you want your variables to be loaded after re-running the game. I suggest using PlayerPrefs for saving them.
To do this you would write a singleton script AudioManager that is set to DontDestroyOnLoad
It's just a script holding your AudioSources and that doesn't get destroy when you switch scenes.
Something like this
public class AudioManager : MonoBehaviour
{
private static AudioManager instance;
[Header("AudioSources")]
[SerializeField] private AudioSource musicSource;
[SerializeField] private AudioSource soundSource;
private void Awake()
{
// If you have AudioManager in every scene, you want to only keep the main one (the first one)
if (instance != null && instance != this)
{
Destroy(gameObject);
}
else
{
instance = this;
DontDestroyOnLoad(this); // This line will tell Unity to keep this gameobject when switching scenes
}
}
}
Then you can alter your audio sources as you wish, they won't get destroy after switching scene.
Okay Its nice that I have a lot of things to do but okay the script that you guys sent me, so if I put it on the audio Gameobject and I still don't get how I can change parameters from 1 scene to other (I'm a beginner and I'm 13 years old so I might not get what audio ATM's are but yes.)
For short I need this:
Scene1.findgameobject.name = blah blah = audiogameobject in menu

Unity: Even when the "player" game object gets destroyed, the text doesn't appear

I've been using Unity to create a simple 2D game but the problem is that even when the game object "player" gets destroyed, the gameobject "isDead" (text) doesn't appear.
This is my script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class youDied_Text : MonoBehaviour
{
private Transform player;
private Text isDead;
// public static bool isDead;
// Start is called before the first frame update
private void Start() {
isDead = GetComponent<Text>();
}
void checkForDeath()
{
if (player==false)
{
isDead.gameObject.SetActive(true);
}
else
{
isDead.gameObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
player = GameObject.FindWithTag("Player").transform;
checkForDeath();
}
}
This script is attached in the text which I need to display in UI element.
As was noted currently you would get a NullReferenceException which is definitely not what you want.
There is absolutely no need / redundancy going through Transform at all actually. Simply store the GameObject reference instead
You are currently setting the object to inactive which has the Text attached ... which is the same object your component is attached to as well!
=> As soon as you end up in the second case once you set it to inactive => from now on Update is never called anymore!
In general as it sounds like this should only happen once anyway I would use a more event driven approach and have a component on your player like e.g.
public class Player : MonoBehaviour
{
public UnityEvent onDied;
private void OnDestroy ()
{
onDied.Invoke();
}
}
And then simply attach a listener/callback to that event once without poll checking states. You can do this either via the Inspector directly (just like in e.g. Button.onClick) or via code like e.g.
public class youDied_Text : MonoBehaviour
{
// Already reference things via the Inspector if possible!
[SerializeField] private GameObject player;
[SerializeField] private Text isDead;
private void Awake()
{
if(!isDead) isDead = GetComponent<Text>();
isDead.gameObject.SetActive(false);
// If you want to rather set it via the Inspector remove all the rest here
//if(!player) player = GameObject.FindWithTag("Player"). GetComponent<Player>();
// or even simpler
if(!player) player = FindObjectOfType<Player>();
player.onDied.AddListener(OnPlayerDied);
}
// If you want to rather set it via the Inspector make this public
private void OnPlayerDied()
{
isDead.gameObject.SetActive(true);
}
}

Unity can't acess prefab's script's variable

I am working on a 3D game on Unity but recently a problem occurred. I can't access a variable from another prefab's script. I tried it before when the object which has to be accessed wasn't a prefab and it worked correctly.
This is the script which tries to access the "slashtime" variable, but when I run it gives back 0 though in the other script the variable is changing continuously.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collision : MonoBehaviour
{
public GameObject sword;
public float slashtime;
private void Update()
{
slashtime=sword.GetComponent<movement>().slashtime;
}
private void OnTriggerEnter(Collider collider)
{
if (collider.tag == "sword" && slashtime+1f > Time.time)
{
Destroy(gameObject);
}
}
}
You can use this. It is also working.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class collision : MonoBehaviour
{
public GameObject sword;
public float slashtime;
private void OnTriggerEnter(Collider collider)
{
sword = collider.gameObject;
slashtime=sword.GetComponent<movement>().slashtime;
if (collider.tag == "sword" && slashtime+1f > Time.time)
{
Destroy(gameObject);
}
}
}
Reason for your code is not working because when you write some code in update then it calls every frame. so when your object is destroyed, update call that code and it shown error.
Reworking your code a bit, with explanations below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class collision : MonoBehaviour
{
[SerializeField]
private GameObject _sword;
private float _slashTime;
private void Start()
{
_slashTime = GameObject.Find("Movement").GetComponent<Movement>().GetSlashTime();
}
private void OnTriggerEnter(Collider collider)
{
if (collider.CompareTag("sword") && _slashTime + 1f > Time.time)
{
Destroy(gameObject); // What is gameObject in this context? the _sword? something else?
}
}
}
Use private properties. Why? Because it increases modularity and protects the object(s) you're working with from accidentally having their values overwritten.
In conjunction to this, use public methods to obtain/change the values in other objects. Public methods are your API.
It's convention to begin the names of private properties with an underscore.
Like I said in my comment above, you first need to Find() your desired object before you can attempt to GetComponent<T>().
Like others have said, attempting to GetComponent<T>() in Update() is computationally expensive. It's better to get that component at Start() and then talk to it as necessary (in this case, during collision).
CompareTag() is the more modern/accepted way to check a tag.
EDIT:
[SerializeField] will keep the property private while also making it available to the Unity editor. It's good for debugging and linking objects.

Editing variables with GetComponent C#

I am trying to get a conveyor belt to reverse its direction when the player presses a button.
Here's the code for the conveyor belt
using UnityEngine;
using System.Collections;
public class Conveyor : MonoBehaviour {
public float speed = 1.0f;
void OnTriggerStay(Collider col)
{
col.transform.position += transform.forward * speed * Time.deltaTime;
}
}
And the code for the button
public class PushButton : MonoBehaviour
{
public GameObject Button;
private Conveyor conveyor;
void Awake ()
{
conveyor = GetComponent<Conveyor>();
}
void OnTriggerStay(Collider entity)
{
if (entity.tag == "Player")
{
if (Input.GetKeyUp(KeyCode.E))
{
conveyor.speed = conveyor.speed * -1;
}
}
}
}
I'm getting an error saying "Object Reference not set to the instance of an object PushButton.OnTriggerStay (Unity Engine.Collider entity) (at Assests/PushButton.cs21)
I'm still not very familiar with using getComponent so I'm not sure how to fix this. Any help would be appreciated.
GetComponent will need a reference to an initialized object and a component or class that object has assigned. For what you are wanting, you will want to find a game object in the scene. Because you are already specifying that your GameObject has a Conveyor class assigned to it, find your GameObject and then specify the Conveyor component.
void Awake ()
{
conveyor = GameObject.FindWithTag("Conveyor").GetComponent<Conveyor>();
}
This should do the trick pending you have tagged your Conveyor game object with a 'Conveyor' tag.
However, there is an even easier way to quickly "grab" something like this. Be careful though!
void Awake()
{
conveyor = Object.FindObjectOfType<Conveyor>();
// ONLY DO THAT IF THERE IS ONLY >>ONE<< OF THE THING!
}
Here's a little essay on that. http://answers.unity3d.com/answers/46285/view.html
You often do that for example to find "boss" objects .. scene managers and the like.
Don't forget though, you can always just use a public variable, and drag inteh Inspector - that's always a sound idea for beginners working with Unity.

Categories

Resources