我想要实现的是:牙刷应该出现在用户在BoxCollider
A
中单击的任何地方,包括BoxCollider
B
中的空间。但显然,点击B
内部不会显示牙刷(OnPointerDown没有被触发)。
我尝试过的是:改变层次的顺序。
牙刷显示后,用户点击内盒对撞机A
,但如果用户点击内盒对撞机B
-牙刷将不会出现,这意味着OnPointerDown
没有被触发。
我认为这是因为一个BoxCollider2D
在另一个BoxCollider2D
中的重叠。在我的例子中,B
In A
,我认为这是罪魁祸首,但我不知道如何解决它,或者可能有另一种方法来实现OnPointerDown
。
我用的是Perspective
相机。但是在这个场景中,所有元素都在同一个z position
中,这是0。是否有可能在每个BoxCollider2D
中触发BoxCollider2D
事件?
DragableObject.cs
这个剧本附在牙刷上。BoxCollider2D
A也属于牙刷。
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("pointer down");
if (GetComponent<DragableObject>() == null)
return;
currentObject = GetComponent<DragableObject>();
MeshRenderer renderer = GetComponent<MeshRenderer>();
if (ShowOnTouch)
ShowObject();
// Store original state
originalPosition = transform.position;
originalOrderLayer = renderer.sortingOrder;
// Snap to mouse
Vector3 newPos = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 30));
newPos.z = 30;
transform.position = newPos;
if (BringToFront)
{
if (renderer != null)
{
renderer.sortingOrder = 90;
}
}
ObjectActive.Invoke();
}
TargetListener.cs
这个脚本附在BoxCollider2D
B上。
public void OnPointerDown(PointerEventData eventData)
{
for (int i = 0; i < Affectors.Count; i++)
{
if (Affectors [i] == DragableObject.currentObject)
{
DragableObject.currentObject.OnEnterTarget(transform);
ITriggerEffect[] iTrigger = GetComponents<ITriggerEffect>();
for (int j = 0; j < iTrigger.Length; j++)
{
Debug.Log("iTrigger enter");
Debug.Log(iTrigger [j]);
iTrigger [j].Execute(eventData, PointerState.Down);
}
}
else
continue;
}
}
如果我点击A
,牙刷就会出现,除非我点击B
内部。在这里,调试日志。
这是附加到的BoxCollider2D
A,它是*Toothbrush
本身以及dragable.cs
脚本。
更新:感谢其他人的回答,这个问题对我来说变得更清楚了。下面是BoxCollider2D
A和BoxCollider2D
B,它们都有大多数OnPointerHander
的脚本。如何确保在各自的OnPointerHandler
上触发所有BoxCollider2D
?
我正在处理的问题:
A
是在指针输入B
时触发的。B
内部,OnPointerDown
只在B
上触发,而不是在A
上触发。发布于 2017-09-13 08:04:38
EventSystem的优点之一是事件不会通过GameObjects。第一个被击中的返回。不过,看起来你不想那样。使EventSystem返回多个GameObjects很复杂,
有两种解决办法:
1.Get .Get of EventSystem
(OnPointerDown
和IPointerDownHandler
),并使用旧的学校光线广播系统。
Physics2D.RaycastAll
和Physics2D.RaycastNonAlloc
可以做到这一点。出于性能原因,此示例将使用RaycastNonAlloc
。这很简单。
只附加到一个GameObject(空GameObject)
public class HitAll : MonoBehaviour
{
//Detect up to 100 Objects
const int raycastAmount = 100;
RaycastHit2D[] result = new RaycastHit2D[raycastAmount];
void Update()
{
#if UNITY_IOS || UNITY_ANDROID
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
checkRaycast(Input.GetTouch(0).position);
}
#else
if (Input.GetMouseButtonDown(0))
{
checkRaycast(Input.mousePosition);
}
#endif
}
void checkRaycast(Vector2 mousePos)
{
Vector3 origin = Camera.main.ScreenToWorldPoint(mousePos);
int hitCount = Physics2D.RaycastNonAlloc(origin, Vector2.zero, result, 200);
Debug.Log(hitCount);
for (int i = 0; i < hitCount; i++)
{
Debug.Log("Hit: " + result[i].collider.gameObject.name);
}
}
}
2.Continue使用EventSystem
,但重新引发事件。
首先,使用EventSystem.current.RaycastAll
抛出raycast,然后使用ExecuteEvents.Execute
手动调用该事件。
用2D对撞机连接到所有的Physics2DRaycaster
,并确保连接到摄像机上
public class ThroughEventScript : MonoBehaviour, IPointerDownHandler
{
public void OnPointerDown(PointerEventData eventData)
{
rethrowRaycast(eventData, eventData.pointerCurrentRaycast.gameObject);
//DO STUFF WITH THE OBJECT HIT BELOW
Debug.Log("Hit: " + eventData.pointerCurrentRaycast.gameObject.name);
}
void rethrowRaycast(PointerEventData eventData, GameObject excludeGameObject)
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = eventData.pressPosition;
//pointerEventData.position = eventData.position;}
//Where to store Raycast Result
List<RaycastResult> raycastResult = new List<RaycastResult>();
//Rethrow the raycast to include everything regardless of their Z position
EventSystem.current.RaycastAll(pointerEventData, raycastResult);
//Debug.Log("Other GameObject hit");
for (int i = 0; i < raycastResult.Count; i++)
{
//Debug.Log(raycastResult[i].gameObject.name);
//Don't Rethrow Raycayst for the first GameObject that is hit
if (excludeGameObject != null && raycastResult[i].gameObject != excludeGameObject)
{
//Re-simulate OnPointerDown on every Object hit
simulateCallbackFunction(raycastResult[i].gameObject);
}
}
}
//This causes functions such as OnPointerDown to be called again
void simulateCallbackFunction(GameObject target)
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
//pointerEventData.ra
RaycastResult res = new RaycastResult();
res.gameObject = target;
pointerEventData.pointerCurrentRaycast = res;
ExecuteEvents.Execute(target, pointerEventData, ExecuteEvents.pointerDownHandler);
}
}
https://stackoverflow.com/questions/46188071
复制相似问题