Unity/C# 如何在用户界面上连续运行脚本选择事件触发器 [英] Unity/C# How to run Script continuously on User Interface Select Event Trigger

查看:46
本文介绍了Unity/C# 如何在用户界面上连续运行脚本选择事件触发器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里完全是初学者,我希望在 UI 中选择它作为子项的按钮时连续平滑地旋转我的球体.

Complete beginner here, I'm looking to smoothly rotate my sphere continuously while the button it is a child of is selected in the UI.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class ButtonHandler : MonoBehaviour
{
    private Vector3 rotationDirection = new Vector3(0, .25f, 0);
    private float smoothTime = 1;
    private float convertedTime = 200;
    private float smooth;
    public void SetText()
    {
        Transform target = transform.Find("Globe");
        smooth = Time.deltaTime * smoothTime * convertedTime;
        target.Rotate(rotationDirection * smooth);
    }
}

问题是当我去选择我的按钮时,该功能只运行一次,而我希望它连续运行直到取消选择.

The issue is that when I go to select my button, the function is only ran a single time, whereas I want it to run continuously until deselected.

** 注意这是使用选择事件触发器

** Note this is using the Select Event Trigger

任何帮助将不胜感激!

如果您需要更多信息来回答,请告诉我

Please let me know if you need additional information to answer

谢谢!

推荐答案

扩展 Nicholas Sims 的回答 一个稍微更好的选择将是一个 协程.协程可以看作是临时的 Update 方法,因为默认情况下,每个迭代步骤都是在 Update 调用之后立即执行.

Extending Nicholas Sims' answer a slightly better option would be a Coroutine. Coroutines can be seen as temporary Update method as by default each iteration step is Don right after the Update call.

这样您就不会在触发器没有被激活时将资源浪费到 Update 方法上.

This way you don't waste resources to an Update method when the trigger is not activated anyway.

另请注意,Find 通常是一个非常昂贵的调用,应尽可能避免!您至少要做的是在 Update 每一帧中使用它!而是尽可能早地存储引用......甚至可能已经通过检查器中的字段!

Also note that Find in general is a very expensive call and should be avoided wherever possible! The least you want to do is using it in Update every frame! Instead store the reference as early as possible .. maybe even already via a field in the Inspector!

// For storing the reference
// If possible already reference this via the Inspector 
// by drag&drop to avoid Find entirely!
[SerializeField] private Transform target;

private bool rotate;

private void Start()
{
    if(!target) target = GameObject.Find("Globe");
}

public void ToggleRoutine()
{
    rotate = !rotate;

    if(!rotate)
    {
        StopAllCoroutines();
    }
    else
    {
        StartCoroutine (RotateContinuously());
    }
}

private IEnumerator RotateContinuously()
{
    // Whut? o.O
    // No worries, this is fine in a Coroutine as long as you yield somewhere inside
    while (true)
    {
        // You should use Find only once .. if at all. You should avoid it wherever possible!
        if(!target) target = transform.Find("Globe");
        smooth = Time.deltaTime * smoothTime * convertedTime;
        target.Rotate(rotationDirection * smooth);

        // Very important for not freezing the editor completely!
        // This tells unity to "pause" the routine here
        // render the current frame and continue
        // from this point on the next frame
        yield return null;
    }
}


如果您更喜欢While Pressed"行为,因此您希望在用户按住鼠标/按钮时继续旋转并在他松开时立即停止,您可以使用 IPointerXYHandler 接口,如

public class WhilePressedRotation : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
    [SerializeField] private Transform target;

    private void Start ()
    {
        if(!target) target = GameObject.Find("Globe");
    }

    public void OnPointerDown(PointerEventData pointerEventData)
    {
        StartCoroutine(RotateContinuously());
    }

    public void OnPointerUp(PointerEventData pointerEventData)
    {
        StopAllCoroutines();
    }

    public void OnPointerEnter(PointerEventData pointerEventData)
    {
        // Actually not really needed
        // but not sure if maybe required for having OnPointerExit work
    }

    public void OnPointerExit(PointerEventData pointerEventData)
    {
        StopAllCoroutines();
    }

    private IEnumerator RotateContinuously()
    {
        // Whut? o.O
        // No worries, this is fine in a Coroutine as long as you yield somewhere inside
        while (true)
        {
            // You should use Find only once .. if at all. You should avoid it wherever possible!
            if(!target) target = transform.Find("Globe");
            smooth = Time.deltaTime * smoothTime * convertedTime;
            target.Rotate(rotationDirection * smooth);

            // Very important for not freezing the editor completely!
            // This tells unity to "pause" the routine here
            // render the current frame and continue
            // from this point on the next frame
            yield return null;
        }
    }
}


或者更通用的代码


Or a more general code

public class WhilePressedButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
    [SerializeField] private UnityEvent whilePressed;

    public void OnPointerDown(PointerEventData pointerEventData)
    {
        StartCoroutine(ContinuousButton());
    }

    public void OnPointerUp(PointerEventData pointerEventData)
    {
        StopAllCoroutines();
    }

    public void OnPointerEnter(PointerEventData pointerEventData)
    {
        // Actually not really needed
        // but not sure if maybe required for having OnPointerExit work
    }

    public void OnPointerExit(PointerEventData pointerEventData)
    {
        StopAllCoroutines();
    }

    private IEnumerator ContinuousButton()
    {
        // Whut? o.O
        // No worries, this is fine in a Coroutine as long as you yield somewhere inside
        while (true)
        {

            whilePressed.Invoke();

            // Very important for not freezing the editor completely!
            // This tells unity to "pause" the routine here
            // render the current frame and continue
            // from this point on the next frame
            yield return null;
        }
    }
}

并在 whilePressed 中引用一个方法,就像通常在按钮 onClick 中通过检查器或代码一样.

And reference a method in whilePressed like usually in a button onClick via Inspector or code.

这篇关于Unity/C# 如何在用户界面上连续运行脚本选择事件触发器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