#onValueChanged

1 messages Β· Page 1 of 1 (latest)

balmy ferry
#
timeSlider.onValueChanged.AddListener(_ =>
{
    if (!changingTime) StartCoroutine(ChangeTime());

    IEnumerator ChangeTime()
    {
        changingTime = true;

        yield return new WaitUntil(() => !Input.GetMouseButton(0));

        if (spawnManager.isPlaying) audioSource.time = timeSlider.value;

        changingTime = false;
    }
});

How to make timeSlider.onValueChanged do to different things when changing the value in the script and in the scene?

timeSlider.value += secondsRemote.right;
eager dome
#

I would think you could

    if (Input.GetMouseButton(0) && !changingTime) StartCoroutine(ChangeTime());

perhaps... but it is a shame that it'd be so tightly bound to input

balmy ferry
#

in update I change timeSlider's value and it's waiting till the left mouse button is held. Every time it's held the audio is changed a bit

eager dome
#

oh I see

balmy ferry
#

so different methods should be called

eager dome
#

I keep going back to the IPointer* and IDrag* interfaces... short of that I'm at a bit of a loss O.o

balmy ferry
#

look

#
timeSlider.onValueChanged.AddListener(_ =>
{
    if (smth)
    {
        // called by the player

        // our previous discussion (change Audio with delay)
        if (!changingTime) StartCoroutine(ChangeTime());

        IEnumerator ChangeTime()
        {
            changingTime = true;

            yield return new WaitUntil(() => !Input.GetMouseButton(0));

            if (spawnManager.isPlaying) audioSource.time = timeSlider.value;

            changingTime = false;
        }
    }
    else
    {
        // called by the script

        // just change the time
        audioSource.time = timeSlider.value;
        return;
    }
});
eager dome
#

Just to make sure I'm understanding the problem correctly, this all because timeSlider.value += secondsRemote.right; is triggering the onValueChanged event?

balmy ferry
#

should I send a video to understand what the problem is?

eager dome
#

I think it makes sense 😁

I didn't realize that Slider.value was a property/would trigger the change event. That's rather pesky

#

What's really obnoxious is that Slider.Set() has a boolean argument to specify whether or not to invoke the event - but it's a protected method

balmy ferry
#

it changes when I am holding the left button

balmy ferry
#

ok, I do think the only way to do it is to use : IPointerDownHandler, IPointerUpHandler

eager dome
#

I think there may be one other way - but it's still not ideal. Extending Slider you can get access to the Set method, so you can expose a property that won't trigger the event:

public class MySlider : Slider
{
    public float rawValue
    {
        get { return value; }
        set { Set(value, false); }
    }
}

But I feel like it's kind of worse than the IPointer interfaces and such, unless you wanted to package up the whole AudioSource/Slider relationship into a new type of slider

balmy ferry
eager dome
#

So instead of using a Slider component on your UI object, you'd use a MySlider instead. It should function just like the normal slider since it inherits from it, but now you could

timeSlider.rawValue += secondsRemote.right;

instead of

timeSlider.value += secondsRemote.right;

and it wouldn't trigger the onValueChanged event.

It would be a little cumbersome though, because you'd have to set up a MySlider manually - no nice context menu to create the game object in the hierarchy with all of it's child objects and default values and such.

#

I think it would make more sense to extend the class if you wanted to create a complete TimeSlider class which would contain most of the behavior for tying a slider and an audiosource together, but that would be a whole other twist on the project πŸ˜…

balmy ferry
#

we actually change the value there

eager dome
# balmy ferry still, are you sure it won't trigger the `onValueChanged` event?

I haven't checked the decompiled sources for slider or anything, or tested this (I totally can/will test though), but that's what the docs say https://docs.unity3d.com/2018.2/Documentation/ScriptReference/UI.Slider.Set.html

I also found an old forum thread with a bunch of people requesting a change so they could do just what you're doing, and a Unity rep mentioning that the functionality exists internally, but isn't exposed - I assume the Unity rep was talking about the protected Set() https://forum.unity.com/threads/change-the-value-of-a-toggle-without-triggering-onvaluechanged.275056/

balmy ferry
#

but the new class should be created?

#

cause that's protected

eager dome
#

