Jump to content
Unity Insider Forum
Garzec

'InvalidOperationException' thrown from state change monitor 'InputActionState' on 'Vector2:/Mouse/position'

Recommended Posts

Ich habe ein neues Projekt angelegt und das neue Input System installiert. Ich möchte einfach nur die Klick (Desktop)/Tap (Mobile) Position abspeichern.
 
Ich weiß, dass das alte System schon etwas liefert
 
 
Ich möchte es aber mit dem neuen System umsetzen. Hier meine Input Map Konfiguration
 
O62dt.png
 
aqKzt.png
 
qnxBy.png
 
WlXoV.png
 
qoPma.png
 
ikLuX.png
 
Nds8N.png
 
Hier ein Script für Tests
 
public class FooBar : MonoBehaviour
{
    public void Select(InputAction.CallbackContext context)
    {
        Vector2 selectPosition = context.ReadValue<Vector2>();
        Debug.Log($"Select position is: {selectPosition.x}|{selectPosition.y}");
    }
}

In der Szene habe ich dann ein leeres GameObject dahingehend konfiguriert

JtQSH.png
 
Leider bekomme ich im PlayMode jedes mal, wenn ich die Maus bewege, folgende Fehler:
 
cmnPp.png 
Ich schätze mal, dass meine Input Konfiguration falsch ist.
 
Weiß jemand, wie man die Input Map dahingehend konfiguriert, dass man entweder bei einem Klick oder einem Tap die Position durchgereicht bekommt?
  • Like 1

Share this post


Link to post
Share on other sites

Sehr schöner Post mit vielen Infos, sieht man auch nicht alle Tage :)

Leider kann ich nicht genau sagen... oder auch nur vernünftig vermuten, was da los ist.

Deine Zeile will ja eindeutig einen Vector2 haben und kein float. Wenn du die zweite Fehlermeldung anklickst und dir in der Konsole den Stacktrace ansiehst, hast du nicht zufällig genügend Schritte, um zu schauen, wo da Code nach einem float-Wert fragt?

Share this post


Link to post
Share on other sites

verstehe ich das richtig dass du einen Mauscklick erfassen willst und seine Position in einer variable Speichern willst? wenn das alles ist brauchst du nur folgende Line:

Vector2 selectedPosition = Camera.main.ScreenToWorldPoint(Mouse.current.position.ReadValue());

zumindest Klappt das für die Maus. mit Touchscreen hab ich mich nicht befasst aber da gibts safe auch eine Methode die ähnlich aussieht. Musst dafür auch keine Actions für deine Map festlegen aber würde sich je nachdem anbieten wenn du verschiedene Controls benutzt.

 

Edit: für den Touchscreen wäre das Äquivalent wohl:

Vector2 selectedPosition = Camera.main.ScreenToWorldPoint(Touchscreen.current.position.ReadValue());

bzw 

Vector2 selectedPosition = Camera.main.ScreenToWorldPoint(Touchscreen.current.startPosition.ReadValue());

wenn du nur die Position des Fingers brauchst als du den Touchscreen das erste mal berührt hast. (ändert sich nicht wenn du den Finger bewegst wärend Touch.

Das ganze kannst du auch hier nachlesen: https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Touch.html

 

Share this post


Link to post
Share on other sites

@Sascha

Hier der Stacktrace von der zweiten Meldung, lässt mich aber leider nicht schlauer werden

Zitat

InvalidOperationException: Cannot read value of type 'float' from control '/Mouse/position' bound to action 'Player/Select[/Mouse/position,/Mouse/position]' (control is a 'Vector2Control' with value type 'Vector2')
UnityEngine.InputSystem.InputActionState.ReadValue[TValue] (System.Int32 bindingIndex, System.Int32 controlIndex, System.Boolean ignoreComposites) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputActionState.cs:2038)
UnityEngine.InputSystem.InputActionState.ReadCompositePartValue[TValue,TComparer] (System.Int32 bindingIndex, System.Int32 partNumber, System.Boolean* buttonValuePtr, System.Int32& controlIndex, TComparer comparer) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputActionState.cs:2101)
UnityEngine.InputSystem.InputBindingCompositeContext.ReadValueAsButton (System.Int32 partNumber) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputBindingCompositeContext.cs:252)
UnityEngine.InputSystem.Composites.ButtonWithOneModifier.ReadValue (UnityEngine.InputSystem.InputBindingCompositeContext& context) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/Composites/ButtonWithOneModifier.cs:84)
UnityEngine.InputSystem.Composites.ButtonWithOneModifier.EvaluateMagnitude (UnityEngine.InputSystem.InputBindingCompositeContext& context) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/Composites/ButtonWithOneModifier.cs:97)
UnityEngine.InputSystem.InputActionState.ComputeMagnitude (System.Int32 bindingIndex, System.Int32 controlIndex) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputActionState.cs:1914)
UnityEngine.InputSystem.InputActionState.IsActuated (UnityEngine.InputSystem.InputActionState+TriggerState& trigger, System.Single threshold) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputActionState.cs:1886)
UnityEngine.InputSystem.InputInteractionContext.ControlIsActuated (System.Single threshold) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputInteractionContext.cs:85)
UnityEngine.InputSystem.Interactions.PressInteraction.Process (UnityEngine.InputSystem.InputInteractionContext& context) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/Interactions/PressInteraction.cs:63)
UnityEngine.InputSystem.InputActionState.ProcessInteractions (UnityEngine.InputSystem.InputActionState+TriggerState& trigger, System.Int32 interactionStartIndex, System.Int32 interactionCount) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputActionState.cs:1335)
UnityEngine.InputSystem.InputActionState.ProcessControlStateChange (System.Int32 mapIndex, System.Int32 controlIndex, System.Int32 bindingIndex, System.Double time, UnityEngine.InputSystem.LowLevel.InputEventPtr eventPtr) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputActionState.cs:933)
UnityEngine.InputSystem.InputActionState.UnityEngine.InputSystem.LowLevel.IInputStateChangeMonitor.NotifyControlStateChanged (UnityEngine.InputSystem.InputControl control, System.Double time, UnityEngine.InputSystem.LowLevel.InputEventPtr eventPtr, System.Int64 mapControlAndBindingIndex) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/Actions/InputActionState.cs:833)
UnityEngine.InputSystem.InputManager.FireStateChangeNotifications (System.Int32 deviceIndex, System.Double internalTime, UnityEngine.InputSystem.LowLevel.InputEvent* eventPtr) (at Library/PackageCache/com.unity.inputsystem@1.0.1/InputSystem/InputManager.cs:2914)
UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr) (at /home/bokken/buildslave/unity/build/Modules/Input/Private/Input.cs:120)

