我正在做我的第一个游戏,其中脚本将障碍物(预制件)放置到场景中。它们在2D环境中的大小均不同。我在下面使用此代码放置它们
Instantiate(normal1, new Vector3(x, y , 0), Quaternion.identity);
这非常好用,除了我需要将所有障碍物从左上方定位。因此,如果我的x和y分别为0、0,则仅障碍物的角将覆盖0、0的位置,而不是整个对象。从我使用GUI元素的经验来看,您可以根据自己的喜好进行调整。预制件是否一样?如果是,怎么做?还是可以以某种方式移动对象的原点?
答案 0 :(得分:1)
我假设您正在谈论非UI元素。
最简单的方法是为您的对象赋予父对象GameObject
并以某种方式进行排列,以使父GameObject已经具有您想要的轴心(左上角)。为此,您首先要正确定位(未来的)父对象,然后将子对象拖到层次结构中(同时保持其当前位置)。
然后,您必须在脚本中使用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);
}
}
}
现在将始终生成锚定在左上方的对象。如果相机移动或调整窗口大小,将无法保持这种状态。
如果您的问题是在调整窗口大小时也要保持该位置,则可以使用相同的代码,例如在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)));
}
}
现在,即使在调整窗口大小之后,该对象也始终保持锚定在左上角,并允许随后调整其偏移量。