Unityでは、シーン内の何かに対する指のタッチ(指の描画)を検出する必要があると言います。
現代のUnityでこれを行う唯一の方法は非常に単純です:
ステップ1。そのオブジェクトにコライダーを置きます。 (「地面」またはそれが何であれ何でも。) 1
ステップ2。カメラのインスペクターパネルで、クリックしてPhysicsレイキャスター(関連する2Dまたは3D)を追加します。
ステップ3。以下の例Aのようにコードを使用します。
(ヒント-EventSystemがあることを確認することを忘れないでください... Unityが自動的に追加する場合とそうでない場合があります!)
素晴らしい、これ以上簡単なことはありません。 Unityは、UIレイヤーを通じて最終的にun/propagationを正しく処理します。デスクトップ、デバイス、エディターなどで均一かつ完璧に動作します。HoorayUnity。
すべて良い。しかし、「画面上」だけを描画したい場合はどうでしょうか。
つまり、ユーザーから「画面上」でスワイプ/タッチ/描画したいということです。 (たとえば、単に軌道カメラを操作する場合など)。カメラが走り回って動く通常の3Dゲームと同じです。
ワールドスペースのオブジェクトでの指の位置は必要ありません。抽象的な「指の動き」(つまりガラス上の位置)が必要なだけです。 。
その後、どのコライダーを使用しますか?コライダーなしでできますか?そのため、コライダーを追加するのは大変なことです。
これは何ですか:
私はある種のフラットコライダーを作成し、実際にカメラの下に取り付けます。したがって、カメラの錐台に座って、画面を完全に覆います。
(コードの場合、ScreenToWorldPointを使用する必要はないので、例Bのようにコードを使用してください-非常にシンプルで、完全に機能します。)
私の質問、私が説明する「アンダーカメラコルディア」を使用する必要があるのは少し奇妙に思われます。ガラスに触れるだけです。
ここでの取引は何ですか?
(注-今日の実際のプロジェクトでは使用できないUnityの古代の「タッチ」システムに関する質問には答えないでください。レガシーアプローチを使用して.UIを無視することはできません。)
コードサンプルA-シーンオブジェクトに描画します。 ScreenToWorldPointを使用します。
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class FingerMove:MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
public void OnPointerDown (PointerEventData data)
{
Debug.Log("FINGER DOWN");
prevPointWorldSpace =
theCam.ScreenToWorldPoint( data.position );
}
public void OnDrag (PointerEventData data)
{
thisPointWorldSpace =
theCam.ScreenToWorldPoint( data.position );
realWorldTravel =
thisPointWorldSpace - prevPointWorldSpace;
_processRealWorldtravel();
prevPointWorldSpace = thisPointWorldSpace;
}
public void OnPointerUp (PointerEventData data)
{
Debug.Log("clear finger...");
}
コードサンプルB ...ユーザーがデバイスのガラススクリーンで行うことだけに関心があります。ここでさらに簡単:
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class FingerMove:MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
private Vector2 prevPoint;
private Vector2 newPoint;
private Vector2 screenTravel;
public void OnPointerDown (PointerEventData data)
{
Debug.Log("FINGER DOWN");
prevPoint = data.position;
}
public void OnDrag (PointerEventData data)
{
newPoint = data.position;
screenTravel = newPoint - prevPoint;
prevPoint = newPoint;
_processSwipe();
}
public void OnPointerUp (PointerEventData data)
{
Debug.Log("FINEGR UP...");
}
private void _processSwipe()
{
// your code here
Debug.Log("screenTravel left-right.. " + screenTravel.x.ToString("f2"));
}
}
1 Unityを初めて使用する場合は、そのステップで、「描画」というレイヤーを作成してください。物理学の設定では、「描画」は何も操作しません。レイキャスターのステップ2では、レイヤーを「描画」に設定するだけです。
これから投稿する質問と回答は、かなり意見に基づいているようです。それでも私はできる限り最善の答えをします。
画面上のポインターイベントを検出しようとしている場合、オブジェクトで画面を表現することに問題はありません。あなたのケースでは、3Dコライダーを使用してカメラの錐台全体をカバーします。ただし、画面全体をカバーする2D UIオブジェクトを使用して、Unityでこれを行うネイティブな方法があります。画面は2Dオブジェクトで最もよく表現できます。私にとっては、これは自然なやり方のようです。
私はこの目的のために一般的なコードを使用します:
public class Screen : MonoSingleton<Screen>, IPointerClickHandler, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerDownHandler, IPointerUpHandler, IScrollHandler {
private bool holding = false;
private PointerEventData lastPointerEventData;
#region Events
public delegate void PointerEventHandler(PointerEventData data);
static public event PointerEventHandler OnPointerClick = delegate { };
static public event PointerEventHandler OnPointerDown = delegate { };
/// <summary> Dont use delta data as it will be wrong. If you are going to use delta, use OnDrag instead. </summary>
static public event PointerEventHandler OnPointerHold = delegate { };
static public event PointerEventHandler OnPointerUp = delegate { };
static public event PointerEventHandler OnBeginDrag = delegate { };
static public event PointerEventHandler OnDrag = delegate { };
static public event PointerEventHandler OnEndDrag = delegate { };
static public event PointerEventHandler OnScroll = delegate { };
#endregion
#region Interface Implementations
void IPointerClickHandler.OnPointerClick(PointerEventData e) {
lastPointerEventData = e;
OnPointerClick(e);
}
// And other interface implementations, you get the point
#endregion
void Update() {
if (holding) {
OnPointerHold(lastPointerEventData);
}
}
}
Screen
はシングルトンです。これは、ゲームのコンテキストでは画面が1つしかないためです。オブジェクト(カメラなど)は、そのポインターイベントをサブスクライブし、それに応じて自分自身を配置します。これにより、単一の責任が損なわれることもありません。
これを、いわゆるガラス(画面の表面)を表すオブジェクトに追加するときに使用します。 UIのボタンが画面から飛び出すと考えると、その下にガラスがあります。このため、グラスはCanvas
の最初の子である必要があります。もちろん、Canvas
は、意味をなすために画面スペースにレンダリングする必要があります。
ここでのハックの1つは、意味のないImage
コンポーネントをガラスに追加して、イベントを受け取ることです。これは、ガラスのレイキャストターゲットのように機能します。
Input
(Input.touches
など)。このガラスオブジェクトを実装します。これは、すべてのUpdate
呼び出しで入力が変更されたかどうかをチェックするように機能します。これはポーリングベースのアプローチのようですが、上記はイベントベースのアプローチです。
あなたの質問は、Input
クラスを使用して正当化する方法を探しているようです。私見、自分のために難しくしないでください。機能するものを使用します。そして、Unityは完璧ではないという事実を受け入れてください。
まず、OnPointerDown
関数を使用してオブジェクトのクリックを検出する_3
_の方法があることを理解する必要があります。
1。OnPointerDown
関数でクリックを検出するには、UIコンポーネントが必要です。これは、他の同様のUIイベントに適用されます。
2。2D/Sprite GameObjectでOnPointerDown
関数を使用してクリックを検出する別の方法は、_Physics2DRaycaster
_をカメラにアタッチし、次にOnPointerDown
をアタッチすることですクリックすると呼び出されます。 2D Colliderをアタッチする必要があることに注意してください。
3。これがコライダーのない3Dオブジェクトである場合2Dコライダーの場合、PhysicsRaycaster
をアタッチする必要がありますOnPointerDown
関数を呼び出すためにカメラに送信します。
画面を覆う大きなコライダーや2Dコライダーを使用するよりも、最初の方法でこれを行う方が合理的です。あなたがしなければならないことは、Canvas
、Panel GameObjectを作成し、画面全体に広がるImage
コンポーネントをそれにアタッチすることです。
.UIを深刻な解決策として使用しているとは思えません。大きなゲームをやっていて、すべてのUI(つまり、ボタン、メニューなど)を実行しているチームをリードしていると想像してください。私は歩行ロボットをやっているチームを率いています。突然、「ああ、ちなみに、タッチ( "!")は処理できません。UIをドロップしてください。パネル、実行中のすべての操作の下に置くことを忘れないでください。あなたが交換するすべてのキャンバスまたはカメラに1つ-そしてその情報を私に返しますOK!」 :)私はそれがただばかげていることを意味します。本質的に言うことはできません:「ああ、Unityはタッチを処理しません」
あなたがそれを説明した方法のようにそれほど難しいことではありません。 Canvas
、Panel
、Image
を作成できる長いコードを記述できます。画像のアルファを_0
_に変更します。あなたがしなければならないのは、そのコードをカメラまたは空のゲームオブジェクトにアタッチすることだけで、プレイモードでこれをすべて自動的に実行します。
画面上でイベントを受信するすべてのGameObjectをサブスクライブし、_ExecuteEvents.Execute
_を使用して、そのGameObjectに接続されているスクリプト内のすべてのインターフェイスにイベントを送信します。
たとえば、以下のサンプルコードは、OnPointerDown
イベントをtargetという名前のGameObjectに送信します。
_ExecuteEvents.Execute<IPointerDownHandler>(target,
eventData,
ExecuteEvents.pointerDownHandler);
_
あなたが遭遇する問題:
非表示のImage
コンポーネントは、他のUIまたはゲームオブジェクトがレイキャストを受信するのをブロックします。これがここでの最大の問題です。
ソリューション:
ブロッキングの問題が発生するため、画像のキャンバスをすべての上に配置することをお勧めします。これにより、他のすべてのUI/GameObjectを100ブロックしていることを確認できます。 _Canvas.sortingOrder = 12;
_がこれを支援します。
画像からOnPointerDown
などのイベントを検出するたびに、手動でOnPointerDown
イベントをImage
の下の他のすべてのUI/GameObjectsに再送信します。
まず、GraphicRaycaster
(UI)、_Physics2DRaycaster
_(2D collider)、PhysicsRaycaster
(3D Collider)を使用してレイキャストをスローし、結果をList
に格納します。
次に、リストの結果をループし、次のコマンドを使用して結果に人工イベントを送信することにより、受け取ったイベントを再送信します。
_ExecuteEvents.Execute<IPointerDownHandler>(currentListLoop,
eventData,
ExecuteEvents.pointerDownHandler);
_
あなたが遭遇する他の問題:
Toggle
を使用して、GraphicRaycaster
コンポーネントのエミュレートイベントを送信することはできません。これはUnityでは バグ です。これに気づくのに2日かかりました。
また、偽のスライダー移動イベントをSlider
コンポーネントに送信できませんでした。これがバグかどうかわかりません。
上記の問題の他に、これを実装することができました。 3の部分で提供されます。フォルダを作成し、すべてのスクリプトをその中に配置するだけです。
[〜#〜] scripts [〜#〜]:
1。_WholeScreenPointer.cs
_-Canvas
、GameObject、非表示のImage
。これは、Image
が常に画面をカバーするように、すべての複雑な処理を行います。また、すべてのサブスクライブGameObjectにイベントを送信します。
_public class WholeScreenPointer : MonoBehaviour
{
//////////////////////////////// SINGLETON BEGIN ////////////////////////////////
private static WholeScreenPointer localInstance;
public static WholeScreenPointer Instance { get { return localInstance; } }
public EventUnBlocker eventRouter;
private void Awake()
{
if (localInstance != null && localInstance != this)
{
Destroy(this.gameObject);
}
else
{
localInstance = this;
}
}
//////////////////////////////// SINGLETON END ////////////////////////////////
//////////////////////////////// SETTINGS BEGIN ////////////////////////////////
public bool simulateUIEvent = true;
public bool simulateColliderEvent = true;
public bool simulateCollider2DEvent = true;
public bool hideWholeScreenInTheEditor = false;
//////////////////////////////// SETTINGS END ////////////////////////////////
private GameObject hiddenCanvas;
private List<GameObject> registeredGameobjects = new List<GameObject>();
//////////////////////////////// USEFUL FUNCTIONS BEGIN ////////////////////////////////
public void registerGameObject(GameObject objToRegister)
{
if (!isRegistered(objToRegister))
{
registeredGameobjects.Add(objToRegister);
}
}
public void unRegisterGameObject(GameObject objToRegister)
{
if (isRegistered(objToRegister))
{
registeredGameobjects.Remove(objToRegister);
}
}
public bool isRegistered(GameObject objToRegister)
{
return registeredGameobjects.Contains(objToRegister);
}
public void enablewholeScreenPointer(bool enable)
{
hiddenCanvas.SetActive(enable);
}
//////////////////////////////// USEFUL FUNCTIONS END ////////////////////////////////
// Use this for initialization
private void Start()
{
makeAndConfigWholeScreenPinter(hideWholeScreenInTheEditor);
}
private void makeAndConfigWholeScreenPinter(bool hide = true)
{
//Create and Add Canvas Component
createCanvas(hide);
//Add Rect Transform Component
//addRectTransform();
//Add Canvas Scaler Component
addCanvasScaler();
//Add Graphics Raycaster Component
addGraphicsRaycaster();
//Create Hidden Panel GameObject
GameObject panel = createHiddenPanel(hide);
//Make the Image to be positioned in the middle of the screen then fix its anchor
stretchImageAndConfigAnchor(panel);
//Add EventForwarder script
addEventForwarder(panel);
//Add EventUnBlocker
addEventRouter(panel);
//Add EventSystem and Input Module
addEventSystemAndInputModule();
}
//Creates Hidden GameObject and attaches Canvas component to it
private void createCanvas(bool hide)
{
//Create Canvas GameObject
hiddenCanvas = new GameObject("___HiddenCanvas");
if (hide)
{
hiddenCanvas.hideFlags = HideFlags.HideAndDontSave;
}
//Create and Add Canvas Component
Canvas cnvs = hiddenCanvas.AddComponent<Canvas>();
cnvs.renderMode = RenderMode.ScreenSpaceOverlay;
cnvs.pixelPerfect = false;
//Set Cavas sorting order to be above other Canvas sorting order
cnvs.sortingOrder = 12;
cnvs.targetDisplay = 0;
//Make it child of the GameObject this script is attached to
hiddenCanvas.transform.SetParent(gameObject.transform);
}
private void addRectTransform()
{
RectTransform rctrfm = hiddenCanvas.AddComponent<RectTransform>();
}
//Adds CanvasScaler component to the Canvas GameObject
private void addCanvasScaler()
{
CanvasScaler cvsl = hiddenCanvas.AddComponent<CanvasScaler>();
cvsl.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
cvsl.referenceResolution = new Vector2(800f, 600f);
cvsl.matchWidthOrHeight = 0.5f;
cvsl.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
cvsl.referencePixelsPerUnit = 100f;
}
//Adds GraphicRaycaster component to the Canvas GameObject
private void addGraphicsRaycaster()
{
GraphicRaycaster grcter = hiddenCanvas.AddComponent<GraphicRaycaster>();
grcter.ignoreReversedGraphics = true;
grcter.blockingObjects = GraphicRaycaster.BlockingObjects.None;
}
//Creates Hidden Panel and attaches Image component to it
private GameObject createHiddenPanel(bool hide)
{
//Create Hidden Panel GameObject
GameObject hiddenPanel = new GameObject("___HiddenPanel");
if (hide)
{
hiddenPanel.hideFlags = HideFlags.HideAndDontSave;
}
//Add Image Component to the hidden panel
Image pnlImg = hiddenPanel.AddComponent<Image>();
pnlImg.Sprite = null;
pnlImg.color = new Color(1, 1, 1, 0); //Invisible
pnlImg.material = null;
pnlImg.raycastTarget = true;
//Make it child of HiddenCanvas GameObject
hiddenPanel.transform.SetParent(hiddenCanvas.transform);
return hiddenPanel;
}
//Set Canvas width and height,to matach screen width and height then set anchor points to the corner of canvas.
private void stretchImageAndConfigAnchor(GameObject panel)
{
Image pnlImg = panel.GetComponent<Image>();
//Reset postion to middle of the screen
pnlImg.rectTransform.anchoredPosition3D = new Vector3(0, 0, 0);
//Stretch the Image so that the whole screen is totally covered
pnlImg.rectTransform.anchorMin = new Vector2(0, 0);
pnlImg.rectTransform.anchorMax = new Vector2(1, 1);
pnlImg.rectTransform.pivot = new Vector2(0.5f, 0.5f);
}
//Adds EventForwarder script to the Hidden Panel GameObject
private void addEventForwarder(GameObject panel)
{
EventForwarder evnfwdr = panel.AddComponent<EventForwarder>();
}
//Adds EventUnBlocker script to the Hidden Panel GameObject
private void addEventRouter(GameObject panel)
{
EventUnBlocker evtrtr = panel.AddComponent<EventUnBlocker>();
eventRouter = evtrtr;
}
//Add EventSystem
private void addEventSystemAndInputModule()
{
//Check if EventSystem exist. If it does not create and add it
EventSystem eventSys = FindObjectOfType<EventSystem>();
if (eventSys == null)
{
GameObject evObj = new GameObject("EventSystem");
EventSystem evs = evObj.AddComponent<EventSystem>();
evs.firstSelectedGameObject = null;
evs.sendNavigationEvents = true;
evs.pixelDragThreshold = 5;
eventSys = evs;
}
//Check if StandaloneInputModule exist. If it does not create and add it
StandaloneInputModule sdlIpModl = FindObjectOfType<StandaloneInputModule>();
if (sdlIpModl == null)
{
sdlIpModl = eventSys.gameObject.AddComponent<StandaloneInputModule>();
sdlIpModl.horizontalAxis = "Horizontal";
sdlIpModl.verticalAxis = "Vertical";
sdlIpModl.submitButton = "Submit";
sdlIpModl.cancelButton = "Cancel";
sdlIpModl.inputActionsPerSecond = 10f;
sdlIpModl.repeatDelay = 0.5f;
sdlIpModl.forceModuleActive = false;
}
}
/*
Forwards Handler Event to every GameObject that implements IDragHandler, IPointerDownHandler, IPointerUpHandler interface
*/
public void forwardDragEvent(PointerEventData eventData)
{
//Route and send the event to UI and Colliders
for (int i = 0; i < registeredGameobjects.Count; i++)
{
ExecuteEvents.Execute<IDragHandler>(registeredGameobjects[i],
eventData,
ExecuteEvents.dragHandler);
}
//Route and send the event to UI and Colliders
eventRouter.routeDragEvent(eventData);
}
public void forwardPointerDownEvent(PointerEventData eventData)
{
//Send the event to all subscribed scripts
for (int i = 0; i < registeredGameobjects.Count; i++)
{
ExecuteEvents.Execute<IPointerDownHandler>(registeredGameobjects[i],
eventData,
ExecuteEvents.pointerDownHandler);
}
//Route and send the event to UI and Colliders
eventRouter.routePointerDownEvent(eventData);
}
public void forwardPointerUpEvent(PointerEventData eventData)
{
//Send the event to all subscribed scripts
for (int i = 0; i < registeredGameobjects.Count; i++)
{
ExecuteEvents.Execute<IPointerUpHandler>(registeredGameobjects[i],
eventData,
ExecuteEvents.pointerUpHandler);
}
//Route and send the event to UI and Colliders
eventRouter.routePointerUpEvent(eventData);
}
}
_
2。_EventForwarder.cs
_-非表示のImage
からイベントを受け取り、それを渡します_WholeScreenPointer.cs
_スクリプトに追加して処理します。
_public class EventForwarder : MonoBehaviour, IDragHandler, IPointerDownHandler, IPointerUpHandler
{
WholeScreenPointer wcp = null;
void Start()
{
wcp = WholeScreenPointer.Instance;
}
public void OnDrag(PointerEventData eventData)
{
wcp.forwardDragEvent(eventData);
}
public void OnPointerDown(PointerEventData eventData)
{
wcp.forwardPointerDownEvent(eventData);
}
public void OnPointerUp(PointerEventData eventData)
{
wcp.forwardPointerUpEvent(eventData);
}
}
_
3。_EventUnBlocker.cs
_-非表示のImage
が送信することでブロックしている光線のブロックを解除しますその上のオブジェクトへの偽のイベント。 UI、2D、または3Dコライダーである。
_public class EventUnBlocker : MonoBehaviour
{
List<GraphicRaycaster> grRayCast = new List<GraphicRaycaster>(); //UI
List<Physics2DRaycaster> phy2dRayCast = new List<Physics2DRaycaster>(); //Collider 2D (Sprite Renderer)
List<PhysicsRaycaster> phyRayCast = new List<PhysicsRaycaster>(); //Normal Collider(3D/Mesh Renderer)
List<RaycastResult> resultList = new List<RaycastResult>();
//For Detecting button click and sending fake Button Click to UI Buttons
Dictionary<int, GameObject> pointerIdToGameObject = new Dictionary<int, GameObject>();
// Use this for initialization
void Start()
{
}
public void sendArtificialUIEvent(Component grRayCast, PointerEventData eventData, PointerEventType evType)
{
//Route to all Object in the RaycastResult
for (int i = 0; i < resultList.Count; i++)
{
/*Do something if it is NOT this GameObject.
We don't want any other detection on this GameObject
*/
if (resultList[i].gameObject != this.gameObject)
{
//Check if this is UI
if (grRayCast is GraphicRaycaster)
{
//Debug.Log("UI");
routeEvent(resultList[i], eventData, evType, true);
}
//Check if this is Collider 2D/SpriteRenderer
if (grRayCast is Physics2DRaycaster)
{
//Debug.Log("Collider 2D/SpriteRenderer");
routeEvent(resultList[i], eventData, evType, false);
}
//Check if this is Collider/MeshRender
if (grRayCast is PhysicsRaycaster)
{
//Debug.Log("Collider 3D/Mesh");
routeEvent(resultList[i], eventData, evType, false);
}
}
}
}
//Creates fake PointerEventData that will be used to make PointerEventData for the callback functions
PointerEventData createEventData(RaycastResult rayResult)
{
PointerEventData fakeEventData = new PointerEventData(EventSystem.current);
fakeEventData.pointerCurrentRaycast = rayResult;
return fakeEventData;
}
private void routeEvent(RaycastResult rayResult, PointerEventData eventData, PointerEventType evType, bool isUI = false)
{
bool foundKeyAndValue = false;
GameObject target = rayResult.gameObject;
//Make fake GameObject target
PointerEventData fakeEventData = createEventData(rayResult);
switch (evType)
{
case PointerEventType.Drag:
//Send/Simulate Fake OnDrag event
ExecuteEvents.Execute<IDragHandler>(target, fakeEventData,
ExecuteEvents.dragHandler);
break;
case PointerEventType.Down:
//Send/Simulate Fake OnPointerDown event
ExecuteEvents.Execute<IPointerDownHandler>(target,
fakeEventData,
ExecuteEvents.pointerDownHandler);
//Code Below is for UI. break out of case if this is not UI
if (!isUI)
{
break;
}
//Prepare Button Click. Should be sent in the if PointerEventType.Up statement
Button buttonFound = target.GetComponent<Button>();
//If pointerId is not in the dictionary add it
if (buttonFound != null)
{
if (!dictContains(eventData.pointerId))
{
dictAdd(eventData.pointerId, target);
}
}
//Bug in Unity with GraphicRaycaster and Toggle. Have to use a hack below
//Toggle Toggle component
Toggle toggle = null;
if ((target.name == "Checkmark" || target.name == "Label") && toggle == null)
{
toggle = target.GetComponentInParent<Toggle>();
}
if (toggle != null)
{
//Debug.LogWarning("Toggled!: " + target.name);
toggle.isOn = !toggle.isOn;
//Destroy(toggle.gameObject);
}
break;
case PointerEventType.Up:
//Send/Simulate Fake OnPointerUp event
ExecuteEvents.Execute<IPointerUpHandler>(target,
fakeEventData,
ExecuteEvents.pointerUpHandler);
//Code Below is for UI. break out of case if this is not UI
if (!isUI)
{
break;
}
//Send Fake Button Click if requirement is met
Button buttonPress = target.GetComponent<Button>();
/*If pointerId is in the dictionary, check
*/
if (buttonPress != null)
{
if (dictContains(eventData.pointerId))
{
//Check if GameObject matches too. If so then this is a valid Click
for (int i = 0; i < resultList.Count; i++)
{
GameObject tempButton = resultList[i].gameObject;
if (tempButton != this.gameObject && dictContains(eventData.pointerId, tempButton))
{
foundKeyAndValue = true;
//Debug.Log("Button ID and GameObject Match! Sending Click Event");
//Send/Simulate Fake Click event to the Button
ExecuteEvents.Execute<IPointerClickHandler>(tempButton,
new PointerEventData(EventSystem.current),
ExecuteEvents.pointerClickHandler);
}
}
}
}
break;
}
//Remove pointerId since it exist
if (foundKeyAndValue)
{
dictRemove(eventData.pointerId);
}
}
void routeOption(PointerEventData eventData, PointerEventType evType)
{
UpdateRaycaster();
if (WholeScreenPointer.Instance.simulateUIEvent)
{
//Loop Through All GraphicRaycaster(UI) and throw Raycast to each one
for (int i = 0; i < grRayCast.Count; i++)
{
//Throw Raycast to all UI elements in the position(eventData)
grRayCast[i].Raycast(eventData, resultList);
sendArtificialUIEvent(grRayCast[i], eventData, evType);
}
//Reset Result
resultList.Clear();
}
if (WholeScreenPointer.Instance.simulateCollider2DEvent)
{
//Loop Through All Collider 2D (Sprite Renderer) and throw Raycast to each one
for (int i = 0; i < phy2dRayCast.Count; i++)
{
//Throw Raycast to all UI elements in the position(eventData)
phy2dRayCast[i].Raycast(eventData, resultList);
sendArtificialUIEvent(phy2dRayCast[i], eventData, evType);
}
//Reset Result
resultList.Clear();
}
if (WholeScreenPointer.Instance.simulateColliderEvent)
{
//Loop Through All Normal Collider(3D/Mesh Renderer) and throw Raycast to each one
for (int i = 0; i < phyRayCast.Count; i++)
{
//Throw Raycast to all UI elements in the position(eventData)
phyRayCast[i].Raycast(eventData, resultList);
sendArtificialUIEvent(phyRayCast[i], eventData, evType);
}
//Reset Result
resultList.Clear();
}
}
public void routeDragEvent(PointerEventData eventData)
{
routeOption(eventData, PointerEventType.Drag);
}
public void routePointerDownEvent(PointerEventData eventData)
{
routeOption(eventData, PointerEventType.Down);
}
public void routePointerUpEvent(PointerEventData eventData)
{
routeOption(eventData, PointerEventType.Up);
}
public void UpdateRaycaster()
{
convertToList(FindObjectsOfType<GraphicRaycaster>(), grRayCast);
convertToList(FindObjectsOfType<Physics2DRaycaster>(), phy2dRayCast);
convertToList(FindObjectsOfType<PhysicsRaycaster>(), phyRayCast);
}
//To avoid ToList() function
void convertToList(GraphicRaycaster[] fromComponent, List<GraphicRaycaster> toComponent)
{
//Clear and copy new Data
toComponent.Clear();
for (int i = 0; i < fromComponent.Length; i++)
{
toComponent.Add(fromComponent[i]);
}
}
//To avoid ToList() function
void convertToList(Physics2DRaycaster[] fromComponent, List<Physics2DRaycaster> toComponent)
{
//Clear and copy new Data
toComponent.Clear();
for (int i = 0; i < fromComponent.Length; i++)
{
toComponent.Add(fromComponent[i]);
}
}
//To avoid ToList() function
void convertToList(PhysicsRaycaster[] fromComponent, List<PhysicsRaycaster> toComponent)
{
//Clear and copy new Data
toComponent.Clear();
for (int i = 0; i < fromComponent.Length; i++)
{
toComponent.Add(fromComponent[i]);
}
}
//Checks if object is in the dictionary
private bool dictContains(GameObject obj)
{
return pointerIdToGameObject.ContainsValue(obj);
}
//Checks if int is in the dictionary
private bool dictContains(int pointerId)
{
return pointerIdToGameObject.ContainsKey(pointerId);
}
//Checks if int and object is in the dictionary
private bool dictContains(int pointerId, GameObject obj)
{
return (pointerIdToGameObject.ContainsKey(pointerId) && pointerIdToGameObject.ContainsValue(obj));
}
//Adds pointerId and its value to dictionary
private void dictAdd(int pointerId, GameObject obj)
{
pointerIdToGameObject.Add(pointerId, obj);
}
//Removes pointerId and its value from dictionary
private void dictRemove(int pointerId)
{
pointerIdToGameObject.Remove(pointerId);
}
public enum PointerEventType
{
Drag, Down, Up
}
}
_
使用法:
1。空のゲームオブジェクトまたはカメラにWholeScreenPointer
スクリプトをアタッチします。
2シーン内のイベントを受信するには、任意のスクリプトにIDragHandler
、IPointerDownHandler
、IPointerUpHandler
を実装してから、WholeScreenPointer.Instance.registerGameObject(this.gameObject);
を1回呼び出します。画面からのイベントはすべてそのスクリプトに送信されます。 OnDisable()
関数で登録を解除することを忘れないでください。
たとえば、タッチイベントを受信する任意のGameObjectにTest
をアタッチします。
_public class Test : MonoBehaviour, IDragHandler, IPointerDownHandler, IPointerUpHandler
{
void Start()
{
//Register this GameObject so that it will receive events from WholeScreenPointer script
WholeScreenPointer.Instance.registerGameObject(this.gameObject);
}
public void OnDrag(PointerEventData eventData)
{
Debug.Log("Dragging: ");
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("Pointer Down: ");
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("Pointer Up: ");
}
void OnDisable()
{
WholeScreenPointer.Instance.unRegisterGameObject(this.gameObject);
}
}
_
[〜#〜]ノート[〜#〜]:
画面上の任意の場所でイベントを受信する場合は、WholeScreenPointer.Instance.registerGameObject(this.gameObject);
を呼び出すだけです。現在のオブジェクトからイベントを受け取るだけの場合は、これを呼び出す必要はありません。その場合、複数のイベントを受け取ります。
その他の重要な機能:
WholeScreenイベントを有効にする-WholeScreenPointer.Instance.enablewholeScreenPointer(true);
WholeScreenイベントを無効にする-WholeScreenPointer.Instance.enablewholeScreenPointer(false);
最後に、これをさらに改善できます。