Полагаю, вы говорите об элементах, не относящихся к интерфейсу пользователя.
Проще всего было бы дать вашим объектам родительский GameObject
и расположить их таким образом, чтобы родительский GameObject уже имел точку поворота, в которой вы его хотите (верхний левый угол). Вы делаете это, сначала правильно позиционируя (будущий) родительский объект, а затем просто перетаскиваете дочерний объект в него в иерархии (пока он сохраняет свою текущую позицию).

Тогда в вашем скрипте вы должны использовать Camera.ScreenToWorldPoint
, чтобы найти верхнее левое угловое положение экрана в трехмерном мире, например
// 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)));
}
}
Теперь объект всегда привязан к верхнему левому углу даже после изменения размера окна и позволяет впоследствии корректировать его смещение.
