【问题标题】:Unity Can't flip sprite from timer elapsed functionUnity无法从计时器经过的功能中翻转精灵
【发布时间】:2021-06-07 06:24:50
【问题描述】:

我刚刚开始探索 unity & c# 一起工作,不小心遇到了下一个问题: 我有一条鱼。鱼本来应该从左到右走,然后改变它的方向,从右到左走。我还没有完成那个移动的部分,但我打算用计时器来做。因此计时器处于活动状态,鱼开始移动,计时器停止,改变方向,计时器重置,鱼开始移动等。 我想翻转我的精灵,所以它会面向正确的方向。它不适用于 Elapsed 函数,我不明白为什么。如果你有任何想法,请分享

using System.Timers;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class FishBehavior : MonoBehaviour
{
    public float moveSpeed;
    private int direction; //for left -1, for right 1
    private Timer timer;
    private SpriteRenderer img;
    private Rigidbody2D rb;


    void Start()
    {
        img = GetComponent<SpriteRenderer>();
        rb = GetComponent<Rigidbody2D>();
        direction = 1;
        timer = new Timer();
        timer.Elapsed += TimerElapsed;
        ChangeTimerOptions();
    }

    private void Move()
    {
        //moving
    }

    private void ChangeDirection()
    {
        direction *= -1;
        img.flipX = !img.flipX; //Doesn't work!
        //stop movement
    }

    private void ChangeTimerOptions()
    {
        System.Random rand = new System.Random();
        timer.Interval = rand.Next(3000, 8000);
        timer.Enabled = true;
        Move();
    }

    private void TimerElapsed(object source, ElapsedEventArgs e)
    {
        ChangeDirection();
        ChangeTimerOptions();
    }

}

【问题讨论】:

    标签: c# unity3d timer sprite


    【解决方案1】:

    问题在于TimerElapsed 的回调与 Unity 的回调位于不同的线程上。这意味着您在其中对通常在 Unity 中工作的方法进行的任何类型的调用都不会。我建议改用CoroutineInvoke

    为了简要解释两者是什么,Coroutine 是一种特殊方法,可以在多个帧上完成少量工作。该方法也可以暂停一段时间以等待执行代码。 InvokeInvokeRepeating 是在一定时间后执行方法或在设定的开始时间和设定的时间后持续调用方法的调用。

    如果您最终还要合并一个移动并随机化等待时间,我会考虑使用 Coroutine 而不是 Invoke,这样您就可以处理来自同一个主调用的所有移动/翻转逻辑。

    public float moveSpeed;
    private int direction; //for left -1, for right 1
    private Timer timer;
    private SpriteRenderer img;
    private Rigidbody2D rb;
    
    // store the coroutine in case a duplicate call occurs somehow
    private Coroutine MoveAndFlip = null;
    
    void Start()
    {
        img = GetComponent<SpriteRenderer>();
        rb = GetComponent<Rigidbody2D>();
        direction = 1;
    
        // detect if any coroutine is already running
        CleanUpMoveAndFlipCoroutine();
    
        MoveAndFlip = StartCoroutine(MoveAndFlipAsset());
    }
    
    private void Move()
    {
        //moving
    }
    
    private void ChangeDirection()
    {
        direction *= -1;
        img.flipX = !img.flipX;
        //stop movement
    }
    
    private IEnumerator MoveAndFlipAsset()
    {
        // instead of milliseconds, use seconds
        float randomTimeInterval = Random.Range(3.0f, 8.0f);
    
        while(true)
        {
           // can do movement here - depending on how you would like to apply motion it would change how
           // it is implemented such as directly changing velocity, using a Vector3.Lerp, AddForce, etc.
    
            // wait the time to flip
            yield return new WaitForSeconds(randomTimeInterval);
    
            // now flip
            ChangeDirection();
        }
    }
    
    private void CleanUpMoveAndFlipCoroutine()
    {
        if (MoveAndFlip != null)
            StopCoroutine(MoveAndFlip);
    }
    

    如果您想要上述实现的 Invoke 示例,请按照以下方式处理。

    void Start()
    {
        img = GetComponent<SpriteRenderer>();
        rb = GetComponent<Rigidbody2D>();
        direction = 1;
    
        Invoke("ChangeDirection", RandomTimeToFlip());
    }
    
    private float RandomTimeToFlip()
    {
        return Random.Range(3.0f, 8.0f); ;
    }
    
    private void ChangeDirection()
    {
        direction *= -1;
        img.flipX = !img.flipX;
        //stop movement
    
        // start our method again after a set amount of time
        Invoke("ChangeDirection", RandomTimeToFlip());
    }
    

    编辑:显然,您可以通过更改计时器的SynchronizingObject 引用来使用TimerElapsed,但我不确定将其分配给什么。不过,我仍然建议使用上述两种方法中的一种。

    【讨论】:

    • 非常感谢您解释这个问题!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多