Change Value Of UI Light Slider to Read At Specific Points Of Slider Value
Wow that was a bit of a mouthful for a question title, sorry but I could not think of a better way to word it. Anyways @Soraphis, Here is a new question based on the last updated script.
Is there a way to have the light UI slider only trigger the audio clips wen it hits a certain pint of the slider like in my attached image?
Is it possible to make it so that if the LDR sensor was deliberately played with i.e. someone waving their hand repeatedly over the sensor that I could trigger audio responses from a 3rd array of audio clips.
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 AudioClip DTMFtone02;
public AudioClip DTMFtone06;
public AudioClip DTMFtone08;
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 () {
//print("BytesToRead" +sp.BytesToRead);
message2 = sp.ReadLine();
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 (0, 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();
}
}
Answer by Soraphis · Dec 18, 2015 at 03:47 PM
as i mentioned in the other question:
float input = 1 - float.Parse (message) / 100f;
// set the slider to the value
float oldValue = slider.value; ////////////// -------- this is new
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 && oldValue <= 0.8f) ////////////// -------- this has changed
source.PlayOneShot (BrightnessAudioClips [Random.Range (0, BrightnessAudioClips.Length)]);
else if (slider.value < 0.2f && oldValue >= 0.2f) ////////////// -------- this has changed
source.PlayOneShot (DarknessAudioClips [Random.Range (0, DarknessAudioClips.Length)]);
should solve your first problem
problem #2
first, i'll quote myself from the other question:
(2)
(1)
keep track of the time, that has passed since the last message was send, and the average value change (delta). if the time gets to low and the average-delta to high, then you know there's someone manipulating (e.g. waving his hand in front of the sensor).But its a bit tricky to find the right values and needs much testing.
(2)
instead of playing an "annoyed audio clip" you could try to "fade" to the new value, someone waving his hands to fast would be "smoothed away" (dont know how to express myself, sry :/).Note: one can always manipulate your light sensor with his hands, you just can make it harder to do so.
ok the 2nd point is easier so adding two new variables:
const float sliderChangeVelocity = 0.5f;
private float desired sliderValue;
sliderChangeVelocity says how much the slider can change per second. So lets change a bit in the Update() method
string message = sp.ReadLine();
float oldValue = slider.value;
slider.value = Mathf.Min(Mathf.abs(desiredValue - slider.value), sliderChangeVelocity*Time.deltaTime)
* Mathf.Sign(desiredValue - slider.value);
if(message == "") return;
float input = 1 - float.Parse (message) / 100f;
desiredValue = input;
note: I'm writing this all out of my head in this text-field not in my IDE so there might be some errors.
Explaining the third line: first we want the absolute value of how much we want to change (desiredValue - slider.value) we compare it to the amount we are allowed to change in the current timestep (sliderChangeVelocity * Time.deltaTime) and keeping the lower value (Mathf.Min()). But now we have the absolute value which is always positive, but its possible that we want to decrement, so we multiply it by the Sign of (desiredValue - slider.value) which is 1 if its positive (0 counts as positive), and -1 if its negative.
(1)the first point is way more complicated and i cant say if the solution im my brain is correct.
i need to think more about it, it would be something like summing up the (absolute value of) changes of desired value in a new variable, divide it each time step with Time.deltaTime (which should be nearly always be less then 1, so the new variable will get greater), and if this variable gets to hight (maybe higher then 2, which would mean it went from pitch black to full bright in less then a half second) play your sound.
but i think there are some flaws in this ... i'll need to test this myself a bit ... maybe when i get some time for myself. but this would be the direction i'd go to solve this
@Soraphis, Awesome, yes that sure did the job, just that 2nd issue to work out and then this will be just the way I want it. :)
@Soraphis, O$$anonymous$$ sounds cool but how would I do that? I don't $$anonymous$$d playing around with values to experiment but what kind of new values and parameters would I need to set up in my script?
@Soraphis, Sounds like you are on the right track though, I did try playing around a little with what you had here but yup, I got some errors and I was not too sure if I should muck about with it until you had a chance to, But I think it sounds like it should work the way you are thinking. :)
as i wrote: you'll not find a perfect solution, and if you manage to code it yourself congratz! it would save me time :D especially because i dont know when i get the time to fiddle around with this. And im pretty sure coding it yourself will help you more then copy and pasting my code ;D.
if you need to find errors in your code, just post them here especially compiler/syntax errors can be found and solved really fast.
@Soraphis, I just noticed something else that is a little odd, $$anonymous$$or issue I'm sure but could be an issue.
If I start up my application and the room is dark it does not update the UI Slider right away, I find I have to shine a light on it first or turn on a room light in order for it to react right away.
I guess if the LDR sensor was pointing out of the windshield the varying light changes would cause the sensor to update the UI slider then but having it do it on start up would be ideal as I could maybe put a timed delay before triggering the audio clip.
a) change in your arduino code the initial value of lightSensorValue
from 0 to -50. (the arduino will send message just in the case the value changed by at least 10, if its initalized with 0 and it measures values ~0-9 it'll not send a message.
b) start the arduino after the unity programm. if your arduino starts before, it'll send the messages for the new light value, but theres nobody to receive them.
this can also be solved by sending messages at least every ~5 seconds. but i dont know much about program$$anonymous$$g an arduino, but im pretty sure the documentation can help you to this
@Soraphis, I added a Coroutine in start that makes a delay of 1.5f before the serial port to the Arduino is open that way my app has started plenty of time before the Arduino, I'm not sure it made much difference. I changed the Arduino code too ;) Anyways Take a look at how this is co$$anonymous$$g along see what you think.