image.thumb.png.535d38602aa4be1a2ee05331dd345602.png

Share this post


Link to post
Share on other sites

@Brighthell96

vielen Dank für den Ansatz! :) Leider habe ich dort Probleme, die mir Unity schon lösen würde

1. Ich muss selbst noch Code schreiben, auf welcher Plattform ich mich gerade befinde

2. Das Ganze ist nicht eventbasiert, das heißt, ich würde im Update 1x pro Frame den Wert abfragen, was nicht notwendig ist, wenn mir Unity ein Event triggern kann

Share this post


Link to post
Share on other sites

Es wäre nicht so schwer, das selber zu coden, aber ich bin da ganz bei dir: Wenn man das krasse-dolle-neue Input-System schon benutzt, dann soll das gefälligst auch den gesamten Input erledigen.

Der Stacktrace bietet tatsächlich leider nicht wirklich eine Lösung - aber man kann sehen, dass da nirgendwo Code aus deinem Projekt drin ist, sondern alles aus UnityEngine.Blub kommt. Das heißt, dass da entweder ein Bug drinsteckt oder deine Einstellung im Input-Fenster schlecht sind - wobei diese Fehlermeldung ohne Aufschluss über das Problem wiederum ein Fehler auf Unitys Seite wäre.

So oder so weist der Stacktrace darauf hin, dass noch andere das Problem haben dürften, und siehe da:

https://stackoverflow.com/questions/58469484/cannot-read-value-of-type-float-from-control

Ist da ein Hinweis dabei, der dir hilft? Obwohl du alles so sorgfältig gepostet hast, steige ich durch das UI vom Inputsystem nie durch... muss man wohl mal selber richtig benutzt haben :D

Share this post


Link to post
Share on other sites
vor 47 Minuten schrieb Garzec:

2. Das Ganze ist nicht eventbasiert, das heißt, ich würde im Update 1x pro Frame den Wert abfragen, was nicht notwendig ist, wenn mir Unity ein Event triggern kann

okay das stimmt natürlich. aber du hast ja bereits eine Action auf deiner Map die du per event triggern kannst:

public void Select(InputAction.CallbackContext context)
    {
		if(//Device ist Maus) {
        	Vector2 selectedPosition = Camera.main.ScreenToWorldPoint(Mouse.current.position.ReadValue());
       		Debug.Log($"Select position is: {selectPosition.x}|{selectPosition.y}");
		}
		else if(//Device ist Touchscreen) {
			Vector2 selectedPosition = Camera.main.ScreenToWorldPoint(Touchscreen.current.position.ReadValue());
       		Debug.Log($"Select position is: {selectPosition.x}|{selectPosition.y}");	
		}
    }

 

Share this post


Link to post
Share on other sites

@Sascha

Ich sehe den Fehler erst einmal bei meiner Konfiguration. Ich werde das Ganze nochmal konfigurieren, muss aber gestehen, dass ich das System als Neuling gar nicht so einfach zu konfigurieren finde.

 

@Brighthell96

Das stimmt zwar alles, aber im Code möchte ich nicht mehr wissen, von wo der Input kommt :) Wenn Unity das alles schon kann, dann muss ich selbst weniger Code warten / Tests schreiben :) 

