使用 Raycast2D 检测对象
Detecting an object with Raycast2D
我正在研究简单的策略游戏机制。我有一个兵营预制件。当我在场景中添加兵营并点击兵营时,我收到NullReferenceException
错误:
NullReferenceException: Object reference not set to an instance of an object PlacementController.Update () (at Assets/Scripts/PlacementController.cs:64)
当我尝试使用 Raycast2D 访问兵营的碰撞器名称时收到错误。
Barracks prefab 有一个 Box Collider2D collider(已选中触发器),它的标签是 "Building",它的层是 "Buildings"。它有一个 rigidbody2D 组件,它是一个运动学刚体。
我想不通这个问题。请帮助我。
感谢您的宝贵时间。
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);
}
Unity 有两个非常相似的物理引擎,但这是它们以微妙且令人困惑的方式不同的地方。
3D 引擎提供 Physics.Raycast
,命中时 returns true
,否则 false
,并允许您通过引用传递 RaycastHit
如果您需要了解更多关于命中的信息。
2D 引擎提供 Physics2D.Raycast
,而不是 returns 命中时 RaycastHit2D
,否则 null
。您的代码编写方式,您访问的 hit
与 raycast 调用返回的命中不同。
因此,您需要更接近于此的内容:
RaycastHit2D hit = Physics2D.Raycast(...); //edit in your raycast settings
if (hit) {
//do something with the hit data
}
(您可能会注意到 RaycastHit2D
隐式转换为 bool
。)
Unity 在很长一段时间内只有 3D 引擎,所以很多旧文档会说好像那是唯一的引擎。当心。
使用新的 UI 系统,您不必再像这样手动处理点击。只需在场景中实现 IPointerClickHandler on your MonoBehaviour, and ensure that there's EventSystem and PhysicsRaycaster。
好的!我检查了所有互联网,并且 none 了解人们在谈论 raycast2D 时真正需要什么,我终于找到了他们需要的东西,并且很高兴))我会尝试 post 到处回答,这样人们就可以轻松找到如果需要的话。
从相机屏幕到 2D sprite,sprite 应该与任何碰撞器一起使用,sprite 上的刚体不需要。
//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
}
}
}
然后使用选择的对象。
将脚本放在相机上,现在每个人都会很高兴,因为在互联网上,甚至 unity3D 社区都不了解人们对 raycast2D 的真正需求,希望将来他们可以使此功能更简单))
谢谢@анонимно,你的回答对我来说非常有用,我只是需要用 mousePosition 击中一条射线,然后知道这个位置是否击中了一些 2D 游戏对象,例如精灵。
我在 OnMouseUp() 方法中调用此点击。
void OnMouseUp(){
RaycastHit2D ray = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
if (ray)
{
GameObject hittedGameObject = ray.collider.gameObject;
// Do something else
}
}
我正在研究简单的策略游戏机制。我有一个兵营预制件。当我在场景中添加兵营并点击兵营时,我收到NullReferenceException
错误:
NullReferenceException: Object reference not set to an instance of an object PlacementController.Update () (at Assets/Scripts/PlacementController.cs:64)
当我尝试使用 Raycast2D 访问兵营的碰撞器名称时收到错误。
Barracks prefab 有一个 Box Collider2D collider(已选中触发器),它的标签是 "Building",它的层是 "Buildings"。它有一个 rigidbody2D 组件,它是一个运动学刚体。
我想不通这个问题。请帮助我。
感谢您的宝贵时间。
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);
}
Unity 有两个非常相似的物理引擎,但这是它们以微妙且令人困惑的方式不同的地方。
3D 引擎提供 Physics.Raycast
,命中时 returns true
,否则 false
,并允许您通过引用传递 RaycastHit
如果您需要了解更多关于命中的信息。
2D 引擎提供 Physics2D.Raycast
,而不是 returns 命中时 RaycastHit2D
,否则 null
。您的代码编写方式,您访问的 hit
与 raycast 调用返回的命中不同。
因此,您需要更接近于此的内容:
RaycastHit2D hit = Physics2D.Raycast(...); //edit in your raycast settings
if (hit) {
//do something with the hit data
}
(您可能会注意到 RaycastHit2D
隐式转换为 bool
。)
Unity 在很长一段时间内只有 3D 引擎,所以很多旧文档会说好像那是唯一的引擎。当心。
使用新的 UI 系统,您不必再像这样手动处理点击。只需在场景中实现 IPointerClickHandler on your MonoBehaviour, and ensure that there's EventSystem and PhysicsRaycaster。
好的!我检查了所有互联网,并且 none 了解人们在谈论 raycast2D 时真正需要什么,我终于找到了他们需要的东西,并且很高兴))我会尝试 post 到处回答,这样人们就可以轻松找到如果需要的话。 从相机屏幕到 2D sprite,sprite 应该与任何碰撞器一起使用,sprite 上的刚体不需要。
//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
}
}
}
然后使用选择的对象。
将脚本放在相机上,现在每个人都会很高兴,因为在互联网上,甚至 unity3D 社区都不了解人们对 raycast2D 的真正需求,希望将来他们可以使此功能更简单))
谢谢@анонимно,你的回答对我来说非常有用,我只是需要用 mousePosition 击中一条射线,然后知道这个位置是否击中了一些 2D 游戏对象,例如精灵。
我在 OnMouseUp() 方法中调用此点击。
void OnMouseUp(){
RaycastHit2D ray = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
if (ray)
{
GameObject hittedGameObject = ray.collider.gameObject;
// Do something else
}
}