C# 光线投射时滑块未填充
我正在处理unity3d,面临一个问题。在场景中有一个C# 光线投射时滑块未填充,c#,unity3d,C#,Unity3d,我正在处理unity3d,面临一个问题。在场景中有一个主摄影机,它有一个子对象作为世界空间画布,该画布也有一个子对象作为图像。我附加了脚本MouseLook用于旋转相机,相机通过按a键投射光线。此外,在场景中还有一个世界空间画布,其中有一个框碰撞器组件和一个子对象滑块,画布上附加了脚本滑块选择 该脚本引用了slidergameobject,并具有一个Coroutine,当我们通过按下a键将光线投射到画布上时,该脚本将填充滑块。我的代码运行良好,但无法正确填充滑块。当光线被投射时,它会立即改变场景
主摄影机
,它有一个子对象作为世界空间画布
,该画布也有一个子对象作为图像。我附加了脚本MouseLook
用于旋转相机,相机通过按a
键投射光线。此外,在场景中还有一个世界空间画布
,其中有一个框碰撞器
组件和一个子对象滑块
,画布上附加了脚本滑块选择
该脚本引用了slidergameobject
,并具有一个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模式。你可以在googleDontDestroyOnLoad
和Singleton上搜索更多信息。我刚刚意识到你的UI元素上有一个碰撞器不应该这样做。请查看我更新的答案。