- Home /
The question is answered, right answer was accepted
Get UI Slider Value
I have a UI slider set to react to information from an Arduino. Is there a way to read in the value of the UI slider so that when the slider reaches a certain value I can then use that information in my script to trigger something?
UPDATE: I added the whole code so you can see what it is I may be messing up.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.IO.Ports;
using System.Threading;
public class Sending : MonoBehaviour {
//int sysHour = System.DateTime.Now.Hour;
//Random Clips
//public AudioClip[] darknessDetectedVoices;
//public AudioClip[] brightnessDetectedVoices;
public AudioClip[] BrightnessAudioClips;
public AudioClip[] DarknessAudioClips;
//DTMF Tones
public AudioClip DTMFtone01;
public AudioSource source;
//UI Text Reference
//public Text MessageCentreText;
//_isPlayingSound is true when a sound is currently playing - just as the name suggests.
private bool _isPlayingSound;
public GameObject LightSlider;
public Slider slider;
Slider lightSlider;
public static Sending sending;
//public static SerialPort sp = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
public static SerialPort sp = new SerialPort("/dev/cu.wchusbserial1420", 115200); //115200
public string message2;
//Button States
bool button01State = false;
void Awake () {
if (sending == null) {
DontDestroyOnLoad (gameObject);
sending = this;
} else if (sending != this) {
Destroy (gameObject);
}
}
float timePassed = 0.0f;
// Use this for initialization
void Start () {
OpenConnection();
lightSlider = GetComponent<Slider> ();
if(slider == null) slider = GetComponent<Slider>(); // search slider in this object if its not set in unity inspector
if(source == null) source = GetComponent<AudioSource>(); // search audiosource in this object if its not set in unity inspector
}
// Update is called once per frame
void Update () {
//timePassed+=Time.deltaTime;
//if(timePassed>=0.2f){
//print("BytesToRead" +sp.BytesToRead);
message2 = sp.ReadLine();
//print(message2);
// timePassed = 0.0f;
//}
/*if (message2!="") {
print("called");
lightMeUp(message2);
//MessageCentreText.text = "LIGHT VALUE CHANGED";
}*/
///////////////////
string message = sp.ReadLine(); //get the message...
if(message == "") return; //if its empty stop right here
// parse the input to a float and normalize it (range 0..1) (we could do this already in the Arduino)
// I dont know if a higher value means darker, if so add a "1 - " right after the "="
float input = /* 1 - */ float.Parse (message) / 100f;
// set the slider to the value
slider.value = input;
// after the slider is updated, we can check for the other things for example play sounds:
if (source.isPlaying) return; // if we are playing a sound stop here
// else check if we need to play a sound and do it
if (slider.value > 0.8f)
source.PlayOneShot (BrightnessAudioClips [Random.Range (0, BrightnessAudioClips.Length)]);
else if (slider.value < 0.2f)
source.PlayOneShot (DarknessAudioClips [Random.Range (DarknessAudioClips.Length)]);
//////////////////
}
public void OpenConnection()
{
if (sp != null)
{
if (sp.IsOpen)
{
sp.Close();
print("Closing port, because it was already open!");
}
else
{
sp.Open(); // opens the connection
sp.ReadTimeout = 16; // sets the timeout value before reporting error
print("Port Opened!");
// message = "Port Opened!";
}
}
else
{
if (sp.IsOpen)
{
print("Port is already open");
}
else
{
print("Port == null");
}
}
}
void OnApplicationQuit()
{
sp.Close();
}
//Movie Player Toggle
public static void sendYellow(){
sp.Write("y");
}
//Analyzer Toggle
public static void sendYellow2(){
sp.Write("A");
}
//Pod 7DLA Toggle
public static void sendYellow3(){
sp.Write("D");
}
//Pod PENG Toggle
public static void sendYellow4(){
sp.Write("P");
}
//Pod 6RM Toggle
public static void sendYellow5(){
sp.Write("6");
}
//Pod Laser Toggle
public static void sendYellow6(){
sp.Write("Z");
}
//Auto Phone Toggle
public static void sendGreen(){
sp.Write("g");
//sp.Write("\n");
}
//Oil Slick Toggle
public static void sendRed(){
sp.Write("r");
}
//Surveillance Mode Toggle
public static void sendBlue(){
sp.Write("b");
}
//Scanner Toggle
public static void sendRed2(){
sp.Write("1");
}
//Fog Lights Toggle
public static void sendGreen2(){
sp.Write("f");
}
//Head Lights Toggle
public static void sendGreen3(){
sp.Write("h");
}
//Hight Beams Toggle
public static void sendWhite(){
sp.Write("H");
}
//Rear Hatch Popper
public static void sendPulse1(){
sp.Write("p");
}
//Grappling Hook Launch
public static void sendPulse2(){
sp.Write("q");
}
//Auto Doors Right Pulse
public static void sendPulse3(){
sp.Write("R");
}
//Auto Doors Left Pulse
public static void sendPulse4(){
sp.Write("L");
}
//Startup and Shutdown Pulse
public static void sendPulse5(){
sp.Write("S");
}
/*void lightMeUp(string message){
//If there is a sound currently playing, return immediately so we don't play another sound simultaneously.
//if(_isPlayingSound) is shorthand for if(_isPlayingSound == true), in case you where wondering.
if (_isPlayingSound)
return;
print (message);
float fl = float.Parse (message) / 100.0f;
fl = 1.0f - fl;
LightSlider.GetComponent<Slider>().value = fl;
//Do something Here if Light Value / UI Slide on the LDR is near Darkness
if (LightSlider.GetComponent<Slider> ().value <= 0.1) {
Debug.Log ("DARKNESS DETECTED");
//Pick a random sound.
AudioClip randomClip = darknessDetectedVoices [UnityEngine.Random.Range (0, darknessDetectedVoices.Length)];
//Play that sound.
GetComponent<AudioSource> ().PlayOneShot (randomClip);
//Flag that we are currently playing a sound.
_isPlayingSound = true;
//Start a coroutine that will set the flag to false once the sound stops playing, so we can start playing a new sound.
StartCoroutine (RunResetIsPlayingSoundFlag (randomClip.length));
if (_isPlayingSound)
return;
}
//Do Something Here if the Light Value on the LDR is near Daylight brightness
else if (LightSlider.GetComponent<Slider> ().value >= 0.6) {
Debug.Log ("NEAR DAYLIGHT DETECTED");
//Pick a random sound.
AudioClip randomClip2 = brightnessDetectedVoices [UnityEngine.Random.Range (0, brightnessDetectedVoices.Length)];
//Play that sound.
GetComponent<AudioSource> ().PlayOneShot (randomClip2);
//Flag that we are currently playing a sound.
_isPlayingSound = true;
//Start a coroutine that will set the flag to false once the sound stops playing, so we can start playing a new sound.
StartCoroutine (RunResetIsPlayingSoundFlag (randomClip2.length));
if (_isPlayingSound)
return;
}
//BONUS if Possible Do something if the LDR is deliberately played with like waving hand over or blocking and un blocking the sensor.
}
private IEnumerator RunResetIsPlayingSoundFlag(float soundDuration)
{
//Wait until the sound finishes playing.
yield return new WaitForSeconds(soundDuration);
//yield return new WaitForSeconds(10.0f);
//Disable the _isPlayingSound flag, so we can play a new sound since this one is over.
_isPlayingSound = false;
} */
//Comlink Clock Close Button
public void GoMainScreen(){
StartCoroutine(LoadT3());
GetComponent<AudioSource>().PlayOneShot(DTMFtone01);
}
IEnumerator LoadT3(){
yield return new WaitForSeconds(0.0f); // wait time
}
}
Answer by Soraphis · Dec 17, 2015 at 08:01 PM
Ok, to provide an acceptable answer to the Question "How do you map an Arduino-measured light intensity to a unity slider" (or something like that)
Step 1: Arduino
Based on this Arduino Tutorial: Arduino: Read Analog Voltage and this video tutorial
we write a script looking like this:
int lightSensorPin = 0;
int lightSensorValue = 0;
void loop(){
// read the new light value (in range 0..1023):
int sensorValue = analogRead(lightSensorPin);
// if the value changed by 10
if(lightSensorValue - sensorValue > 10 || sensorValue - lightSensorValue > 10){
lightSensorValue = sensorValue; // save the new value
float p = lightSensorValue * (100.0 / 1023.0); // make the value to range 0..100
// the Parentheses may be for compiler optimization idk
Serial.println(p); // send it to unity
}
}
One may want to check out https://www.arduino.cc/en/Tutorial/Calibration to adjust the script
Step 2: Unity
We need a Component with the following script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class SliderTest : MonoBehaviour {
public Slider slider;
public AudioSource source;
public AudioClip[] BrightnessAudioClips;
public AudioClip[] DarknessAudioClips;
public static SerialPort sp = new SerialPort("COM4", 9600);
void Start () {
if(slider == null) slider = GetComponent<Slider>(); // search slider in this object if its not set in unity inspector
if(source == null) source = GetComponent<AudioSource>(); // search audiosource in this object if its not set in unity inspector
}
void Update () {
string message = sp.ReadLine(); // get the message...
if(message == "") return; // if its empty stop right here
// parse the input to a float value and normalize it (range 0..1) (we could do this already in the arduino)
// i dont know if a higher value means darker, if so add a "1 - " right after the "="
float input = /* 1 - */ float.Parse(message) / 100f;
// set the slider to the value
slider.value = input;
// after the slider is updated, we can check for other things for example play sounds:
if(source.isPlaying) return; // if we are already playing a sound stop here
// else check if we need to play a sound and do it
if(slider.value > 0.8f) source.PlayOneShot(BrightnessAudioClips[Random.Range(0, BrightnessAudioClips.Length)]);
else if(slider.value < 0.2f) source.PlayOneShot(DarknessAudioClips[Random.Range(0, DarknessAudioClips.Length)]);
}
}
Well i really hope your problem is solved by this
@Soraphis, I tried typing all of this into the existing script I had and I get this error:
Assets/Scripts/Sending.cs(97,72): error CS1501: No overload for method Range' takes
1' arguments
I'll update my original question with the complete code maybe you'll see what I' messing up. I have a bunch of my previous stuff committed out in case I need to switch it back. ;)
hows your script 97 lines long and $$anonymous$$e is 41?
i use Range in two lines and both times its: Random.Range(0, DarknessAudioClips.Length)
which are 2 parameters. ( the unity code compiles for me, the arduino i cant say)
as i wrote in my comments, just uncomment the "-1" line 28 (my script)
Answer by Tom01098 · Dec 16, 2015 at 08:03 PM
Can't you just do an if statement based on lightSlider.value?
@$$anonymous$$10098 I thought it was an if statement but I can't seem to find examples of how that done.
if(lightSlider.GetComponent<Slider>().value > 0.5)
(for 50%) or in your case if(fl > 0.5)
because you set them to the same value
Thanks @Soraphis, I tried putting a Debug.Log in there and it does not appear to be reaching that part of the script?
void light$$anonymous$$eUp(string message){
//If there is a sound currently playing, return immediately so we don't play another sound simultaneously.
//if(_isPlayingSound) is shorthand for if(_isPlayingSound == true), in case you where wondering.
if (_isPlayingSound)
return;
print (message);
float fl = float.Parse (message) / 100.0f;
fl = 1.0f - fl;
LightSlider.GetComponent<Slider>().value = fl;
//Do something Here if Light Value / UI Slide on the LDR is near Darkness
if (LightSlider.GetComponent<Slider> ().value > 0.5) {
Debug.Log ("I HIT 0.5!");
}
//Do Something Here if the Light Value on the LDR is near Daylight brightness
//BONUS if Possible Do something if the LDR is deliberately played with like waving hand over or blocking and un blocking the sensor.
//Pick a random sound.
AudioClip randomClip = voices [UnityEngine.Random.Range (0, voices.Length)];
//Play that sound.
GetComponent<AudioSource> ().PlayOneShot (randomClip);
//Flag that we are currently playing a sound.
_isPlayingSound = true;
//Start a coroutine that will set the flag to false once the sound stops playing, so we can start playing a new sound.
StartCoroutine (RunResetIsPlayingSoundFlag (randomClip.length));
}
private IEnumerator RunResetIsPlayingSoundFlag(float soundDuration)
{
//Wait until the sound finishes playing.
yield return new WaitForSeconds(soundDuration);
//Disable the _isPlayingSound flag, so we can play a new sound since this one is over.
_isPlayingSound = false;
}
Answer by seth_slax · Dec 17, 2015 at 03:54 AM
In response to the above suggestions, are your Slider's min and max set to 0 and 1? Do you have "Whole Numbers" toggled on the Slider? If so, you'll never get a value of 0.5. If your values are set differently than 0 and 1 and you still want to check to see if it's at 50%, just use a Lerp, like this:
if (LightSlider.GetComponent ().value >= Mathf.Lerp(LightSlider.GetComponent().minValue, LightSlider.GetComponent().maxValue, 0.5))
Also, if you're operating on the Slider component often, it'd be better to store it as a variable somewhere at the beginning to save CPU. GetComponent can be a heavy operation if used too often, and it'll reduce the amount of code, to something more like this:
Slider mySlider = LightSlider.GetComponent();
if mySlider.value >= Mathf.Lerp(mySlider.minValue, mySlider.maxValue, 0.5))
@seth_slax, Thanks. I do have the slider values set at $$anonymous$$ & max set to 0 & 1 and I don't have it set to whole number, that is unchecked. Basically I'm trying to get the LDR on the Arduino to be able to play a audio clip from a couple of random arrays depending on if it's near dark or near light. Can't seem to fine tune it just right though. I'll try that Lerp stuff and see if it helps :)
If so, you'll never get a value of 0.5. If your values are set differently than 0 and 1
but this does not matter, because of the comparison for "> 0.5" even if its 1 this will become true
@Soraphis, I think I get what you're saying, What happens is that if I take a bright LED flashlight and lower that slowly over the LDR sensor from dark to light I do seem to get my two voice responses but the slider I'm using in place of the world light what happens with that is that even in a normally lighted room I would expect the UI slider to show a mid range sort of value but it just goes right to the lowest end of the slider value. I'm basically trying to do follow this but make some modifications like the ones you see in my somewhat badly put together script, lol how can you tell I'm not much of a coder ;) Unity Arduino LDR Sensor Video Tutorial Link
Well, its kinda weird. is this script the only place where the slider value is touched?
can you verify with the inspector that the slider value does not change? (to be sure its not just a visual thing)
I've just made a dummy Scene, made with nothing but an UI slider and attached this script to the slider:
public Slider slider;
void Start () {
if(slider == null) slider = GetComponent<Slider>(); // search slider in this objects components if its not set in unity inspector
}
void Update () {
//this would be the value received from the arduino after Float.Parse(message);
float someInputValue = Random.Range(0, 100);
//normalize the value (so its in range 0..1)
someInputValue /= 100f;
// set the slider to the specific value
slider.value = someInputValue;
if(slider.value > 0.8f) Debug.Log("> 0.8");
else if(slider.value < 0.3f) Debug.Log("< 0.3");
}
well i use random numbers as input so the slider is jumping up and down, but it works as i expected it. i found some not-nice things in your script but nothing to be worried about