Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 光线投射时滑块未填充_C#_Unity3d - Fatal编程技术网

C# 光线投射时滑块未填充

C# 光线投射时滑块未填充,c#,unity3d,C#,Unity3d,我正在处理unity3d,面临一个问题。在场景中有一个主摄影机,它有一个子对象作为世界空间画布,该画布也有一个子对象作为图像。我附加了脚本MouseLook用于旋转相机,相机通过按a键投射光线。此外,在场景中还有一个世界空间画布,其中有一个框碰撞器组件和一个子对象滑块,画布上附加了脚本滑块选择 该脚本引用了slidergameobject,并具有一个Coroutine,当我们通过按下a键将光线投射到画布上时,该脚本将填充滑块。我的代码运行良好,但无法正确填充滑块。当光线被投射时,它会立即改变场景

我正在处理unity3d,面临一个问题。在场景中有一个
主摄影机
,它有一个子对象作为
世界空间画布
,该画布也有一个子对象作为图像。我附加了脚本
MouseLook
用于旋转相机,相机通过按
a
键投射光线。此外,在场景中还有一个
世界空间画布
,其中有一个
框碰撞器
组件和一个子对象
滑块
,画布上附加了脚本
滑块选择

该脚本引用了slider
gameobject
,并具有一个
Coroutine
,当我们通过按下
a
键将光线投射到画布上时,该脚本将填充滑块。我的代码运行良好,但无法正确填充滑块。当光线被投射时,它会立即改变场景。我想要的是第一个滑块是填充,音频是播放比滑块值等于0。比场景变化。我想我在
Coroutine
中做错了什么

代码:
光线投射脚本:

public class RayCast : MonoBehaviour
{
    private RaycastHit hit;

    [SerializeField]
    private AudioSource source;

    [SerializeField]
    private AudioClip clip;

    //Refrence of Slider Canvas Script
    [SerializeField]
    private SliderSelect sliderCanvasScript;

    private void Update()
    {
        Debug.DrawRay(transform.position, transform.forward, Color.cyan);

        if (Input.GetKeyDown(KeyCode.A) && SliderSelect.check)
        {
            if (Physics.Raycast(transform.position, transform.forward, out hit, 9f))
            {
                if (hit.collider.gameObject.name == "SliderCanvas")
                {
                    Debug.Log("Ray cast to the slider");
                    StartCoroutine(sliderCanvasScript.FillUp());
                    source.PlayOneShot(clip);
                    SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
                }
            }
        }
    }
}
滑块选择脚本:

public class SliderSelect : MonoBehaviour
{
    [SerializeField]
    private Slider mSlider;

    public static bool check;
    private void Start()
    {
        mSlider.minValue = 0;
        mSlider.maxValue = 100;
        mSlider.wholeNumbers = true;
        mSlider.value = 0;
        check = true;
    }

