c# - 在 Unity MonoBehaviour 脚本中实例化自定义对象
问题描述
我正在尝试在 Unity 中编写自己的小游戏,我对编程并不陌生,但对 Unity 和 C# 并不陌生。问题是我编写了自己的类来处理游戏地图,并且我试图将这些类连接到 Unity 中的 MonoBehaviour 脚本。
我有一个名为InputManager的脚本,它应该通过鼠标和键盘等处理输入,在这个脚本中,我想创建一个 MapManager 类的对象,它可以访问我的图块和东西。我遇到的问题是我似乎无法在 InputManager 中创建 MapManager 的实例,new MapManager()
无论如何都不是通用的。当我使用它时,我猜会创建某种 NullPointer?
我没有收到编译错误,但游戏启动后出现错误,即:
NullReferenceException: Object reference not set to an instance of an object
InputManager.Update () (at Assets/Scripts/InputManager.cs:55)
谢谢您的帮助!
!更新!:
我尝试使用一种解决方法,以便首先调用Start()或Update()并不重要,这意味着我只是在第一个Update()调用中实例化 MapManager。但是,当我运行程序时,错误仍然相同。我的结论是,不知何故我的构造函数不工作或Monobehaviour脚本不知何故不允许使用标准构造函数......有什么想法吗?
这是我的代码:
输入管理器.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class InputManager : MonoBehaviour
{
public int mapRightBorder = 10;
public int mapLeftBorder = -10;
public int mapTopBorder = 8;
public int mapBottomBorder = -4;
public double camSpeed = 0.2;
public double mouseSensitivity = 0.3;
public double scrollSensitivity = 2;
public double maxZoomIn = -3;
public double maxZoomOut = -12;
public Tilemap ground, overlays, buildings;
public Tilemap selected;
public AnimatedTile animatedTile;
private double detectionBorder;
private double leftRightCorrection;
private MapManager mapManager;
// Start is called before the first frame update
void Start()
{
detectionBorder = 50;
leftRightCorrection = 1.2;
mapManager = new MapManager();
mapManager.ground = ground;
mapManager.overlays = overlays;
mapManager.buildings = buildings;
mapManager.selected = selected;
mapManager.animatedTile = animatedTile;
Cursor.lockState = CursorLockMode.Confined;
}
// Update is called once per frame
void Update()
{
moveCam();
checkMouse();
mapManager.updateTilemaps();
}
private void moveCam()
{
double moveX = Camera.main.transform.position.x;
double moveY = Camera.main.transform.position.y;
double moveZ = Camera.main.transform.position.z;
double xPos = Input.mousePosition.x;
double yPos = Input.mousePosition.y;
double zDelta = Input.GetAxis("Mouse ScrollWheel");
if (Input.GetKey(KeyCode.LeftArrow))
{
moveX -= camSpeed * leftRightCorrection;
}
else if (xPos >= 0 && xPos < detectionBorder)
{
moveX -= camSpeed * mouseSensitivity * leftRightCorrection;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
moveX += camSpeed * leftRightCorrection;
}
else if (xPos <= Screen.width && xPos > Screen.width - detectionBorder)
{
moveX += camSpeed * mouseSensitivity * leftRightCorrection;
}
if(moveX > mapRightBorder || moveX < mapLeftBorder)
{
moveX = Camera.main.transform.position.x;
}
if (Input.GetKey(KeyCode.DownArrow))
{
moveY -= camSpeed;
}
else if (yPos >= 0 && yPos < detectionBorder)
{
moveY -= camSpeed * mouseSensitivity;
}
else if (Input.GetKey(KeyCode.UpArrow))
{
moveY += camSpeed;
}
else if (yPos <= Screen.height && yPos > Screen.height - detectionBorder)
{
moveY += camSpeed * mouseSensitivity;
}
if(moveY > mapTopBorder || moveY < mapBottomBorder)
{
moveY = Camera.main.transform.position.y;
}
if (!(moveZ + zDelta * scrollSensitivity > maxZoomIn || moveZ + zDelta * scrollSensitivity < maxZoomOut))
{
moveZ += zDelta * scrollSensitivity;
}
Vector3 newPos = new Vector3((float)moveX, (float)moveY, (float) moveZ);
Camera.main.transform.position = newPos;
}
private void checkMouse()
{
if (Input.GetMouseButtonDown(0))
{
mapManager.selectTile(Input.mousePosition);
}
}
}
地图管理器.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class MapManager
{
public int mapWidth = 16;
public int mapHeight = 16;
public Tilemap ground, overlays, buildings;
public Tilemap selected;
public AnimatedTile animatedTile;
private Vector3Int currentlySelected;
private OwnTilemap tilemap;
public MapManager()
{
tilemap = new OwnTilemap(mapWidth, mapHeight, ground, overlays, buildings);
currentlySelected = new Vector3Int(-1, -1, 0);
}
private Vector3Int mouseToTilemap(Vector3 mousePosition)
{
Ray ray = Camera.main.ScreenPointToRay(mousePosition);
// create a plane at 0,0,0 whose normal points to +Y:
Plane hPlane = new Plane(Vector3.forward, Vector3.zero);
// Plane.Raycast stores the distance from ray.origin to the hit point in this variable:
float enter = 0.0f;
if (hPlane.Raycast(ray, out enter))
{
//Get the point that is clicked
Vector3 hitPoint = ray.GetPoint(enter);
Vector3Int cell = ground.WorldToCell(hitPoint);
return cell;
}
return new Vector3Int(-1, -1, 0);
}
private bool isInBorders(Vector3Int p)
{
if (p.z != 0) return false;
if (p.x < 0 || p.x >= mapWidth) return false;
if (p.y < 0 || p.y >= mapHeight) return false;
return true;
}
public void updateTilemaps()
{
tilemap.updateTilemaps();
}
public void previewBuilding()
{
}
public void selectTile(Vector3 mousePosition)
{
if(currentlySelected != new Vector3Int(-1, -1, 0))
{
selected.SetTile(currentlySelected, null);
}
if (isInBorders(mouseToTilemap(mousePosition)))
{
selected.SetTile(mouseToTilemap(mousePosition), animatedTile);
currentlySelected = mouseToTilemap(mousePosition);
}
}
}
解决方案
推荐阅读
- canvas - ThreeJS - 沿样条线移动相机,同时保持轨道控制平移
- java - 这个 Java 布尔表达式有什么问题?为什么它会做它做的事情?
- java - 如何在字符串中的字符左右添加空格?
- r - 如何在 tidycensus 包中获取州内每个县的 zcta 代码列表?
- python - 我将如何修复此 pkg_resources.DistributionNotFound:未找到 'pygmt' 发行版,应用程序需要该发行版
- java - 在 android studio 中使用 TextChangeHandler 计算
- python - 是否有修复脚本中混合列类型的 DtypeWarning 的方法?
- java - 如何解决a.io.InvalidClassException:org.ejml.data.DMatrixRMaj;本地类不兼容:流 classdesc serialVersionUID
- php - 对嵌套对象应用回调
- vb.net - 我需要把它从一个子改写成一个函数