yeah, sadly :(

#

I don't know why they wouldn't just make it public - it seems like a reasonable enough thing to expose

balmy ferry
#

I even have a folder for Helper scripts

#

@eager dome maybe you know the better way to call that slider class?

#

like SliderExtension ?

eager dome
#

I struggled with that... TimeSlider doesn't really make sense, because it doesn't deal with the audio source or anything... Yeah I dunno πŸ˜…

SliderExtension - sure. SliderRaw?

#

SliderWithPropertyWhichWontTriggerChangedEvent

#

it's a tricky one

#

even valueRaw is a weird name

balmy ferry
#

@eager dome now I do have one little problem

#

how to I set it in the Inspector?

[SerializeField] private SliderExtension timeSlider;
eager dome
#

I would think that should be fine? And same as you did with Slider - drag the GO with the SliderExtension component into the field?

balmy ferry
#

TimeSlider should have SliderExtension script?

#

oh, yeah

#

i have done it

eager dome
#

Yeah - it's a whole new component. Sadly it can't just be an extension method thingy - apparently extensions can't add properties, and they can't access protected methods, which sort of bummed me out

balmy ferry
#

but the Slider component should have been deleted

eager dome
#

On the GO? yeah - this will replace the Slider component

balmy ferry
#

there are some problems with setting the slider's components though

eager dome
#

Like the missing default graphics and such? Yeah - that why I mentioned it would be sort of cumbersome to use - would have to be manually configured.

balmy ferry
eager dome
#

I've just set mine up - it seems to be basically functional... but I'll add a script and see if it's events and such are working

balmy ferry
eager dome
#

All I've done is

  • create a slider in the hierarchy
  • delete it's Slider component
  • add the new component
  • copy the Handle target graphic from another slider and paste it
  • And dragged these two GOs to these fields:
eager dome
#

Oh though maybe the graphic copy + paste is wrong

balmy ferry
#

I have done it, but first time it was weird though

balmy ferry
#

I have deleted it and did one more time

#

and set it up then

eager dome
#

I think the target graphic's supposed to come from the Background GO?

balmy ferry
#

i gonna try to use that method now

balmy ferry
#

proved by normal slider

eager dome
#

oh I see

#

Yes that'd make sense as to why it's named "Handle" πŸ˜†

balmy ferry
#

it works ))

eager dome
#

\o/

#

epic!

balmy ferry
#

yeah

#

now no bugs I guess

eager dome
#

don't jynx it πŸ‘€

balmy ferry
#

everything works good now

#

@eager dome thank you one more time!

#

thanks for your time and effort 🫑

eager dome
#

Your welcome! Thanks for the interesting problem 🫑

balmy ferry
balmy ferry
eager dome
#

😁

balmy ferry
#

that's a pleasure when someone does not let your issue and writes in a few minutes with a new solution that they have invented

eager dome
#

I like to explore other peoples' questions, because it makes me learn and think about things which I wouldn't have otherwise πŸ‘

But I feel you

balmy ferry
#

@eager dome I am sorry to bother you one more time, but maybe you know why rawValue is changed just after I have clicked on the TimeSlider?

#
if (Input.GetKeyDown(KeyCode.RightArrow))
{
    Debug.Log("RightArrow");
    timeSlider.rawValue += secondsRemote.right;

    // this one works always
    // timeSlider.value += secondsRemote.right;
}
else if (Input.GetKeyDown(KeyCode.LeftArrow))
{
    Debug.Log("LeftArrow");
    timeSlider.rawValue -= secondsRemote.left;
}
balmy ferry
#

oh, never mind, I just forgot to change audioSource.time

if (Input.GetKeyDown(KeyCode.RightArrow))
{
    timeSlider.rawValue += secondsRemote.right;
    audioSource.time = timeSlider.value;
}
else if (Input.GetKeyDown(KeyCode.LeftArrow))
{
    timeSlider.rawValue -= secondsRemote.left;
    audioSource.time = timeSlider.value;
}
eager dome
balmy ferry
eager dome
balmy ferry
# eager dome As goes development πŸ˜… Still related to the time slider? :/ I have to leave fo...

Yeah, that's the issue with the same project.
So when the audioClip ends - I should start the new one. The clip is changed a few times in Update's else block.

private void Update()
{
    if (audioSource.isPlaying)
    {
        if (!changingTime) timeSlider.rawValue = (int)audioSource.time;

        ChangeTimeInputText();
    }
    else
    {
        print($"started: {audioSource.isPlaying}; \nclip: {audioSource.clip.name}; \ntime: {audioSource.time}");

        PlayBackgroundMusic();
        ChangeTimeSlider();

        Debug.LogWarning($"CHANGED: {audioSource.isPlaying}");
    }
}
private void ChangeTimeSlider()
{
    timeSlider.minValue = 0f;
    timeSlider.maxValue = (int)audioSource.clip.length;

    musicParsedLength = ParseMusicTime(audioSource.clip.length);

    ChangeTimeInputText();
}

private void ChangeRawValue(float rawValue)
{
    if (!Mathf.Approximately(timeSlider.rawValue, timeSlider.maxValue) && !(rawValue < 0 && timeSlider.rawValue <= timeSliderStart))
    {
        timeSlider.rawValue = rawValue;
        audioSource.time = timeSlider.value;
    }
}