Jump to content
Unity Insider Forum

Leaderboard

Popular Content

Showing content with the highest reputation since 04/24/2022 in all areas

  1. Jeah, nach gut 20 Stunden Arbeit bin ich nun fertig und es funktioniert völlig fehlerfrei. Hätte ich nie gedacht und wollte schon aufgeben 😂 ☺️ Wer möchte kann das Script gerne nutzen, vielleicht hat ja auch noch jemand bedarf an sowas. Dazu einfach das Input Script dem EventSystem unter das "Input System UI Input Module"(Wichtig, da darf nichts anderes dazwischen sein) geben und die Tags "Horizontal Menu" und "Vertical Menu" hinzufügen und den entsprechenden Panels zuweisen. Das InputModule, welches man erstellt muss man entweder umbenennen in InputManager, oder in Script InputSO alle "InputManger" durch was anderes ersetzen. Das gleich gilt auf für die ActionMaps. Bei mehr als einer wird man allerdings noch mehr Anpassungen vornehmen müssen, sofern diese die Funktionalität auch benötigen. Wenn noch jemand Anmerkungen und Verbesserungen hat, gerne her damit 😁 Input.cs using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.InputSystem.UI; using UnityEngine.UI; internal struct NavigationModel { public Vector2 move; public int consecutiveMoveCount; public MoveDirection lastMoveDirection; public float lastMoveTime; public AxisEventData eventData; public void Reset() { move = Vector2.zero; } } public class Input : BaseInputModule { public InputSO inputSO; private NavigationModel m_NavigationState; private string parentTag; private bool isDynamicList; protected override void OnEnable() { base.OnEnable(); inputSO.moveVector += SetInputDirection; inputSO.navigate += CheckDynamicListObject; inputSO.submit += SetParentOnSubmit; } protected override void OnDisable() { base.OnDisable(); inputSO.moveVector -= SetInputDirection; inputSO.navigate -= CheckDynamicListObject; inputSO.submit -= SetParentOnSubmit; } public void OnClick() { eventSystem.SetSelectedGameObject(eventSystem.firstSelectedGameObject); } private void ProcessNavigation(ref NavigationModel navigationState) { var usedSelectionChange = false; if (eventSystem.currentSelectedGameObject != null) { var data = GetBaseEventData(); ExecuteEvents.Execute(EventSystem.current.currentSelectedGameObject, data, ExecuteEvents.updateSelectedHandler); usedSelectionChange = data.used; } if (!eventSystem.sendNavigationEvents) return; var movement = navigationState.move; if (!usedSelectionChange && (!Mathf.Approximately(movement.x, 0f) || !Mathf.Approximately(movement.y, 0f))) { var time = Time.unscaledTime; var moveVector = navigationState.move; var moveDirection = MoveDirection.None; if (moveVector.sqrMagnitude > 0) { if(parentTag == "Horizontal Menu") { if (Mathf.Abs(moveVector.x) > Mathf.Abs(moveVector.y)) moveDirection = moveVector.x > 0 ? MoveDirection.Right : MoveDirection.Left; } else if (parentTag == "Vertical Menu") { if (Mathf.Abs(moveVector.x) < Mathf.Abs(moveVector.y)) moveDirection = moveVector.y > 0 ? MoveDirection.Up : MoveDirection.Down; } else if (Mathf.Abs(moveVector.x) > Mathf.Abs(moveVector.y)) moveDirection = moveVector.x > 0 ? MoveDirection.Right : MoveDirection.Left; else moveDirection = moveVector.y > 0 ? MoveDirection.Up : MoveDirection.Down; } if (moveDirection != m_NavigationState.lastMoveDirection) m_NavigationState.consecutiveMoveCount = 0; if (moveDirection != MoveDirection.None) { var allow = true; if (m_NavigationState.consecutiveMoveCount != 0) { if (m_NavigationState.consecutiveMoveCount > 1) allow = time > m_NavigationState.lastMoveTime + GetComponent<InputSystemUIInputModule>().moveRepeatRate; else allow = time > m_NavigationState.lastMoveTime + GetComponent<InputSystemUIInputModule>().moveRepeatDelay; } if (allow) { Selectable newBtn = eventSystem.currentSelectedGameObject.GetComponent<Selectable>().FindSelectable(moveVector); if (newBtn.transform.parent.tag != parentTag) return; var eventData = m_NavigationState.eventData; if (eventData == null) { eventData = new AxisEventData(eventSystem); m_NavigationState.eventData = eventData; } eventData.Reset(); eventData.moveVector = moveVector; eventData.moveDir = moveDirection; ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, eventData, ExecuteEvents.moveHandler); usedSelectionChange = eventData.used; m_NavigationState.consecutiveMoveCount = m_NavigationState.consecutiveMoveCount + 1; m_NavigationState.lastMoveTime = time; m_NavigationState.lastMoveDirection = moveDirection; } } else m_NavigationState.consecutiveMoveCount = 0; } else m_NavigationState.consecutiveMoveCount = 0; if (!usedSelectionChange && EventSystem.current.currentSelectedGameObject != null) { var submitAction = GetComponent<InputSystemUIInputModule>().submit?.action; var cancelAction = GetComponent<InputSystemUIInputModule>().cancel?.action; var data = GetBaseEventData(); if (cancelAction != null && cancelAction.WasPressedThisFrame()) ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.cancelHandler); if (!data.used && submitAction != null && submitAction.WasPressedThisFrame()) ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, data, ExecuteEvents.submitHandler); } } public override void Process() { ProcessNavigation(ref m_NavigationState); if (parentTag != "Horizontal Menu" && parentTag != "Vertical Menu") { parentTag = eventSystem.currentSelectedGameObject.transform.parent.tag; UnityEditorInternal.ComponentUtility.MoveComponentDown(this); isDynamicList = false; } } public void SetInputDirection(Vector2 moveVector) { m_NavigationState.move = moveVector; } public void CheckDynamicListObject() { parentTag = eventSystem.currentSelectedGameObject.transform.parent.tag; if (!isDynamicList) { if (parentTag == "Horizontal Menu" || parentTag == "Vertical Menu") { isDynamicList = true; UnityEditorInternal.ComponentUtility.MoveComponentUp(this); } } } public void SetParentOnSubmit() { parentTag = eventSystem.currentSelectedGameObject.transform.parent.tag; } } InputSO.cs using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; [CreateAssetMenu(fileName = "AdvancedInput")] public class InputSO : ScriptableObject, InputManager.IMenuActions { public InputManager InputManager; public event UnityAction navigate; public event UnityAction<Vector2> moveVector; public event UnityAction submit; private void OnEnable() { if (InputManager == null) InputManager = new InputManager(); InputManager.Menu.SetCallbacks(this); InputManager.Menu.Enable(); } private void OnDisable() { InputManager.Menu.Disable(); } public void OnCancel(InputAction.CallbackContext context) { //throw new System.NotImplementedException(); } public void OnNavigate(InputAction.CallbackContext context) { navigate?.Invoke(); moveVector?.Invoke(context.ReadValue<Vector2>()); } public void OnSubmit(InputAction.CallbackContext context) { submit?.Invoke(); } }
    2 points
  2. Hat nix mit Generic zu tun, aber Mecanim scheint das in der Tat nicht zu wollen. Der korrekte Weg wäre, einfach eine Animation zu erstellen, die von Anfang bis Ende genau das tut, was du willst, statt eine halbe Animation zu haben und dann das Animationssystem den Rest auffüllen zu lassen. Falls das aber gerade nicht drin ist, hast du hier einen Workaround.
    1 point
  3. Hallo, ich möchte euch ein kleines Video meines Projektes zeigen. Wo stehe ich im Moment? Jack erhält zu Beginn des Spiels eine Begrüßung von Fuchs Eddi, ein paar Anweisungen und seine erste Aufgabe. Dabei geht es erstmal nur um das Anbauen und Ernten von Maiskolben.
    1 point
  4. Im englisch-sprachigen Unity-Forum habe ich folgende Antwort auf mein Problem bekommen, die ich euch nicht vorenthalten möchte: "A hacked together way we allowed for pdf exports on our WebGL app was to have a .jslib file that generates the information we wanted (text and images) onto the webpage below the unity container. That information was encapsulated in an HTML element and then we generate a "Print" button that will use the browser's print dialogue to print only that element. Not elegant in the least, but does what we need it to do." Quelle: Englischer Post Das ganze hat funktioniert und reicht auch erstmal für meine Zwecke aus.
    1 point
  5. Hallo, jedes RPG Spiel benötigt an einer bestimmten Stelle ein Dungeon. Also habe ich mich heute mal rangemacht und einen Dungeon erstellt. Der Spieler muss durch diesen hindurchlaufen, da der eigentliche Weg an der Oberfläche durch einen Erdrutsch verschüttet wurde. Das Labyrinth ist noch nicht komplett fertig. Es fehlt noch an Interieur und Gegnern. Des Weiteren sind viele Gänge versperrt und müssen durch Schlüssel, die der Spieler finden muss, versperrt.
    1 point
  6. Hi Erst mal danke für den Beitrag. Ich habe nun Zugriff zum Dateisystem. Ich musste in der AndroidManifest.xml im Application-Tag noch folgendes ergänzen: <application android:requestLegacyExternalStorage="true"> Ich kann nun auf das Dateisystem zugreifen, wenn ich den Pfad direkt anspreche (/storage/emulated/0/) aber der Pfad "/storage/emulated/" ist immer noch leer. Android mag das einfach nicht so, wenn man direkt im Filesystem rumwurstelt. Deshalb habe ich nach einer Lösung gesucht und nun das kostenlose "Runtime File Browser" entdeckt. War in 5 Minuten implementiert und funktioniert perfekt. Jetzt habe ich einfach meinen eigenen File Browser mit diesem ersetzt. Ich hatte noch das Problem, keine Zugriff auf die Files auf der SD-Karte zu haben. Da ist Android auch irgendwie empfindlich. Trotz den Berechtigungen. Android mag es einfach nicht, wenn man Dateien umbenennt oder verschiebt (ist ja das selbe). Deshalb habe ich das ganze jetzt so geändert, dass ich die Datei auch nicht mehr umbenennen muss (hab vorher an den Dateinamen eine ID gehängt, damit die Datei wieder erkannt werden kann, falls der User sie verschiebt). Jetzt läuft alles gut 😃
    1 point
  7. Hallo, heute möchte ich euch ein kleines Video vom Fantasiewald und ein paar neue Skills zeigen. Zwei neue Gegner (Steingolem und Ent) sind auch schon dabei. Download der Version 0.2.0: http://https//www.pchobbyspieleschmiede.de/orfaya/Orfaya%200.2.0.zip
    1 point
  8. Physics2D.Raycast ist ein 2D-Raycast. Es ist nicht einfach ein 3D-Raycast, der Collider2D treffen kann. Es ist ein Strahl, der innerhalb der 2D-Physik-Ebene etwas treffen kann. Wenn du eine perspektivische Kamera hast und dann damit schauen willst, wo auf einer imaginären Ebene du bist, dann kannst du dafür den Plane.Raycast nehmen. Damit findest du dann den Punkt auf der 2D-Physik-Ebene und kannst mit Physics2D.OverlapPoint schauen, ob da ein Collider2D an diesem Punkt ist. if (Input.GetMouseButtonDown(0)) { var ray = cam.ScreenPointToRay(Input.mousePosition); var physicsPlane = new Plane(Vector3.forward, Vector3.zero); if (physicsPlane.Raycast(ray, out var distance)) { var hitPoint = ray.GetPoint(distance); var collider = Physics2D.OverlapPoint(hitPoint); if (collider) { Debug.Log(collider); } } }
    1 point
  9. Von der Logik her müssten die Static Variablen der sparsamste Weg sein, denn die sind immer an der selben Stelle im Speicher. Sie belegen aber auch immer ihren Platz, egal ob sie gebraucht werden, oder nicht. Es ist doch so, dass ein Szenenwechsel ja den alten Kram verwirft und alles neu einlädt, was in der neuen Szene jetzt nötig ist. Ein Scriptable Object, was ja an ein Script gebunden ist, wird mit dem Script neu eingeladen / verknüpft. Ein Singleton, was den Szenenwechsel überlebt, bleibt im Speicher. Aber wahrscheinlich wird in jeder Szene ein Singelton geladen (damit es beim laden einer bestimmten Szene auch da ist), was dann schaut ob es einzigartig ist und wenn nicht sich wieder zerstören würde. Da passiert also noch viel mehr als nur ein Einladen und das kostet alles eine gewisse Zeit. Hier und da würden also Daten neu eingelesen und in den Speicher geschoben werden. Nur von wo werden sie eingeladen? Sind sie nicht vielleicht schon längst im Speicher, weil die Engine weiß, dass sie fürs Spiel gebraucht werden? Ich weiß nicht, wie weit die Engine optimiert ist. Was relativ langsam ist, ist ja das Laden von einem mechanischen Laufwerk. Alles Andere geht so schnell, dass du keinen Unterschied feststellen wirst. Und wenn deine neue Szene nur eine einzige Textur oder einen Sound laden muss, die/der vorher noch nicht da war, dann sind deine paar Daten in den Variablen völlig nebensächlich.
    1 point
  10. Hallo Ich weiß es nicht, halte es für nicht wichtig, würde aber in deinem Fall den Profiler anwerfen. Christoph
    1 point
  11. Moin! Raycast will einen Richtungsvektor haben, aber Input.mousePosition ist die Position des Mauszeigers auf dem Bildschirm... in Pixeln. Das passt so gar nicht zusammen. Was du brauchst, ist eine Funktion, die dir die Mausposition in einen Kamera-Richtungsvektor umrechnet. Und die heißt Camera.ScreenPointToRay. Da kriegst du nicht nur den Richtungsvektor, sondern direkt den ganzen Ray in die Hand. Insgesamt sieht das so aus: var ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out var hit)) { Debug.Log("getroffen"); } Ich hab die Deklaration der hit-Variable auch direkt in den Methodenaufruf gezogen.
    1 point

Announcements

Hy, wir programmieren für dich Apps(Android & iOS):

Weiterleitung zum Entwickler "daubit"



×
×
  • Create New...