Share this post


Link to post
Share on other sites

Ich habe als Grundlage erstmal dieses Video hier genommen

 

und dann eben versucht die "Jump" Funktion zu erweitern. Jump muss ja keine Daten durchreichen, bei mir muss halt noch der V2 durchgereicht werden.

Share this post


Link to post
Share on other sites

hast du es mal mit "passh through" probiert? funktioniert wunderbar bei mir. Hier die Klasse:

public class FooBar : MonoBehaviour, InputManager.IMouseClickTestActions {

    private InputManager input;

    void Awake() {
        input = new InputManager();
        input.MouseClickTest.SetCallbacks(this);
    }

    public void OnClick(InputAction.CallbackContext context) {
            Vector2 selectPosition = Camera.main.ScreenToWorldPoint(context.ReadValue<Vector2>());
        Debug.Log($"Select position is: {selectPosition.x}|{selectPosition.y}");
    }

    private void OnEnable() {
        input.MouseClickTest.Enable();
    }

    private void OnDisable() {
        input.MouseClickTest.Disable();
    }
}

(das Interface heißt natürlich anders bei dir) dasselbe kannst du natürlich auch über die Player Input Component machen anstatt über das interface. mir ist das interface einfach lieber.

Unbenannt.thumb.PNG.80d41b702defdefd98f8ab0a64c43f5c.PNG

Share this post


Link to post
Share on other sites

Leider passt das nicht ganz....

1. Das wäre jetzt nur für die Maus, auf Mobile müsste es ja anders sein
2. Jetzt wird das Event durchgehend getriggert. Ich möchte das Event ja nur auslösen, wenn tatsächlich geklickt / getappt wurde

Aber danke :)

Share this post


Link to post
Share on other sites

@Brighthell96 nein, noch nicht. Da ich das Input System nur dafür brauche, sieht mein momentaner Schlachtplan wie folgt aus...

Das Ganze wird mit dem alten System umgesetzt, das heißt, ich prüfe 1x pro Update, auf welcher Plattform ich mich befinde, je nachdem ziehe ich mir dann den Vector2 und überschreibe die Variable.

Schlechte Lösung, ist aber klein und hat keine Abhängigkeiten. Besser (sobald Lösung da ist):

- Neues Input System installieren

- Klick/Tap für Desktop/Mobile konfigurieren

- Update Code komplett wegwerfen

- Select Methode als Event Handler definieren

Damit ist mir dann die Plattform egal und der Code läuft nur, wenn er tatsächlich gebraucht wird :)

Share this post


Link to post
Share on other sites
vor 2 Stunden schrieb Garzec:

ich prüfe 1x pro Update, auf welcher Plattform ich mich befinde

Ich bin gerade mit dem Kopf nicht in dem Problem drin, aber bei der Aussage gilt generell: Das muss man nie. Man kann dem Compiler sagen, dass er beim Android-Build bitte diesen Code und beim Windows-Build einen anderen usw. kompilieren soll.

#if UNITY_ANDROID || UNITY_IOS
  DoTouchStuff();
#elif UNITY_STANDALONE
  DoMouseStuff();
#endif

Das kannst du überall im Code machen. Damit kannst du Zeilen, ganze Methoden oder gar ganze Klassen aus deinem Code rausschmeißen lassen, wenn die Bedingung nicht erfüllt ist. Hier hast du eine schöne Liste mit all den Flags, die Unity für dich hat: https://docs.unity3d.com/Manual/PlatformDependentCompilation.html

Share this post


Link to post
Share on other sites

Stimmt, ganz vergessen. Geht auch :)

Wobei mein oberstes TODO ist diesen Code natürlich komplett rauszuwerfen, da man es mit dem neuen Input System einfacher und performanter haben kann 👍

Share this post


Link to post
Share on other sites

Hier nur mal zur Info, so sieht momentan der Workaround Code aus. Auch damit ihr mal sehen könnt, wie klein dieses "Feature" eigentlich ist, ich möchte es eben nur mit dem neuen Input System noch kleiner machen ;)

 

    public sealed class SelectedPositionStateController : MonoBehaviour
    {
        private void Update()
        {
#if UNITY_ANDROID || UNITY_IOS
            if (UnityEngine.Input.touchCount > 0)
            {
                Touch touch = UnityEngine.Input.GetTouch(0);

                // hier touch.position an meine ECS Simulation übergeben
            }
#elif UNITY_STANDALONE
            if (UnityEngine.Input.GetMouseButtonDown(0))
            {
                // hier UnityEngine.Input.mousePosition an meine ECS Simulation übergeben
            }
#endif
        }
    }

Weil den Code hier

public sealed class SelectedPositionStateController : MonoBehaviour
{
    public void Select(InputAction.CallbackContext context)
    {
        Vector2 selectedPosition = context.ReadValue<Vector2>();
        // hier selectedPosition an meine ECS Simulation übergeben
    }
}

Kann ich viel einfacher testen :P

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...