【问题标题】:Find the next Transform to the left or right of a Player找到玩家左侧或右侧的下一个变换
【发布时间】:2018-04-09 21:18:08
【问题描述】:

我有一个类,它有一个公共的变换数组,这些变换是角色可以移动到的点。每次玩家按下 A 或 D 键时,他们的角色都会平滑地移动到左侧或右侧的下一个位置,具体取决于他们是按下 A 还是 D。

我尝试这样做的方式是在玩家按下键盘上的 A 或 D 键时启动协程。然后协程将立即找到数组中的下一个左变换点,并开始使用 while 循环移动到那里。

现在我遇到的问题是能够找到最近的左/右点。我该怎么做?

到目前为止,这是我的代码:

public Transform[] positions;

    public int StartPosition = 0;

    private void Awake()
    {
        //set the start position, change the index to the one you would like the player to start at
        transform.position = positions[StartPosition].position;
    }

    private void Update()
    {
        //Register Key Events
        if (Input.GetKeyDown(KeyCode.A))
        {
            StartCoroutine(Move("Left", transform.position));
        }
        if (Input.GetKeyDown(KeyCode.D))
        {
            StartCoroutine(Move("Right", transform.position));
        }
    }

    /// <summary>
    /// Moves the player character to the next position to the left or right
    /// </summary>
    IEnumerator Move(string dir, Vector2 currentPosition)
    {
        if(dir == "Left")
        {
            //Find and store next left position if it exists
            // HOW DO I DO THIS??????

            // Go To Next Left Position
            while (transform.position.x > nextLeftPos.position.x)
            {
                transform.position = Vector3.MoveTowards(transform.position, nextLeftPos.position, moveSpeed * Time.deltaTime);
                //Come back next frame
                yield return null;
            }

        }
    }

这是我的玩家移动组件:

提前致谢

