Unity将预制件对齐到左上方(2D游戏)

时间:2019-06-04 02:27:57

标签: c# unity3d

我正在做我的第一个游戏,其中脚本将障碍物(预制件)放置到场景中。它们在2D环境中的大小均不同。我在下面使用此代码放置它们

Instantiate(normal1, new Vector3(x, y , 0), Quaternion.identity);

这非常好用,除了我需要将所有障碍物从左上方定位。因此,如果我的x和y分别为0、0,则仅障碍物的角将覆盖0、0的位置,而不是整个对象。从我使用GUI元素的经验来看,您可以根据自己的喜好进行调整。预制件是否一样?如果是,怎么做?还是可以以某种方式移动对象的原点?

1 个答案:

答案 0 :(得分:1)

我假设您正在谈论非UI元素。

最简单的方法是为您的对象赋予父对象GameObject并以某种方式进行排列,以使父GameObject已经具有您想要的轴心(左上角)。为此,您首先要正确定位(未来的)父对象,然后将子对象拖到层次结构中(同时保持其当前位置)。

enter image description here

然后,您必须在脚本中使用Camera.ScreenToWorldPoint才能在3D世界中找到屏幕左上角的位置,例如

// an optional offset from the top-left corner in pixels
Vector2 PixelOffsetFromTopLeft;

// Top Left pixel is at 
// x = 0
// y = Screen height

// and than add the desired offset
var spawnpos = new Vector2(0 + PixelOffsetFromTopLeft.x, Screen.height - PixelOffsetFromTopLeft.y);

// as z we want a given distance to camera (e.g. 2 Units in front)
spawnedObject = Instantiate(Prefab, camera.ScreenToWorldPoint(new Vector3(spawnpos.x, spawnpos.y, 2f)), Quaternion.identity);

我用作示例的完整脚本

public class Spawner : MonoBehaviour
{
    public GameObject Prefab;

    public Vector2 PixelOffsetFromTopLeft = Vector2.zero;

    private GameObject spawnedObject;
    private Camera camera;

    private void Start()
    {
        camera = Camera.main;
    }

    private void Update()
    {
        if (Input.anyKeyDown)
        {
            // you don't need this I just didn't want to mess up the scene
            // so I just destroy the last spawned object before placing a new one
            if (spawnedObject)
            {
                Destroy(spawnedObject);
            }

            // Top Left pixel is at 
            // x = 0
            // y = Screen height

            // and than add the desired offset
            var spawnpos = new Vector2(0 + PixelOffsetFromTopLeft.x, Screen.height - PixelOffsetFromTopLeft.y);

            // as z we want a given distance to camera (e.g. 2 Units in front)
            spawnedObject = Instantiate(Prefab, camera.ScreenToWorldPoint(new Vector3(spawnpos.x, spawnpos.y, 2f)), Quaternion.identity);
        }
    }
}

enter image description here

现在将始终生成锚定在左上方的对象。如果相机移动或调整窗口大小,将无法保持这种状态。


如果您的问题是在调整窗口大小时也要保持该位置,则可以使用相同的代码,例如在Update方法中(出于效率的考虑,您应该仅在真正需要/窗口实际调整大小时才调用它),例如

public class StickToTopLeft : MonoBehaviour
{
    private Camera camera;

    public Vector2 PixelOffsetFromTopLeft = Vector2.zero;

    private void Start()
    {
        camera = Camera.main;
    }

    // Update is called once per frame
    private void Update()
    {
        var spawnpos = new Vector2(0 + PixelOffsetFromTopLeft.x, Screen.height - PixelOffsetFromTopLeft.y);

        // This time simply stay at the current distance to camera
        transform.position = camera.ScreenToWorldPoint(new Vector3(spawnpos.x, spawnpos.y, Vector3.Distance(camera.transform.position, transform.position)));
    }
}

现在,即使在调整窗口大小之后,该对象也始终保持锚定在左上角,并允许随后调整其偏移量。

enter image description here