繁体   English   中英

(2D) 在 Unity 中使用脚本制作 GameObject Shake

[英](2D) Make a GameObject Shake using script in Unity

当玩家进入危险区域(由对撞机触发)时,我有以下游戏 Object(盒子)掉落,但我想要的是盒子在掉落前摇晃半秒钟。 我认为协程是实现这种情况的最佳方式,并且我有使盒子掉落的代码,但我不确定如何使盒子在我的脚本中摇晃。

截屏

这是我的代码,以防它有助于理解:

public class FallingBox : MonoBehaviour
{    
    [SerializeField] float fallSpeed = 3f;
    [SerializeField] Transform target;
    
    Rigidbody2D rigidbody;
    BoxCollider2D boxCollider;

    bool isFalling = false;
    

    void Start()
    {
        rigidbody = GetComponent<Rigidbody2D>();
        boxCollider = GetComponent<BoxCollider2D>();
    }


    void Update()
    {    
        var frameMovement = fallSpeed * Time.deltaTime;
        var targetPosition = target.transform.position;

        if (isFalling)
        {    
            transform.position = Vector2.MoveTowards(transform.position, targetPosition, frameMovement);

            if (transform.position == targetPosition)
            {    
                gameObject.layer = LayerMask.NameToLayer("Ground");
                boxCollider.enabled = true;    
            }    
        }
    }


    //Called when entering the "danger zone"
    public void ChangeStatus()
    {
        isFalling = true;    
    }

也许是这样的? 我留下了很多你正常的秋季代码,只是协同它。

这个想法是让一个正弦波驱动震动,所以它有点平滑的震动。

public class FallingBox : MonoBehaviour
{
    [SerializeField] float fallSpeed = 3f;
    [SerializeField] Transform target;
    
    Rigidbody2D rigidbody;
    BoxCollider2D boxCollider;

    void Start()
    {
        rigidbody = GetComponent<Rigidbody2D>();
        boxCollider = GetComponent<BoxCollider2D>();
    }

    //Called when entering the "danger zone"
    public void ChangeStatus()
    {
        StartCoroutine(OnStartFall());
    }

    IEnumerator OnStartFall()
    {
        var maxTrembleTime = 0.25f;
        var currentTime = 0.0f;

        while(currentTime < maxTrembleTime)
        {
            currentTime = Mathf.Clamp(currentTime + Time.deltaTime, 0, maxTrembleTime);

            // sinOffset = 0 will have us back at the same point.
            // You might want to scale this number by a constant to make it shake faster or slower
            var sinOffset = (maxTrembleTime - currentTime); 
                                                
            var offset = Mathf.Sin(sinOffset); // Scale this offset to make it shake over more distance
            transform.position.y += offset;

            yield return null; // wait until next frame
        }

        // Begin normal falling code

        while(true)
        {
            var frameMovement = fallSpeed * Time.deltaTime;
            var targetPosition = target.transform.position;
            transform.position = Vector2.MoveTowards(transform.position, targetPosition, frameMovement);

            if (transform.position == targetPosition)
            {
                gameObject.layer = LayerMask.NameToLayer("Ground");
                boxCollider.enabled = true;
                break;
            }

            yield return null; // wait until next frame.
        }
    }
}

我现在做了这段代码,我认为它可能会有所帮助:

     IEnumerator Tremble() {
           for ( int i = 0; i < 10; i++)
           {
               transform.localPosition += new Vector3(5f, 0, 0);
               yield return new WaitForSeconds(0.01f);
               transform.localPosition -= new Vector3(5f, 0, 0);
               yield return new WaitForSeconds(0.01f);
           }
     }

这个想法是直接将localPosition非常快速地更改为不同的方向。 检查它是否是您正在寻找的东西,或者您是否可以努力到达那里

在大多数情况下,我不是协程的忠实拥护者,只要简单的逻辑就可以解决问题。

这是一个仅使用 Box State 来确定该框在任何给定时间应该做什么的示例:

public enum BoxState
{
    None,
    Shaking,
    Falling,
    Finished
}

public class FallingBox : MonoBehaviour
{
    [SerializeField] float fallSpeed = 3f;
    [SerializeField] Transform target;

    [SerializeField] float shakeTime = 0.5f;
    [SerializeField] float shakeSpeed = 1f;
    [SerializeField] float shakeFactor = 0.1f;

    Rigidbody2D rigidbody;
    BoxCollider2D boxCollider;

    private Vector3 originalPosition;
    private Vector3 targetPosition;
    private float timer;

    public BoxState boxState { get; private set; } = BoxState.None;

    void Start ( )
    {
        rigidbody = GetComponent<Rigidbody2D> ( );
        boxCollider = GetComponent<BoxCollider2D> ( );
    }


    void Update ( )
    {
        switch ( boxState )
        {
            case BoxState.None:
            case BoxState.Finished:
                return;

            case BoxState.Shaking:
                // Use Perlin Noise here for a quasi-random shake. Multiply or Add extra values for noise speed variations.
                // Many different ways to produc these offset values. This is just one variation.
                var xOffset = Mathf.PerlinNoise ( Time.time * shakeSpeed, 0 );
                var yOffset = Mathf.PerlinNoise ( 0, Time.time * shakeSpeed );

                transform.position = originalPosition + new Vector3 ( xOffset, yOffset, 0 ) * shakeFactor;
                timer += Time.deltaTime;
                if ( timer > shakeTime )
                {
                    boxState = BoxState.Falling;
                    timer = 0;
                }
                break;

            case BoxState.Falling:
                transform.position = Vector2.MoveTowards ( transform.position, targetPosition, fallSpeed * Time.deltaTime );
                if ( ( transform.position - targetPosition ).sqrMagnitude < Vector3.kEpsilon )
                {
                    transform.position = targetPosition;
                    gameObject.layer = LayerMask.NameToLayer ( "Ground" );
                    boxCollider.enabled = true;
                    boxState = BoxState.Finished;
                }
                break;            
        }
    }


    //Called when entering the "danger zone"
    public void ChangeStatus ( )
    {
        if ( boxState == BoxState.None )
        {
            boxState = BoxState.Shaking;
            originalPosition = transform.position;
            targetPosition = target.transform.position;
            timer = 0;
        }
    }
}

我个人也发现像这样的解决方案更容易更新。 在这里添加一个额外的 state 比创建和计时新的协程要容易得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM