Я программирую окно редактора в Unity, чтобы можно было быстро создавать настольные игры. Моя проблема связана с тем, что ScreenToWorldPoint() заставляет сценарий думать, что предыдущая плитка находится в совершенно другом месте, чем на самом деле.
Я пробовал вместо этого использовать основную камеру, но это думает, что плитка находится в центре экрана. Я попытался сфокусировать камеру на предыдущем фрагменте, чтобы в любом случае использовать основную камеру, но это затруднило бы реализацию системы расходящихся траекторий в дальнейшем (и мне не нравится, как это вообще ощущается). Я попытался поместить положение предыдущего тайла и положение мыши на экране в метод мировой точки и сравнить их, но, как и ожидалось, это также не сработало. Наконец, я также попробовал почти все комбинации различных камер в OnSceneGUI(), и ни одна из них не смогла решить проблему, с которой я столкнулся. Чат GPT тоже выдает плохой код, так что я очень растерялся. Я думаю, что проблема как-то связана с тем, что камеры видят мир иначе, чем мировые координаты, в которых существуют тайлы, что делает векторы несравнимыми. Я так думаю, потому что перетаскивание по виду сцены меняет «центр» вида мира с точки зрения SceneCam, но не положение первого тайла (который всегда существует в центре мировых координат).
Ниже мой код как для скрипта трафарета (в котором, как я думаю, проблема), так и для скрипта Board Builder (в случае, если этот скрипт вызывает скрипт трафарета таким образом, что вызывает проблемы). Вероятно, в скрипте Board Builder также есть некоторые несвязанные ошибки. Я еще не закончил с этим (но буду рад любым советам по этому сценарию!).
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using UnityEngine;
using UnityEditor;
[ExecuteInEditMode]
public class StencilScript : MonoBehaviour
{
private static EdgeCollider2D tileDist;
private static Vector3 mousePos;
private static Vector3 worldMousePos;
private static Vector3 worldTilePos;
private static Vector3 relativePos;
private static Transform body;
void OnEnable()
{
body = gameObject.transform;
tileDist = gameObject.AddComponent();
tileDist.points = new Vector2[] {
new Vector2(-1, -1),
new Vector2(-1, -0.5f),
new Vector2(-1, 0),
new Vector2(-1, 0.5f),
new Vector2(-1, 1),
new Vector2(-0.5f, 1),
new Vector2(0, 1),
new Vector2(0.5f, 1),
new Vector2(1, 1),
new Vector2(1, 0.5f),
new Vector2(1, 0),
new Vector2(1, -0.5f),
new Vector2(1, -1),
new Vector2(0.5f, -1),
new Vector2(0, -1),
new Vector2(-0.5f, -1),
new Vector2(-1, -1) };
SceneView.duringSceneGui += OnSceneGUI;
}
private static void OnSceneGUI(SceneView sceneView)
{
Event e = Event.current;
if (e.isMouse)
{
Camera cam = Camera.main;
Camera sceneCam = sceneView.camera;
mousePos = e.mousePosition;
mousePos.y = cam.pixelHeight - mousePos.y;
worldMousePos = sceneCam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, sceneCam.nearClipPlane));
}
}
private static Vector2 GetDrawLocation()
{
Vector2 exactPos = tileDist.ClosestPoint(worldMousePos);
Vector2[] targets = tileDist.points;
Vector2 drawPos = targets[0];
for (int i = 1; i < targets.Length; i++)
{
float distanceA = Vector2.Distance(exactPos, targets);
float distanceB = Vector2.Distance(exactPos, drawPos);
if (distanceA < distanceB)
{
drawPos = targets;
}
}
return drawPos;
}
public void UpdateDrawLocation(GameObject tile)
{
if (tile != null)
{
Vector2 drawLocation = GetDrawLocation();
tile.transform.position = new Vector3(drawLocation.x, drawLocation.y, tile.transform.position.z);
}
}
}
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class BoardBuilder : EditorWindow
{
StencilScript _stencilScript;
string boardName = "";
GameObject active;
GameObject stencil;
GameObject board;
GameObject nextToPlace;
List tiles = new List();
int tileCount;
int nextSuitID;
bool buildButton;
string prefabFolder = "Assets/Prefabs/Tiles";
private GameObject[] prefabs;
private string[] tileNames;
GameObject[] suitSpaces = new GameObject[4];
int selected;
static Vector2 mousePos;
[MenuItem("Tools/Board Builder")]
public static void ShowWindow() {
GetWindow(typeof(BoardBuilder)); // GetWindow is from the EditorWindow Class
}
private void OnEnable() {
LoadTiles();
board = GameObject.FindGameObjectWithTag("Board");
if (board != null)
{
tiles.Add(board.transform);
for (int i = 0; i < board.transform.childCount; i++)
{
tiles.Add(board.transform.GetChild(i));
}
tileCount = board.transform.childCount + 1;
active = tiles[tiles.Count - 1].gameObject;
}
}
private void OnGUI()
{
boardName = EditorGUILayout.TextField("BoardName", boardName);
if (GUILayout.Button("Create Board") && GameObject.FindGameObjectWithTag("Board") == null)
{
board = Instantiate(prefabs[0].gameObject);
board.tag = "Board";
board.name = boardName + " (Home)";
board.transform.position = new Vector3(0, 0, 0);
tileCount = 1;
}
tileCount = EditorGUILayout.IntField("Tile Count", tileCount);
buildButton = GUILayout.Toggle(buildButton, "Build Mode");
selected = GUILayout.SelectionGrid(selected, tileNames, 2);
if (GUILayout.Button(new GUIContent("Refresh Tile Selection", "Checks for new tiles in the 'Tile' folder")))
{
LoadTiles();
}
GUILayout.Label("--------------\nMap?");
}
private void LoadTiles()
{
string[] guids = AssetDatabase.FindAssets("t:Prefab", new[] { prefabFolder });
prefabs = new GameObject[guids.Length];
tileNames = new string[guids.Length];
for (int i = 0; i < guids.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(guids);
prefabs = AssetDatabase.LoadAssetAtPath(path);
tileNames = prefabs.name;
}
}
[ExecuteInEditMode]
void Update()
{
if(board != null)
{
if (!buildButton)
{
if(active!= null && active.GetComponent() != null)
{
DestroyImmediate(active.GetComponent());
DestroyImmediate(active.GetComponent());
}
if (nextToPlace != null)
{
ChangeTileInUse(-1);
}
}
else
{
active = Selection.activeGameObject;
if(active != null)
{
if (active.GetComponent() == null)
{
_stencilScript = active.AddComponent();
}
if (nextToPlace == null || nextToPlace.GetComponent().tileType != selected)
{
ChangeTileInUse(selected);
}
_stencilScript.UpdateDrawLocation(nextToPlace);
if (Input.GetMouseButtonDown(0))
{
PlaceTile();
}
}
}
}
}
void ChangeTileInUse(int tileID)
{
DestroyImmediate(nextToPlace);
if (tileID == -1)
{
nextToPlace = null;
}
else
{
nextToPlace = Instantiate(prefabs[tileID], board.transform);
nextToPlace.GetComponent().tileType = selected;
}
}
private void PlaceTile()
{
UnityEngine.Debug.Log("place");
DestroyImmediate(active.GetComponent());
DestroyImmediate(active.GetComponent());
tiles[tileCount] = active.transform;
Selection.activeGameObject = nextToPlace;
active = nextToPlace;
active.AddComponent();
nextToPlace = Instantiate(prefabs[selected].gameObject, board.transform);
tileCount++;
}
}
Подробнее здесь: https://stackoverflow.com/questions/788 ... -edit-mode
Проблемы с Camera.ScreenToWorldPoint() Unity Engine в режиме редактирования ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Проблемы с Camera.ScreenToWorldPoint() Unity Engine в режиме редактирования
Anonymous » » в форуме C# - 0 Ответы
- 11 Просмотры
-
Последнее сообщение Anonymous
-