【问题标题】:How to move 2D Object within camera view boundary如何在相机视图边界内移动 2D 对象
【发布时间】:2017-11-01 23:05:33
【问题描述】:

我有一个场景,我的相机没有跟随我的播放器。当玩家到达相机的尽头时,我希望玩家不能走得更远(超出相机视图)。我该怎么做?

我的运动密码

public class PlayerBlueController : MonoBehaviour {

public float speed;
private float x;



// Use this for initialization
void Start () {


}

// Update is called once per frame
void FixedUpdate () {

    x = Input.GetAxis ("Horizontal") / 100 * speed;
    transform.Translate (x,0,0);

}
}

从这里可以看出。它离开了相机的视野。

【问题讨论】:

  • 在每个极端角落(左下角,右上角)放置两个空游戏对象。然后使用他们的位置来钳制用户的运动。或者,如果您只是像您看起来的那样在一维中移动,x = Mathf.Clamp(x, minX, maxX);

标签: c# unity3d


【解决方案1】:

我注意到你使用了 Collider2D。 您应该使用Rigidbody2D.MovePosition 而不是transform.Translate,否则在使用transform.Translate 时可能会遇到问题。

1.获取最终移动位置并将其转换为 ViewPortPoint 中的新位置,Camera.main.WorldToViewportPoint

2。将Mathf.Clamp 的限制应用于#1中的结果。

3. 使用Camera.main.ViewportToWorldPoint 将 ViewPortPoint 转换回世界点。

4。最后,用Rigidbody2D.MovePosition移动它。


下面的代码是从this答案修改的,包括对屏幕边界的限制。

不带Rigidbody移动

仅在不需要碰撞和物理时使用:

public float speed = 100;
public Transform obj;

public void Update()
{
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");

    //Move only if we actually pressed something
    if ((h > 0 || v > 0) || (h < 0 || v < 0))
    {
        Vector3 tempVect = new Vector3(h, v, 0);
        tempVect = tempVect.normalized * speed * Time.deltaTime;


        Vector3 newPos = obj.transform.position + tempVect;
        checkBoundary(newPos);
    }
}

void checkBoundary(Vector3 newPos)
{
    //Convert to camera view point
    Vector3 camViewPoint = Camera.main.WorldToViewportPoint(newPos);

    //Apply limit
    camViewPoint.x = Mathf.Clamp(camViewPoint.x, 0.04f, 0.96f);
    camViewPoint.y = Mathf.Clamp(camViewPoint.y, 0.07f, 0.93f);

    //Convert to world point then apply result to the target object
    obj.position = Camera.main.ViewportToWorldPoint(camViewPoint);
}

使用Rigidbody2D移动对象

在需要碰撞和物理时使用:

public float speed = 100;
public Rigidbody2D rb;

public void Update()
{
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");

    //Move only if we actually pressed something
    if ((h > 0 || v > 0) || (h < 0 || v < 0))
    {
        Vector3 tempVect = new Vector3(h, v, 0);
        tempVect = tempVect.normalized * speed * Time.deltaTime;

        //rb.MovePosition(rb.transform.position + tempVect);

        Vector3 newPos = rb.transform.position + tempVect;
        checkBoundary(newPos);
    }
}

void checkBoundary(Vector3 newPos)
{
    //Convert to camera view point
    Vector3 camViewPoint = Camera.main.WorldToViewportPoint(newPos);

    //Apply limit
    camViewPoint.x = Mathf.Clamp(camViewPoint.x, 0.04f, 0.96f);
    camViewPoint.y = Mathf.Clamp(camViewPoint.y, 0.07f, 0.93f);

    //Convert to world point then apply result to the target object
    Vector3 finalPos = Camera.main.ViewportToWorldPoint(camViewPoint);
    rb.MovePosition(finalPos);
}

【讨论】:

  • 感谢您的回答。真的很有帮助。我想问一些事情。 mathf.clamp 到底是做什么的?因为当我更改数字 0.04f 0.96f 时,播放器只会粘在相机的一侧。这些数字是多少?我没有理解它背后的逻辑。还有一个关于运动的问题。当我释放按钮时,播放器会继续播放一些时间。我怎样才能防止这种情况发生?
  • 使用Input.GetAxisRaw 代替Input.GetAxis 使其立即停止或设置Rigidbody.velocity to Vector3.zero` 以立即停止。屏幕视口在 x 轴上的值介于 0(左)到 1(右)之间。0.04f 是您希望对象位于 x 轴上的最小值。 0.96f 是您希望对象位于 x 值上的最大值。您可以创建这些公共变量并在编辑器中修改它们,直到获得确定屏幕上对象位置的最小值/最大值的完美值。
  • 例如public float min = 0.04f;public float max = 0.96f; 则可以使用camViewPoint.x = Mathf.Clamp(camViewPoint.x, min, max);。在编辑器中,您可以使用修改最小值和最大值,直到获得所需的完美值。
  • 一切正常。但有一件事。我必须将 Input.GetAxisRaw 更改为 Input.GetKey(KeyCode.A) 并将其设为 AddForce。因为我想在不同的目的上使用我的 a、d 键和箭头键。我能够做到这一点,但我现在不能用同样的东西限制玩家。除了使用 getkey-addforce 来使用 wasd 和箭头键之外,我应该做其他事情还是需要完全更改方法以限制玩家移动?
  • 我建议你还是用MovePosition而不是AddForce。只需删除Input.GetAxis,然后将Vector3(h, v, 0); 中的hv 替换为01。按下时使用1 (Input.GetKey),释放时使用0 (Input.GetKeyUp)。提出一个新问题,因为这个问题使用了Input.GetAxis。我会看看它。我回来时可能会出去几个小时,我会看看。如果您创建新问题,请不要忘记发布您当前的代码。
【解决方案2】:

图片没有反应。 但你可以查看播放器位置

x = Input.GetAxis ("Horizontal") / 100 * speed;
if(gameobject.transform.x > someValue)
    x=0

游戏对象将是场景中的对象,您将类附加到它。

另一种方法是将 2 个空的游戏对象与对撞机作为 invisibleWall 并获得对撞机给玩家

【讨论】:

    【解决方案3】:

    可能的解决方案是:

    1.获取屏幕角的坐标(左上、右上、左下、右下)。您可以使用Screen.height and Screen.width 获取此坐标。

    2.使用Camera.ScreenToWorldPoint使用您需要的相机转换此坐标。

    3.获取你的玩家坐标并检查他们是否在由屏幕角的4个坐标组成的矩形内。

    【讨论】:

      【解决方案4】:

      您需要根据相机的边缘限制变换的位置。 Here is an answer describing the different coordinate systems in unity

      你可能想要做这样的事情:

      float xMin = Camera.main.ViewportToWorldPoint(Vector3.zero).x;
      float xMax = Camera.main.ViewportToWorldPoint(Vector3.one).x;
      
      Vector3 currentPos = transform.position;
      float dx = Input.GetAxis ("Horizontal") / 100 * speed;
      Vector3 desiredPos = new Vector3(currentPos.x + dx, currentPos.y, currentPos.z);
      
      Vector3 realPos = desiredPos;
      
      if(desiredPos.x > xMax)
          realPos.x = xMax;
      else if(desiredPos.x < xMin)
          realPos.x = xMin;
      
      transform.position = realPos;
      

      Read up here for more info on ViewportToWorldPoint(), it's extremely useful to become comfortable with the different coordinate spaces and how you can convert between them.

      【讨论】:

        猜你喜欢
        • 2021-07-10
        • 1970-01-01
        • 2014-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多