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_Flashing - Fatal编程技术网

C# 单位:以可变开/关比的频率闪烁

C# 单位:以可变开/关比的频率闪烁,c#,unity3d,flashing,C#,Unity3d,Flashing,我希望能够以一定的频率闪现东西。例如,假设为2Hz。我还希望能够指定一个比率,在这个比率中,我可以显示周期的2/3,并将其隐藏1/3,因此比率为2:1。这是一个疯狂的一串闪烁,所以我需要保持灵活的方式,我这样做。可能会有一些比为3:5、频率为2Hz的闪烁,还有一些比为1:1、频率为4Hz的闪烁,以此类推 此外,我需要能够同步闪烁。因此,如果一个对象已经在闪烁,我开始闪烁另一个对象,它们需要同步(或者说,它们的周期需要同步,闪烁可能会随着比率的不同而变化)。但如果频率相同,它们需要同时“打开”,即

我希望能够以一定的频率闪现东西。例如,假设为2Hz。我还希望能够指定一个比率,在这个比率中,我可以显示周期的2/3,并将其隐藏1/3,因此比率为2:1。这是一个疯狂的一串闪烁,所以我需要保持灵活的方式,我这样做。可能会有一些比为3:5、频率为2Hz的闪烁,还有一些比为1:1、频率为4Hz的闪烁,以此类推

此外,我需要能够同步闪烁。因此,如果一个对象已经在闪烁,我开始闪烁另一个对象,它们需要同步(或者说,它们的周期需要同步,闪烁可能会随着比率的不同而变化)。但如果频率相同,它们需要同时“打开”,即使它们的比率不同。此外,它们都需要在最慢的开关打开的同时打开

我目前的方法是:我有一个游戏对象FlashCycle,它的更新方法基本上计算了我拥有的3个频率(2Hz、4Hz和8Hz)的进度

我尝试过不同的
time
s,但这并不重要,所以如果你不认为这是个坏主意的话,我们还是坚持使用它吧

现在,每当我想刷新一个对象时,在它自己的
Update()
中,我会这样做:

switch (flashRate.herz)
    {
        case FlashRateInterval.twoHerz:
            show = flashCycle.oneHerzProgress <= onTimePercentage;
        case FlashRateInterval.fourHerz:
            show =flashCycle.twoHerzProgress <= onTimePercentage;
        case FlashRateInterval.eightHerz:
            show =flashCycle.fourHerzProgress <= onTimePercentage;
        default:
            show =true;
    }
