我正在研究简单的策略游戏机制。我有一个军营预制件。当我在场景中添加军营并点击军营时,我收到NullReferenceException
错误:
NullReferenceException:对象引用未设置为对象的实例PlacementController.Update()(在Assets / Scripts / PlacementController.cs:64)
当我尝试使用Raycast2D到达军营的对撞机名称时收到错误。
军营预制件有一个Box Collider2D对撞机(触发器被检查),其标签是" Building"它的层是#34; Buildings"。它有一个刚体2D组件,它是一个运动刚体。
我无法弄清楚这个问题。请帮帮我。
感谢您的时间。
using UnityEngine;
using System.Collections;
public class PlacementController : MonoBehaviour
{
private Buildings buildings;
private Transform currentBuilding;
private bool _hasPlaced;
public LayerMask BuildingsMask;
public void SelectBuilding(GameObject g)
{
_hasPlaced = false;
currentBuilding = ((GameObject)Instantiate(g)).transform;
buildings = currentBuilding.GetComponent<Buildings>();
}
bool CheckPosition()
{
if (buildings.CollidersList.Count > 0)
{
return false;
}
return true;
}
// Update is called once per frame
void Update () {
Vector3 m = Input.mousePosition;
m = new Vector3(m.x, m.y, transform.position.z);
Vector3 p = GetComponent<Camera>().ScreenToWorldPoint(m);
if (currentBuilding != null && !_hasPlaced)
{
currentBuilding.position = new Vector3(p.x,p.y,0);
if (Input.GetMouseButtonDown(0))
{
if (CheckPosition())
{
_hasPlaced = true;
}
}
}
else
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = new RaycastHit2D();
Ray2D ray2D = new Ray2D(new Vector2(p.x,p.y), Vector3.down );
//Ray2D ray = new Ray(transform.position,new Vector3(p.x,p.y,p.z));
if (Physics2D.Raycast(new Vector2(p.x,p.y),Vector3.down,5.0f,BuildingsMask) )
{
Debug.Log(hit.collider.name); //error
}
}
}
}
------------------我正在分享答案,谢谢你的帮助------------------- -
if (Input.GetMouseButtonDown(0) && !EventSystem.current.IsPointerOverGameObject())
{
RaycastHit2D hit = new RaycastHit2D();
Ray2D ray2D = new Ray2D(new Vector2(p.x,p.y), Vector3.down );
hit = Physics2D.Raycast(new Vector2(p.x, p.y), Vector3.forward, 5.0f, BuildingsMask);
Debug.Log(hit.collider.name);
}
答案 0 :(得分:6)
Unity有两个物理引擎,它们非常相似,但这是一个区域,它们以微妙和混乱的方式不同。
3D引擎提供Physics.Raycast
,在点击时返回true
,否则返回false
,如果您需要了解更多,则可以通过引用传递RaycastHit
关于打击。
2D引擎提供Physics2D.Raycast
,而在点击时返回RaycastHit2D
,否则返回null
。编写代码的方式,您访问的hit
与光线投射调用返回的命中不同。
所以,你需要更接近这个:
RaycastHit2D hit = Physics2D.Raycast(...); //edit in your raycast settings
if (hit) {
//do something with the hit data
}
(您可能会注意到RaycastHit2D
隐式转换为bool
。)
Unity很长一段时间都只有3D引擎,所以很多旧的文档都会说话,好像这是唯一一个。请注意这一点。
答案 1 :(得分:1)
使用新的UI系统,您不必再像这样手动处理点击。只需在您的MonoBehaviour上实施IPointerClickHandler,并确保场景中存在EventSystem和PhysicsRaycaster。
答案 2 :(得分:0)
OK!我检查所有互联网,没有人理解人们真正需要什么时,我最终找到他们需要的东西,采取,并快乐))生病尝试回答所有地方,以便人们可以轻松找到它,如果它的需要。 从相机屏幕到2D精灵,精灵应该与任何对撞机,精灵上的刚体不需要。
//create 2 empty places for objects
public RaycastHit2D hit;
public GameObject choosen;
//in update put click on mouse //take Method play by clicking mouse
void Update(){
if (Input.GetKeyDown (KeyCode.Mouse0)) {
RayCaster ();
}
}
// create raycast Method
void RayCaster (){
RaycastHit2D ray = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay (Input.mousePosition));//making ray and object, taking mouse position on screen from camera
if(!UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject (-1)) {
if (ray.collider != null) {// for non error, check maybe you hit none collider sprite
hit = ray;// not hit is our obj from scene, but we cant work with it as an object
choosen = hit.transform.gameObject;// making hit obj as normal object, now we can work with it like with 3Dobject, not as sprite
}
}
}
然后选择obj。
把脚本放在相机上,现在每个人都会很开心,甚至在互联网上甚至Unity3D社区也不了解人们真正需要的是什么,使用raycast2D,希望将来可能会让这个功能变得更容易))
答案 3 :(得分:0)
谢谢@анонимно,你的答案对我来说非常有用,我只是需要使用mousePosition打一个光线,并知道这个位置是否与某个2D gameObject匹配,例如精灵。
我在OnMouseUp()方法中调用了这个命中。
void OnMouseUp(){
RaycastHit2D ray = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
if (ray)
{
GameObject hittedGameObject = ray.collider.gameObject;
// Do something else
}
}