【问题标题】:Unity2D move object up and back down with smooth transitionUnity2D 平滑过渡上下移动对象
【发布时间】:2021-01-04 02:11:08
【问题描述】:

(我是初学者,请耐心等待)。

它需要如何发生:

我有一个可以跳跃并击中瓷砖的玩家,在与瓷砖碰撞时向上移动固定距离,然后以平滑的过渡返回。

我目前所拥有的: 我正在检测碰撞,现在只需上下移动瓷砖即可。

捕获

瓷砖悬浮在空气中,所以基本上它们要么没有 RigidBody2D,要么有一个重力比例为 0 的瓷砖

我的尝试

基本上我已经尝试了 2 个解决方案:

(我不限于这两个,我想实现正确的解决方案,所以我对其他想法持开放态度)

  1. 我想简单地取当前位置,用另一个位置计算另一个向量,然后 lerp 到新位置,然后 lerp 回到初始位置。

         Vector2 initialPosition = transform.position;
         Vector2 targetPosition = new Vector2(initialPosition.x + 4f, initialPosition.y + 4f);
         print("Initial position: " + initialPosition);
         print("Target position: " + targetPosition);
         Vector2.Lerp(initialPosition, targetPosition, 1f);
    
  2. 我尝试添加比例为 0 的刚体

         private void OnCollisionEnter2D(Collision2D collision)
         {
         if (collision.gameObject.tag == "Ground")
         {
             Jumping = false;
             anim.SetInteger("State", 0);
    
         }
    
         // print("Colision layer: " + collision.collider.gameObject.layer);
    
         if (collision.collider.gameObject.layer == Mathf.Log(layerMask.value, 2))
         {
    
             GameObject Tile = collision.gameObject;
             Rigidbody2D rigidBody = Tile.GetComponent<Rigidbody2D>();
             rigidBody.gravityScale = 1;
             rigidBody.AddForce(new Vector2(0, 10f), ForceMode2D.Force);
             StartCoroutine(MoveTileWithForce(rigidBody));
         }
     }
    
     IEnumerator MoveTileWithForce(Rigidbody2D TileRigidBody)
     {
         yield return new WaitForSeconds(1);
         TileRigidBody.AddForce(new Vector2(0, -5f), ForceMode2D.Force);
         TileRigidBody.gravityScale = 0;
         print("END MY COROUTINE, gravityScale: " + TileRigidBody.gravityScale);
     }
    

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    我认为实现这一目标的最佳方法是采用这种简单的方式:

    1

    确保你的角色有一个box collider和一个Rigidbody,你想移动的方块也是如此。对于设置在 trigger 上的两个对撞机。如果您想为玩家添加另一个碰撞器以使他接触地面或击中敌人,您可以添加另一个 box 碰撞器,但请确保在他的头上有一个触发器

    2

    为您要移动的方块添加一个脚本,并为玩家添加一个标签,例如"player"

    3

    在这个新脚本中检查方块是否触发了播放器:

    void OnTriggerEnter2D(Collision other)
    {
    if(other.compareTag("player"))
    { StartCoroutine(MovingBlock(0.5f, transform.position, upperPosition));}
    |
    

    当玩家触摸方块时,它会进入 if 内部,它会启动一个协程,我现在将编写这个协程,以便您了解 0.5f 和其他变量

    IEnumerator MovingBlock(float time, Vector2 startpos, Vector2 endpos)
    {
        
                float elapsedTime = 0;
    
                    while (elapsedTime < time)
                    {
                        transform.position= Vector2.Lerp(startpos, endpos, (elapsedTime / time));
                        elapsedTime += Time.deltaTime;
    
                        yield return null;
                }
    
              elapsedTime = 0f;
    
                while (elapsedTime < time)
                    {
                        transform.position= Vector2.Lerp(endpos, startpos, (elapsedTime / time));
                        elapsedTime += Time.deltaTime;
    
                        yield return null;
                }
    }
    

    基本上,Coroutine 会将对象从startpos 移动到endpos,然后在您决定的时间量内(在本例中为 0.5 秒)再次返回。我使用了 Vector2 变量 upperposition,它只是您希望通过平台达到的高度。

    如果你愿意,你也可以在协程内部添加一些yield return new WaitForSeconds(timeToWait),让平台在某个位置等待你想要的秒数(timeToWait)

    【讨论】:

    • 您好 Leoverload,感谢您的帮助。您的解决方案需要进行一些小的更改,但总体而言使我走上了实现目标的正确轨道。我将在今天晚些时候对我所做的更改添加另一条评论。
    • 完美@JohnDoe
    【解决方案2】:

    在课程开始时声明Vector2 initialPosition

    在平铺对象的Start() 上,您应该获得initialPosition = transform.position

    OnCollisionEnter2D(Collision2D collision) 中,您可以启动一个协程来将磁贴放回原处。

    例如:

    播放器脚本:

    public class Player : MonoBehaviour
    {
        public Rigidbody2D rb;
        //Initialize the rigidbody on the editor.
    
        // Update is called once per frame
        void Update()
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                rb.AddForce(new Vector2(0f, 1000f));
            }
        }
    }
    

    还有瓷砖脚本:

    public class MyTile : MonoBehaviour
    {
      
        Vector2 initialPosition;
        float speed = 2f; //the speed the tile will go down.
    
        private void Start()
        {
            initialPosition = transform.position;
        }
    
        private void OnCollisionEnter2D(Collision2D collision)
        {
            //The amount you want to go up on the Y component, for this example I used 2.
            transform.position = new Vector2(transform.position.x, transform.position.y + 2f);
    
            StartCoroutine(MoveTileDown());
        }
    
        IEnumerator MoveTileDown()
        {
            while (transform.position.y > initialPosition.y)
            {
                transform.position = Vector2.Lerp(transform.position, initialPosition, Time.deltaTime * speed);
                yield return null; //Make it run every frame, just like Update()
            }
    
            StopCoroutine(MoveTileDown());
        }
    
    }
    
    

    有很多方法可以达到相同的效果,这只是其中一种。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 2015-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多