.GetComponent Function Makes my Variable = 0 - c#

StripeNum is on a button and the colour function is set to the same colour button and using Debug.Log it shows stripe1 = 20. But in the second script Debug.Log stripe1.stripe1 = 0. Im just referencing the game object the script is on (the same gameobject is used as the object for the button) Image of The Console Showing Debug.Logs
using UnityEngine;
public class StripeNum : MonoBehaviour
{
public void black()
{
stripe1 = 0;
}
public void brown()
{
stripe1 = 10;
}
public void red()
{
stripe1 = 20;
Debug.Log(stripe1);
}
public void orange()
{
stripe1 = 30;
}
public void yellow()
{
stripe1 = 40;
}
public void green()
{
stripe1 = 50;
}
public void blue()
{
stripe1 = 60;
}
public void purple()
{
stripe1 = 70;
}
public void grey()
{
stripe1 = 80;
}
public void white()
{
stripe1 = 90;
}
public float stripe1;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class FinalCalc : MonoBehaviour
{
Scene c_scene;
float TwoStripesAdded;
float FinalR;
public Text FinalNum;
void Start(){
c_scene = SceneManager.GetActiveScene();
GameObject gameobject = GameObject.Find("GameObject");
StripeNum stripe1 = gameobject.GetComponent<StripeNum>();
Stripe2Num stripe2 = gameobject.GetComponent<Stripe2Num>();
Stripe3Num stripe3 = gameobject.GetComponent<Stripe3Num>();
Stripe4Num stripe4 = gameobject.GetComponent<Stripe4Num>();
if (c_scene.buildIndex == 6){
TwoStripesAdded = stripe1.stripe1 + stripe2.stripe1;
Debug.Log($"Added {stripe1.stripe1} and {stripe2.stripe1} and got {TwoStripesAdded}");
FinalR = TwoStripesAdded * stripe3.stripe1;
FinalNum.text = FinalR.ToString() + "Ω " + "±" + stripe4.stripe1 + "%";
}
}
}

Why not just name the class Stripe and have multiple instances of it? You can have empty child GameObjects and you can plop each stripe MonoBehaviour on the empty child. Then you can name the GameObject Stripe1, Stripe2, etc.
In Start() you can find those GameObjects, get the component attached to each, and cache those references so you don't have to keep re-getting them.
Aaaand actually in looking at your code I was assuming you were running this in Update, but you're running the check in Start. I don't know when or how you're setting colors, but if you're doing it in Play mode it's already too late, because this script won't check the colors.
You can't activate the methods until play mode (which is why I was asking you how you set it), so the only way to get a reading is if you set the value in Editor mode, but again that's not going to call a method.
Maybe what you're doing is setting the value in Editor mode that corresponds to a color?
Whatever the case, I think your data is not initialized when you check it, which is only once, before the first frame is drawn. If you're getting other debug messages then I need to know how you're getting. The Sum should be printed before anyone gets to set a value in Play mode.
Also a thought - you're checking the scene for some reason? If you set values and change scenes, all your objects are destroyed. The resistor calculator in one scene is a different instance than the one in scene 6 and will not have any values set on any stripes.

Related

Function not showing up in OnClick() for unity

I've been trying to get a function to return a number to change the text in a button. However, I can not use the functions I wrote with OnClick(). I won't show up.
Here is the script I've been working with.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class DiceRollerBehavior : MonoBehaviour
{
public int setRandom;
// Start is called before the first frame update
void Start()
{
setRandom = 0;
}
// Update is called once per frame
void Update()
{
}
public int roll()
{
setRandom = Random.Range(1, 10);
Debug.Log("Your new number is:" + setRandom.ToString());
return setRandom;
}
}
The OnClick() should put the roll function in this list but doesn't.
I just need to be able to trigger a function in this script using the OnClick() feature for unity.
To be able to set a callback here it must be public void, not public int.
Also, your code will not change any text. To be able to do this, you need to assign the text label you want to change to a class field. So, it will look like this:
public class DiceRollerBehavior : MonoBehaviour
{
[SerializeField]
private Text _text; // assign this field in the inspector
public int setRandom;
void Start()
{
setRandom = 0;
}
public void OnBtnClick()
{
int rollValue = roll();
_text.text = #"{rollValue}";
}
int roll()
{
setRandom = Random.Range(1, 10);
Debug.Log("Your new number is:" + setRandom.ToString());
return setRandom;
}
}

Unity Slider Value not cooperating with being set

I have two scripts that I'm currently having problem with. One is attached directly to a slider, which depending on its configuration will either send a slider value to the Options for music or sound.
In the Unity editor, I have it so whenever the options menu is brought up, run the OptionsLevel() script on both of the sliders to set them to the value saved in my options. I have no errors not being able to find the options, however the sliders do not move themselves to the value I am trying to set them too.
As far as I can tell, this should work.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;
public class SetVolume : MonoBehaviour
{
public AudioMixer Mixer;
private GameObject canvas;
[SerializeField] public enum Master { MusicVol, SoundVol }
public Master master;
public Slider slider;
public void OptionsLevel() //Call this when opening menu, changesss the slide layout to what already exits in the options
{
if (master.ToString() == "SoundVol")
{
Debug.Log("I am being called sound");
gameObject.GetComponent<Slider>().value = Options.Instance.GetSoundVolume(); //SETS VALUE of Slider, to value in Options
}
if (master.ToString() == "MusicVol")
{
Debug.Log("I am being called music");
slider.value = Options.Instance.GetMusicVolume();
}
}
public void SetLevel(float sliderValue)
{
Mixer.SetFloat(master.ToString(), Mathf.Log10(sliderValue) * 20); //Reads in the slider value and changes the mixer whenever the slider is changed
if (master.ToString() == "SoundVol") //if sound then set the sound volume in the settings
{
Options.Instance.SetSoundVolume(sliderValue);
}
if (master.ToString() == "MusicVol") //if the slider is configured for music it sends a copy of that value to the options
{
Options.Instance.SetMusicVolume(sliderValue);
}
}
}
my options script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Options : MonoBehaviour
{
public float musicFxVolume; // used to measure the value of sliders
public float soundFxVolume;
public float musicRealVolume;
public float soundRealVolume; //used to measure the actual volume level of the mixer
#region Singleton
public static Options Instance;
private void Awake()
{
SetUpSingleton();
Instance = this;
}
private void SetUpSingleton()
{
int numberOptions = FindObjectsOfType<Options>().Length;
if (numberOptions > 1)
{
Destroy(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
}
}
#endregion
public void SetSoundVolume(float volume) //when called this will make a copy of the volume
{
soundFxVolume = volume;
soundRealVolume = Mathf.Log10(volume) * 20; //and make a copy of the volume sent to the mixuer
Debug.Log("Setting the sound volume");
}
public void SetMusicVolume(float volume)
{
musicFxVolume = volume; //just store the value
musicRealVolume = Mathf.Log10(volume) * 20;
Debug.Log("Setting the music volume");
}
public float GetMusicVolume()
{
return musicFxVolume; //returns the value of the copied slider
}
public float GetSoundVolume()
{
return soundFxVolume;
}
}
I'm using Unity 2018.3.14f1, if that matters.

An Unity3D button appears to be null while trying to disable it

What I'm trying to do is disable the button when the time is up. But I get an error while I set the button to be disable: it appears to be null.
The following script (RightButton.cs) includes a function called DisableButton that is invoked by the main script (TappingEngine.cs).
The statement that hangs inside the DisableButton function is btn.interactable = false;.
/* RightButton.cs */
using UnityEngine;
using UnityEngine.UI;
public class RightButton : MonoBehaviour {
Button btn;
// Use this for initialization
void Start () {
Debug.Log("Right button ready.");
}
public void Tap()
{
Debug.Log("Tap right! tot: " + TappingEngine.te.nTaps);
TappingEngine.te.Tap(TappingEngine.tapType_t.right);
}
public void DisableButton()
{
btn = this.GetComponent<Button>();
btn.interactable = false;
}
}
The following code is a part of the main script (which is quite long). However, someone advised me to post the full version for clarity.
(Focus on the two functions Update () and DisableButtons().)
/* TappingEngine.cs */
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class TappingEngine : MonoBehaviour {
public static TappingEngine te;
public int nTaps = 0;
public int GlobalTotal;
public int RightTaps;
public int LeftTaps;
public string FirstTap;
public int LastTap;
public int MaxChain;
public int FastestTwoTaps;
public int FastestTwoChainedTaps;
public GlobalTotalTaps GlobalTotalTaps_script;
public TotalRightTaps RightTotalTaps_script;
public TotalLeftTaps LeftTotalTaps_script;
public FirstTap FirstTap_script;
public RightButton RightButton_script;
const float TimeSpan = 5F;
public float Chrono;
public bool ChronoStart = false;
public bool ChronoFinished = false;
public float ElapsedPercent = 0F;
public enum tapType_t { right, left };
// Use this for initialization
void Start () {
GlobalTotal = 0;
te = this;
GlobalTotalTaps_script = FindObjectOfType(typeof(GlobalTotalTaps)) as GlobalTotalTaps;
RightTotalTaps_script = FindObjectOfType(typeof(TotalRightTaps)) as TotalRightTaps;
LeftTotalTaps_script = FindObjectOfType(typeof(TotalLeftTaps)) as TotalLeftTaps;
FirstTap_script = FindObjectOfType(typeof(FirstTap)) as FirstTap;
RightButton_script = FindObjectOfType(typeof(RightButton)) as RightButton;
}
// Update is called once per frame
void Update () {
if(ChronoStart) {
ElapsedPercent = (Time.time - Chrono) * 100 / TimeSpan;
if(ElapsedPercent >= 100F) {
DisableButtons();
//SceneManager.LoadScene("Conclusion", LoadSceneMode.Single);
}
}
Debug.Log("Elapsed time: " + (Time.time - Chrono));
}
private void DisableButtons()
{
RightButton_script.DisableButton();
}
public void OnTap() {
Debug.Log("Tap!");
}
public void Tap(tapType_t tapType) {
Manage_GlobalTotalTaps();
if(GlobalTotal == 1) {
Manage_FirstTap(tapType);
ChronoStart = true;
Chrono = Time.time;
}
Manage_LeftRight(tapType);
}
private void Manage_FirstTap(tapType_t tapType)
{
FirstTap = tapType.ToString();
FirstTap_script.FastUpdate();
}
private void Manage_LeftRight(tapType_t tapType)
{
if (tapType.Equals(tapType_t.left))
{
LeftTaps++;
LeftTotalTaps_script.FastUpdate();
}
else
{
RightTaps++;
RightTotalTaps_script.FastUpdate();
}
}
public void Manage_GlobalTotalTaps() {
GlobalTotal++;
GlobalTotalTaps_script.FastUpdate();
}
}
Below are a couple of screenshots that I hope will be useful.
Until now I have not yet figured out where the problem is. Moreover, the script of the button is very similar to that of the various Text objects that represent the statistics (the list on the right side of the screen).
With Text objects it works, with the Button object not.
I asked the same question on Unity3D Forum and I got the solution here.
One the game object where I attached the RightButton.cs there is a variable on line 24 Button btn; that needs to be set to public, so public Button btn;.
This makes appearing a new entry in the Inspector of the Right Button object (see the image below) and so in Unity3D drag and drop the Right Button GameObject into Right Button (Script)'s proper field (Btn in this case).

Pass Value to One Script to Another in Unity3d

Currently, I'm trying to add / subtract value from one script to another. I wanted script one to add +125 health to script two but don't know how. There is no gameobject involved in this scenarios.
Script one is
using UnityEngine;
using System.Collections;
public class AddHealth : MonoBehaviour {
int health = 10;
public void ChokeAdd()
{
AddHealthNow();
}
public void AddHealthNow()
{
health += 125;
Debug.Log("Added +125 Health");
}
}
Script two is
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
namespace CompleteProject
{
public class DataManager : MonoBehaviour
{
public static int depth;
public Text BOPPressureText;
int health = 20;
void Awake ()
{
depth = 0 ;
}
void Update ()
{
BOPPressureText.text = depth + 7 * (health) + " psi ";
}
}
}
If you're trying to add health to your second script, declare your health field as public. So that you can access its value in your first script.
public int health;
But I wouldn't do stuff like that. Expose this field by a property like:
public int Health
{
get
{
return this.health;
}
set
{
this.health = value;
}
}
by default the health will be declared as
private int health;
Other scripts can't access private fields.
Also you need a reference to your second script. You can access this via:
public DataManager data;
You've to assign your second object into this field in your Unity Editor. Then
This way, you can access the field healthby calling data.health += 125 in your first script.
I don't know the specific thing in Unity, but I think you can also call your script by:
DataManager data = GetComponent<DataManager>();
data.health += 125;
Other method to get your other script is call it like that in your first script:
var secondScript = GameObject.FindObjectOfType(typeof(DataManager)) as DataManager;
secondScript.health += 125;

unity 5 how can I display stats of an class on a Character Creation menu?

Making a game in Unity 5 and I have the Main-Menu, and CharacterCreation-Menu. However in the CharacterCreation-Menu I want it to display the "Warrior" stats and "Mage" stats once I click that class in the menu. How can I do so?
I realize that I can add more Menus with each class stats placed onto the screen with the UI text but that wouldn't be that very fun, also that I can add a new canvas for each player on the CharacterCreationg_Menu but that would make Everything so hard to see and very messy.
I have a hunch that I should add the necessery information in the "public void Warrior" and "public void Mage" But I cannot figure it out.
Once I press a class in the CharacterCreation_Script:
CharacterCreation-Menu_Script:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class CharacterCreationScript : MonoBehaviour {
// Class Info
public Canvas classInfo;
// Class Buttons
public Button warrior;
public Button mage;
// Buttons
public Button createCharacter;
public Button goBack;
// Use this for initialization
void Start ()
{
classInfo = classInfo.GetComponent<Canvas>();
classInfo.enabled = false;
// Classes
warrior = warrior.GetComponent<Button>();
mage = mage.GetComponent<Button>();
// Buttons
createCharacter = createCharacter.GetComponent<Button>();
goBack = goBack.GetComponent<Button>();
}
// Classes
// Warrior
public void Warrior()
{
classInfo.enabled = true;
}
// Mage
public void Mage()
{
classInfo.enabled = true;
}
// Create Character Button
public void CreateCharacter()
{
Application.LoadLevel("NewGame");
}
// Go Back Button
public void GoBack()
{
Application.LoadLevel("MainMenu");
}
// Update is called once per frame
void Update ()
{
}
}
I get a text popping up on the screen "Class Info"
But it does not contain the information stored in the Player_Classes:
Warrior
using UnityEngine;
using System.Collections;
public class BaseWarriorClass : BaseCharacterClass
{
public BaseWarriorClass()
{
// Basic
CharacterClassName = "Warrior";
CharacterClassDescription = "Uses melee to crush enemies.";
//Gold = 100;
// Stats
Health = 100;
Mana = 100;
Stamina = 10;
Strength = 20;
Intelligence = 5;
Armour = 0;
Resistance = 0;
}
}
Mage
using UnityEngine;
using System.Collections;
public class BaseMageClass : BaseCharacterClass
{
public BaseMageClass()
{
// Basic
CharacterClassName = "Mage";
CharacterClassDescription = "Uses spells to vaporize enemies.";
//Gold = 100;
// Stats
Health = 100;
Mana = 100;
Stamina = 10;
Strength = 5;
Intelligence = 20;
Armour = 0;
Resistance = 0;
}
}
You might just have a general UI element (the View) that shows the stats/abilities/description of any character class (the Model).
public class CharacterDetailsView : MonoBehaviour
{
public Text healthText;
public Text manaText;
// ...
public void SetModel(BaseCharacterClass chr)
{
healthText.text = chr.Health.ToString();
manaText.text = chr.Mana.ToString();
// ...
}
}
In your CharacterCreationScript you would not hide and show specific Canvases for each class, but you would just create different types of characters and pass them on to your view:
public class CharacterCreationScript : MonoBehaviour
{
public CharacterDetailsView characterDetailsView;
private BaseCharacterClass createdCharacter;
// ...
void WarriorClicked()
{
createdCharacter = new BaseWarriorClass();
UpdateCharacterDetailsView();
}
void MageClicked()
{
createdCharacter = new BaseMageClass();
UpdateCharacterDetailsView();
}
void UpdateCharacterDetailsView()
{
characterDetailsView.SetModel(createdCharacter);
}
}
You also have to make sure that your scene is setup correctly:
Have a GameObject in your scene that represents the character details view area, and give it child Text ui elements matching those declared in the CharacterDetailsView class.
Add the CharacterDetailsView script to your new GameObject and assign the child Text elements to their respective fields.
Finally, you assign the GameObject to the characterDetailsView field in your CharacterCreationScript.
Even though there is still much room for improvement, this is much easier to maintain than having seperate UI elements.
You may want to read up on the Model-View-Control design pattern, which should be very helpful for any UI based game.

Categories