    public IEnumerator FillUp()
    {
        int i = 0;

        while (i <= 100)
        {
            mSlider.value += 2;
            i += 2;
            yield return null;
        }
        mSlider.value = 0 ;
    }
}
公共类幻灯片选择:MonoBehavior
{
[序列化字段]
私人滑杆滑杆;
公共静态布尔检查;
私有void Start()
{
mSlider.minValue=0;
mSlider.maxValue=100;
mSlider.wholeNumbers=真;
mSlider.value=0;
检查=正确;
}
公共IEnumerator填充()
{
int i=0;
而
我的代码工作正常,但没有正确填充滑块。它是
当光线投射时,立即改变场景。我想要的是第一个
滑块为填充,音频播放比滑块值等于0
换个场景,我觉得我在合作中做错了什么

那是因为你在打电话

StartCoroutine(sliderCanvasScript.FillUp());
source.PlayOneShot(clip);
SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
Update
函数进入,它实际上不需要等待
FillUp()
coroutine函数完成

从更新函数启动一个新的协同例程函数,然后在该协同例程函数中执行这三行代码。然后,您可以将
Start例程(sliderCanvasScript.FillUp());
替换为
yield return Start例程(sliderCanvasScript.FillUp())
在调用
source.PlayOneShot(clip);
后接
SceneManager.LoadScene(“Scene0”,LoadSceneMode.Single);

另外,要等待音频完成播放,请不要使用静态
PlayOneShot
功能

首先,使用
source.clip=clip;
将剪辑分配给AudioSource。现在使用
source.play();
播放。接下来,等待音频在(source.isplay){yield return null;}
播放时完成播放

该函数应该是这样的:

IEnumerator doInOrder()
{
    //Wait for Fill to finish
    yield return StartCoroutine(sliderCanvasScript.FillUp());
    //Assign Audio Clip
    source.clip = clip;
    //Then Play Sound
    source.Play();

    //Wait for Audio to finish Playing
    while (source.isPlaying)
    {
        yield return null;
    }
    //Load new Scene
    SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
}
public class RayCast : MonoBehaviour
{
    private RaycastHit hit;

    [SerializeField]
    private AudioSource source;

    [SerializeField]
    private AudioClip clip;

    //Refrence of Slider Canvas Script
    [SerializeField]
    private SliderSelect sliderCanvasScript;



    private void Update()
    {
        Debug.DrawRay(transform.position, transform.forward, Color.cyan);
        if (Input.GetKeyDown(KeyCode.A) && SliderSelect.check)
        {
            if (Physics.Raycast(transform.position, transform.forward, out hit, 9f))
            {
                if (hit.collider.gameObject.name == "SliderCanvas")
                {
                    Debug.Log("Ray cast to the slider");
                    StartCoroutine(doInOrder());
                }
            }
        }
    }

    IEnumerator doInOrder()
    {
        //Wait for Fill to finish
        yield return StartCoroutine(sliderCanvasScript.FillUp());
        //Then Play Sound
        source.clip = clip;
        //Then Play Sound
        source.Play();

        //Wait for Audio to finish Playing
        while (source.isPlaying)
        {
            yield return null;
        }
        //Load new Scene
        SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
    }
}
整个代码应该是这样的:

IEnumerator doInOrder()
{
    //Wait for Fill to finish
    yield return StartCoroutine(sliderCanvasScript.FillUp());
    //Assign Audio Clip
    source.clip = clip;
    //Then Play Sound
    source.Play();

    //Wait for Audio to finish Playing
    while (source.isPlaying)
    {
        yield return null;
    }
    //Load new Scene
    SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
}
public class RayCast : MonoBehaviour
{
    private RaycastHit hit;

    [SerializeField]
    private AudioSource source;

    [SerializeField]
    private AudioClip clip;

    //Refrence of Slider Canvas Script
    [SerializeField]
    private SliderSelect sliderCanvasScript;



    private void Update()
    {
        Debug.DrawRay(transform.position, transform.forward, Color.cyan);
        if (Input.GetKeyDown(KeyCode.A) && SliderSelect.check)
        {
            if (Physics.Raycast(transform.position, transform.forward, out hit, 9f))
            {
                if (hit.collider.gameObject.name == "SliderCanvas")
                {
                    Debug.Log("Ray cast to the slider");
                    StartCoroutine(doInOrder());
                }
            }
        }
    }

    IEnumerator doInOrder()
    {
        //Wait for Fill to finish
        yield return StartCoroutine(sliderCanvasScript.FillUp());
        //Then Play Sound
        source.clip = clip;
        //Then Play Sound
        source.Play();

        //Wait for Audio to finish Playing
        while (source.isPlaying)
        {
            yield return null;
        }
        //Load new Scene
        SceneManager.LoadScene("Scene0", LoadSceneMode.Single);
    }
}
不要将碰撞器放在画布UI组件上

碰撞器
应仅用于精灵/精灵渲染器(2D对象)和网格渲染器(2D对象)。不应将其放置在画布UI组件上

即使这对您有效,您也应该使用
OnPointerClick
检测滑块上的点击,然后使用
onValueChanged
事件检测滑块值的变化。检测这两种情况的脚本必须附加到
滑块
游戏对象。然后您可以实现两个事件,您可以注册并接收c单击或
滑块上的
值发生更改时返回

将下面的脚本附加到滑块:

public class SliderDetector : MonoBehaviour, IPointerClickHandler
{
    public Slider slider;

    public delegate void sliderClicked();
    public static event sliderClicked OnClicked;

    public delegate void valueChanged(float value);
    public static event valueChanged onValueChanged;

    // Use this for initialization
    void Awake()
    {
        slider = GetComponent<Slider>();
        //Subscribe To Slider Event
        slider.onValueChanged.AddListener(delegate { sliderCallBack(slider.value); });
    }


    public void OnPointerClick(PointerEventData eventData)
    {
        if (OnClicked != null)
        {
            //Notify All Subscribed function
            OnClicked();
        }
    }

    void sliderCallBack(float value)
    {
        if (onValueChanged != null)
        {
            //Notify All Subscribed function
            onValueChanged(value);
        }
    }

    void OnDisable()
    {
        //Un-Subscribe To Slider Event
        slider.onValueChanged.RemoveListener(delegate { sliderCallBack(slider.value); });
    }
}

滑块填充正确,但由于加载了场景,因此无法播放音频!请检查更新。它也被修改以解决音频问题。感谢您的详细回答。如果我们仅使用
[SerializeField]
作为一个场景的参考,我想再问一件事,我们是否可以禁用该
[SerializeField]
在下一个场景中。因为下一个场景没有这个字段的引用。我们怎么做?我想你不明白
SerializeField
的用途。它只用于在编辑器中显示一个私有变量。如果你想让GameObject在下一个场景中保留,你必须使用
DontDestroyOnLoad
funAction和Singleton模式。你可以在google
DontDestroyOnLoad
和Singleton上搜索更多信息。我刚刚意识到你的UI元素上有一个碰撞器不应该这样做。请查看我更新的答案。