【问题讨论】:

    标签: unity3d vector coroutine


    【解决方案1】:

    您可以使用指向播放器右侧的Transform.right 向量来完成此测试。

    通过创建一个从玩家到该位置的单位向量,并减去Transform.forward 向量,您将得到一个向量,可以让您测试该点是在玩家的左侧还是右侧。

    Vector3 f = transform.forward;
    Vector3 r = transform.right;
    foreach (Transform t in Positions) {
        Vector3 pos = t.position;
        Vector3 sideTest = (pos - f).normalized;
    
        if(Vector3.Dot(sideTest, r)) >= 0.0) {
            // This position its on the right
        } else {
            // This position is on the left
        }
    }
    

    在开始游戏之前将所有这些信息预先计算到树中会更有效,因为您可以获得接下来的 2 个位置来测试,而不是遍历所有数组。

    【讨论】:

      【解决方案2】:

      我假设你的位置不会在比赛期间改变。

      创建一个整数作为玩家位置。以屏幕中间为起点,忘记玩家当前的 transform.position。计算数组中的位置。

      例如;如果您的播放器停留在数组的第三个元素上。然后向右移动应该到第四个。所以第四个元素的位置已经在数组中定义为Transform。

      enter image description here

      粗略的脚本在这里;

       public int whichRoad;
          public float roadChangeSpeed = 5.0f;
          Vector2 roadMinusOne = new Vector2(-2.4f, -3.44f); // -1. Left road coordinates
          Vector2 roadZero = new Vector2(0f, -3.44f);       // 0.  Middle road coordinates
          Vector2 roadOne = new Vector2(2.44f, -3.44f);      // 1. Right road coordinates
          Vector2 choosenRoad;
      
      
      void SwipeLeft(){
      
      bla bla bla swipe left
      whichRoad--;
      
      }
      
      void SwipeRight(){
      
      bla bla bla swipe right
      whichRoad++;
      
      }
      
      void FixedUpdate()
      {
      
      ChangeRoad();
      }
      
      
          void ChangeRoad() 
              {
                  if (whichRoad == -1)
      
                  {
      
                    choosenRoad = roadMinusOne;
      
                  }
      
                  else if (whichRoad == 0)
      
                  {
      
                      choosenRoad = roadZero;
      
                  }
      
                  else if (whichRoad == 1)
      
                  {
      
                      choosenRoad = roadOne;
      
                  }
      
      
                      transform.position = Vector2.Lerp(transform.position, choosenRoad, Time.deltaTime * roadChangeSpeed);
      

      【讨论】:

        【解决方案3】:

        您不应该使用 while 循环来检查这一点,因为通常性能非常低。建议的方法是使用 Raycast 和 collider。

        将球体碰撞器添加到所有“点”,即与当前玩家碰撞的候选游戏对象,并使用下面的sn-p:

        using UnityEngine;
        
        public class ExampleClass : MonoBehaviour
        {
            RaycastHit hit;
            void FixedUpdate()
            {
                Vector3 left = transform.TransformDirection(Vector3.left);
        
                if (Physics.Raycast(transform.position, left, out hit, Mathf.Infinity))
                    Debug.Log(hit.transform.position); // <--- this is what you want
            }
        } 
        

        一个很好的教程可以找到here

        【讨论】:

          【解决方案4】:

          感谢所有帮助。我找到了一个解决方案,它结合了在Update()Vector3.MoveTowards() 中使用运动标志。为了在玩家到达下一个目的地点后停止玩家,我有一个在每次移动调用后调用的函数,该函数检测玩家是否与数组中的任何移动点接触。如果是这样,它将移动标志设置为 false 并存储玩家当前位置索引。

          这是我的课:

          public class PlayerMovementStepper : MonoBehaviour
              {
                  [Tooltip("From furthest left to furthest right...")]
                  public Transform[] Points;
          
                  [Tooltip("How fast the player moves between points")]
                  public float MoveSpeed;
          
                  [Tooltip("On which point index does the player start?")]
                  public int StartPointIndex;
          
                  //This is going to be so we can tell which point to move towards
                  private int currentIndex;
          
                  //Moving flags for update function
                  private bool movingLeft = false;
                  private bool movingRight = false;
          
                  private void Awake()
                  {
                      transform.position = Points[StartPointIndex].position;
                      currentIndex = StartPointIndex;
                  }
          
                  private void Update()
                  {
                      //Check for movement flags
                      if (movingLeft)
                      {
                          if (currentIndex > 0)
                          {
                              transform.position = Vector3.MoveTowards(transform.position, Points[currentIndex - 1].position, MoveSpeed * Time.deltaTime);
                          }
                          StopPlayerIfOnPoint();
                      }
          
                      if (movingRight)
                      {
                          if (currentIndex < Points.Length - 1)
                          {
                              transform.position = Vector3.MoveTowards(transform.position, Points[currentIndex + 1].position, MoveSpeed * Time.deltaTime);
                          }
                          StopPlayerIfOnPoint();
                      }
                  }
          
                  public void MoveToNextLeft()
                  {
                      movingLeft = true;
                      movingRight = false;
                  }
          
                  public void MoveToNextRight()
                  {
                      movingLeft = false;
                      movingRight = true;
                  }
          
                  /// <summary>
                  /// This Function calls after every move call (if any) to check
                  /// whether or not the player hit the next point. If the player did hit 
                  /// then it will stop the player from moving and then store its current 
                  /// position.
                  /// </summary>
                  private void StopPlayerIfOnPoint()
                  {
                      var i = 0;
                      foreach (Transform pos in Points)
                      {
                          //Check for collisions
                          if (transform.position == pos.position)
                          {
                              if (movingLeft || movingRight)
                              {
                                  currentIndex = i;
                              }
                              movingLeft = false;
                              movingRight = false;
                          }
                          i++;
                      }
                  }
          
              }
          

          这个类允许用户附加多个玩家可以移动到的位置点,只要他们从最左边添加到最右边:

          我希望获得有关此解决方案的所有信息。我注意到我需要立即更改的一件事是我检测玩家何时到达他的下一个目的地点的方式。现在它依赖于玩家角色在点数组中的一个点的位置。我宁愿将目标点存储在一个变量中,当角色移动时,我可以检查玩家是否在该点的某个半径范围内,以便停止它并将玩家捕捉到该点。

          无论如何。让我知道你们的想法。提前致谢。

          【讨论】:

            猜你喜欢
            • 2018-11-19
            • 1970-01-01
            • 2019-12-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-29
            • 2021-09-03
            • 1970-01-01
            相关资源
            最近更新 更多