开关(flashRate.herz)
{
案例FlashRateInterval.twoHerz:

show=flashCycle.oneHerzProgress您有一些不同之处,因为您在一个更新()周期中用完成所有事情,您可以使用并实现这一点

// onRatio and offRatio are "optional" parameters
// If not provided, they will simply have their default value 1
IEnumerator Flash(float frequency ,float onRatio = 1, float offRatio = 1)
{

    float cycleDuration = 1.0f / frequency;
    float onDuration = (onRatio/ (onRatio + offRatio)) * cycleDuration;
    float offDuration = (offRatio/ (onRatio + offRatio)) * cycleDuration; 

    while(true)
    {
        show = true;

        yield return new WatForSeconds(onDuration);        

        show = false;

        yield return new WatForSeconds(offDuration);
    }
}
因此,您可以使用频率(例如8Hz)调用它

StartCoroutine(Flash(8.0f));
这实际上等于您设置
onRatio=offRatio
的任何调用

StartCoroutine(Flash(8.0f, onRatio = 1, offRatio = 1));

StartCoroutine(Flash(8.0f, onRatio = 2, offRatio = 2));

....
或使用频率和比率,例如1(开):2(关)和8Hz


使用此设置,协程将在
while(true)
-循环中“永远”运行。因此,在启动具有不同参数的新协程之前,不要忘记首先停止所有具有

 StopAllCoroutines();

现在,如果您想在更新方法中动态更改,您必须在roder中添加一些控制标志和其他变量,以确保只有在发生更改时才调用新的协同程序:

FlashRateInterval currentInterval;
float currentOnRatio = -1;
float currentOffRatio = -1;

void Update()
{
    // if nothing changed do nothing
    if(flashRate.herz == currentInterval
       //todo && Mathf.Approximately(<yourOnRatio>, currentOnRatio)
       //todo && Mathf.Approximately(<yourOffRatio>, currentOffRatio)
    ) return;

    StopAllCoroutines();

    currentInterval = flashRate.herz;
    //todo currentOnRatio = <yourOnRatio>;
    //todo currentOffRatio = <yourOffRatio>;

    switch (flashRate.herz)
    {
        case FlashRateInterval.twoHerz:
            StartCoroutine(2.0f);
            //todo StartCoroutine(2.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
        case FlashRateInterval.fourHerz:
            StartCoroutine(4.0f);
            //todo StartCoroutine(4.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
        case FlashRateInterval.eightHerz:
            StartCoroutine(8.0f);
            //todo StartCoroutine(8.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
        default:
            show =true;
    }
}
以便直接使用正确的值

  • 我会调用频率变量
    flashRate.herz
    。您也不会调用大小值
    cube.meters
    。我建议将其重命名为
    flashRate.frequency


  • 要归档同步,您需要访问所有行为并比较它们的值(因此我要说的是一些
    静态列表
    )然后,例如,在协同程序中,等待所有布尔值都设置为真,然后再继续使用您自己的布尔值。为此,您需要额外的布尔值,因为在一个组件上,
    show
    可能永久为真

    public bool isBlinking;
    
    IEnumerator Flash(float frequency ,float onRatio = 1, float offRatio = 1)
    {
        //todo: You'll have to set this false when not blinking -> in Update
        isBlinking = true;
    
        float cycleDuration = 1.0f / frequency;
        float onDuration = (onRatio/ (onRatio + offRatio)) * cycleDuration;
        float offDuration = (offRatio/ (onRatio + offRatio)) * cycleDuration; 
    
        // SYNC AT START
        show = false;
    
        // wait until all show get false
        foreach(var component in FindObjectsOfType<YOUR_COMPONENT>())
        {
            // skip checking this component
            if(component == this) continue;
    
            // if the component is not running a coroutine skip
            if(!component.isBlinking) continue;
    
            // Now wait until show gets false
            while(component.show)
            {
                // WaitUntilEndOfFrame makes it possible
                // for us to check the value again already before
                // the next frame
                yield return new WaitForEndOfFrame;
            }
        }
    
        // => this line is reached when all show are false
    
        // Now lets just do the same but this time wating for true
        // wait until all show get false
        foreach(var component in FindObjectsOfType<YOUR_COMPONENT>())
        {
            // skip checking this component
            if(component == this) continue;
    
            // if the component is not running a coroutine skip
            if(!component.isBlinking) continue;
    
            // Now wait until show gets false
            while(!component.show)
            {
                // WaitUntilEndOfFrame makes it possible
                // for us to check the value again already before
                // the next frame
                yield return new WaitForEndOfFrame;
            }
        }
    
        // this line is reached when all show are getting true again => begin of loop
    
        while(true)
        {
    
        .........
    
    public bool正在闪烁;
    IEnumerator闪烁(浮动频率,浮动接通比率=1,浮动断开比率=1)
    {
    //todo:在更新中不闪烁->时,必须将此设置为false
    isBlinking=true;
    浮动循环率=1.0f/频率;
    浮点数持续时间=(onRatio/(onRatio+offRatio))*循环次数;
    浮动关闭持续时间=(关闭比率/(打开比率+关闭比率))*循环关闭;
    //开始时同步
    show=false;
    //等到所有显示都变为假
    foreach(FindObjectsOfType()中的var组件)
    {
    //跳过检查此组件
    如果(组件==此)继续;
    //如果组件未运行协同路由,则跳过
    如果(!component.isBlinking)继续;
    //现在等到节目变假
    while(component.show)
    {
    //WaitUntilEndOfFrame使之成为可能
    //让我们在之前再次检查该值
    //下一帧
    返回新的WaitForEndOfFrame;
    }
    }
    //=>当所有显示均为false时,到达此行
    //现在,让我们做同样的事情,但这一次等待的是真实的
    //等到所有显示都变为假
    foreach(FindObjectsOfType()中的var组件)
    {
    //跳过检查此组件
    如果(组件==此)继续;
    //如果组件未运行协同路由,则跳过
    如果(!component.isBlinking)继续;
    //现在等到节目变假
    而(!component.show)
    {
    //WaitUntilEndOfFrame使之成为可能
    //让我们在之前再次检查该值
    //下一帧
    返回新的WaitForEndOfFrame;
    }
    }
    //当所有显示再次变为真=>循环开始时,达到此行
    while(true)
    {
    .........
    
    除了使用有点慢的
    FindObjectsOfType()
    ,您还可以执行以下操作

    public static List<YOUR_COMPONENT> Components = new List<YOUR_COMPONENT>();
    
    private void Awake()
    {
        if(!Components.Contains(this)){
            Components.Add(this);
        }
    }
    
    公共静态列表组件=新列表();
    私人空间
    {
    如果(!Components.Contains(this)){
    增加(本);
    }
    }
    

    因此,您也会得到当前禁用的组件和对象

    您可能希望使用
    屈服返回
    ,否则您的协同程序将在第一帧后结束。如果我使用的协同程序以最快的速度“启动”(在我的情况下为8Hz),这是否明智/是否有效对于4Hz和2Hz,四分之三跳过一次?我有点喜欢在一个集中的地方进行闪烁,并考虑拥有这段代码(即使重写到所有可能的美!)在每个游戏对象中运行都很糟糕?啊,好吧,所以你建议的问题是,我很难让多个对象同步闪烁,同时拥有不同的闪烁比率,除非我为每个对象运行一个协同进程(即使这样,它们也可能在某个时候关闭)。即使它们有不同的闪烁比率,我也需要它们同时“打开”所有对象(aka具有相同的周期开始)。我试图用
    sync
    解释的是,当我使另一个对象闪烁时,它应该
    FlashRateInterval currentInterval;
    float currentOnRatio = -1;
    float currentOffRatio = -1;
    
    void Update()
    {
        // if nothing changed do nothing
        if(flashRate.herz == currentInterval
           //todo && Mathf.Approximately(<yourOnRatio>, currentOnRatio)
           //todo && Mathf.Approximately(<yourOffRatio>, currentOffRatio)
        ) return;
    
        StopAllCoroutines();
    
        currentInterval = flashRate.herz;
        //todo currentOnRatio = <yourOnRatio>;
        //todo currentOffRatio = <yourOffRatio>;
    
        switch (flashRate.herz)
        {
            case FlashRateInterval.twoHerz:
                StartCoroutine(2.0f);
                //todo StartCoroutine(2.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
            case FlashRateInterval.fourHerz:
                StartCoroutine(4.0f);
                //todo StartCoroutine(4.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
            case FlashRateInterval.eightHerz:
                StartCoroutine(8.0f);
                //todo StartCoroutine(8.0f, onRatio = <yournRatio>, offRatio = <yourOffRatio>);
            default:
                show =true;
        }
    }
    
    public enum FlashRateInterval
    {
        AllwaysOn,
    
        twoHerz = 2,
        fourHerz = 4,
        eightHerz = 8
    }
    
    public bool isBlinking;
    
    IEnumerator Flash(float frequency ,float onRatio = 1, float offRatio = 1)
    {
        //todo: You'll have to set this false when not blinking -> in Update
        isBlinking = true;
    
        float cycleDuration = 1.0f / frequency;
        float onDuration = (onRatio/ (onRatio + offRatio)) * cycleDuration;
        float offDuration = (offRatio/ (onRatio + offRatio)) * cycleDuration; 
    
        // SYNC AT START
        show = false;
    
        // wait until all show get false
        foreach(var component in FindObjectsOfType<YOUR_COMPONENT>())
        {
            // skip checking this component
            if(component == this) continue;
    
            // if the component is not running a coroutine skip
            if(!component.isBlinking) continue;
    
            // Now wait until show gets false
            while(component.show)
            {
                // WaitUntilEndOfFrame makes it possible
                // for us to check the value again already before
                // the next frame
                yield return new WaitForEndOfFrame;
            }
        }
    
        // => this line is reached when all show are false
    
        // Now lets just do the same but this time wating for true
        // wait until all show get false
        foreach(var component in FindObjectsOfType<YOUR_COMPONENT>())
        {
            // skip checking this component
            if(component == this) continue;
    
            // if the component is not running a coroutine skip
            if(!component.isBlinking) continue;
    
            // Now wait until show gets false
            while(!component.show)
            {
                // WaitUntilEndOfFrame makes it possible
                // for us to check the value again already before
                // the next frame
                yield return new WaitForEndOfFrame;
            }
        }
    
        // this line is reached when all show are getting true again => begin of loop
    
        while(true)
        {
    
        .........
    
    public static List<YOUR_COMPONENT> Components = new List<YOUR_COMPONENT>();
    
    private void Awake()
    {
        if(!Components.Contains(this)){
            Components.Add(this);
        }
    }