Jump to content
Unity Insider Forum

Kurumi-chan

Members
  • Posts

    24
  • Joined

  • Last visited

  • Days Won

    1

Kurumi-chan last won the day on May 7

Kurumi-chan had the most liked content!

About Kurumi-chan

  • Birthday 02/05/1998

Profile Information

  • Gender
    Female
  • Location
    NRW

Kurumi-chan's Achievements

Member

Member (2/3)

2

Reputation

  1. Hey, ich habe mal wieder ein Problem😕 Und zwar habe ich in der DB einige Optionen, die entscheiden ob manche Dinge angezeigt werden oder nicht, bzw. halt Daten, die ja dann auch irgendwie im Spiel verfügbar gemacht werden müssen. Dazu habe ich mir überlegt unteranderem Prefabs zu benutzen. Da ich jetzt aber auch faul bin möchte ich das ganze etwas dynamischer gestallten. Ich habe hierzu eine Funktion die das entsprechende Prefab läd, bzw. erstellt, falls nicht vorhanden. Das funktioniert auch alles soweit ganz gut, nur bekomme ich jetzt eine Performance Warnung und ich verstehe nicht warum. Die Warnung dazu lautet z. B. (habe die für jeden einzelnen Aufruf) Performance warning: There are more than 100 preview scenes. There might be code not releasing the preview scene after creating it. UnityEditor.PrefabUtility:LoadPrefabContents (string) Utility:LoadPrefab (string,string,UnityEngine.GameObject) (at Assets/Scripts/Utility.cs:94) TitleMenu:ShowSplashScreen () (at Assets/Scripts/Menus/TitleMenu/TitleMenu.cs:49) TitleMenu:Start () (at Assets/Scripts/Menus/TitleMenu/TitleMenu.cs:33) Die Funktion sieht wie folgt aus public static GameObject LoadPrefab(string prefab, string folder, GameObject obj = null) { string localPath = CheckFolder(folder) + prefab + ".prefab"; if (!File.Exists(localPath)) { obj = (obj != null) ? obj : new GameObject(); PrefabUtility.SaveAsPrefabAsset(obj, localPath); } return PrefabUtility.LoadPrefabContents(localPath); } private static string CheckFolder(string folder) { if (!Directory.Exists("Assets/Prefabs")) AssetDatabase.CreateFolder("Assets", "Prefabs"); if (folder != "" && !Directory.Exists("Assets/Prefabs/" + folder)) AssetDatabase.CreateFolder("Prefabs", folder); folder = (folder != "") ? folder + "/" : folder; return "Assets/Prefabs/" + folder; } Und aufgerufen wird das ganze dann // z.B. so private void ShowCopyright() { if (settings.ShowCopyright) { GameObject copy = new GameObject("Copyright"); copy.AddComponent<CanvasRenderer>(); GameObject go = new GameObject("CopyrightText"); go.transform.parent = copy.transform; go.AddComponent<CanvasRenderer>(); go.AddComponent<TextMeshProUGUI>(); go.GetComponent<TMP_Text>().text = settings.Copyright; Instantiate(Utility.LoadPrefab("CopyrightPrefab", "", copy), TitleMenuPanel.transform); Destroy(copy); Destroy(go); } } // oder so for (int i = 0; i < BGM.Count; i++) { GameObject audioObject = Instantiate(Utility.LoadPrefab("AudioPrefab", ""), transform.Find("BGM")); audioObject.name = BGM[i].Name; audioObject.AddComponent<AudioSource>(); audioObject.GetComponent<AudioSource>().loop = BGM[i].Loop; audioObject.GetComponent<AudioSource>().volume = BGM[i].Volume; audioObject.GetComponent<AudioSource>().pitch = BGM[i].Pitch; audioObject.GetComponent<AudioSource>().mute = BGM[i].Mute; audioObject.GetComponent<AudioSource>().panStereo = BGM[i].StereoPan; audioObject.GetComponent<AudioSource>().priority = BGM[i].Priority; audioObject.GetComponent<AudioSource>().playOnAwake = BGM[i].PlayOnAwake; audioObject.GetComponent<AudioSource>().clip = BGM[i].AudioClip; } // oder so if (AudioManager.Instance == null) { GameObject bgm = new GameObject("BGM"); GameObject sfx = new GameObject("SFX"); GameObject audioManager = new GameObject("Audio Manager"); audioManager.AddComponent<AudioManager>(); bgm.transform.parent = audioManager.transform; sfx.transform.parent = audioManager.transform; Utility.LoadPrefab("Audio Manager", "Manager", audioManager); AudioManager.Instance = audioManager.GetComponent<AudioManager>(); } Insgesamt, wenn man die Schleifen nicht mit einbezieht, wird die Funktion LoadPrefab() aktuell 7 mal aufgerufen. Wenn ich die Schleifen mit einbeziehe, dann 12 mal. Der Fehler wiederum wird aber nur 7 mal angezeigt, also auch nur einmal pro Schleifendurchlauf. Also vorher nimmt der über 100 Aufrufe??? Hoffe es hat jemand eine Idee. LG
  2. Hey Jog, das hätte ich jetzt nicht gedacht, dass man das über Animationen nicht ändern kann. Hatte daran bisher keinen Bedarf, deswegen noch nicht versucht. Aber gut zu wissen, dann brauch ichs auch gar nicht erst über Animationen versuchen beizeiten 😄
  3. Etwas besseres ist mir halt auch nicht eingefallen 😅 Und mit den Flags, bzw. dem Interface habe ich es nicht geschafft. Vor allem, da ich ja trotzdem irgendwann die Objekte wieder zerstören muss und ich dann ja doch wieder die Awake Methode aufrufe. Aber es hat natürlich jetzt auch den weiteren Vorteil, dass ich nicht jede Unterdatenbank von Hand erstellen muss. Also wieder ein wenig weniger Arbeit 😂 Lösche ja immer mal wieder die Dbs, um zu testen.
  4. Hey, könnte man nicht auch einfach eine Animation dafür hernehmen?
  5. Ok, das ist auch interessant. Damit kann ich sicherlich noch was anfangen 😁 Danke dir für diesen Hinweis. Habe es jetzt so gelöst, dass ich die Scriptable Objects gar nicht mehr selbst erstelle, sondern durch einen neuen Button im Editor. Der ist dann auch nur da, wenn es noch keine DB gibt. Der erstellt diese dann und zudem kann ich alles, was ich einmalig machen will, über diesen Button machen.
  6. Ich danke dir Sascha. Das werde ich mir direkt mal anschauen. Ich möchte halt beim erstmaligem erstellen der DB Initialwerte setzen. Nur doof, wenn das jedes mal gemacht wird und man dann z.B. zig mal die Kategorie None hat^^
  7. Moin Sascha, ja es ging mir in erster Linie um Performance. Ich habe ein Array in dem alle Attribute des Charakters enthalten sind und darin dann ein Array in dem die Werte für jedes einzelne Level sind. Das sind in meinem Fall 100. Können also je nach Anzahl der Attribute einige Werte zusammen kommen. Aber wenn du sagst, dass das nicht ganz so tragisch ist, dann bin ich ja beruhigt. Danke dir ☺️ Ach und gibt es auch eine Methode bei den Scriptable Objects, die nur einmalig aufgerufen wird, z.B beim erstmaligem initialisieren. OnEnable wird leider jedes mal aufgerufen, sobald ich meine Datenbank öffne.
  8. Hey Leute, gibt es eine Möglichkeit genau herauszufinden, in welchem Array-Element die aktuelle Änderung stattfindet, sodass man nicht jedes mal jedes Element aktualisieren muss, sondern nur das indem auch die Änderung stattfindet? Ich habe hier ein Verschachteltes Array mit mehreren Elementen, wenn ich jetzt den Basiswert ändere, dann sollen sich halt im Unterarray die Werte entsprechend aktualisieren. LG
  9. 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(); } }
  10. Also technisch gesehen habe ich das Problem gelöst, nur kann ich leider das Inputsystem nicht unterbrechen und in der Canceled Phase sieht man den Button wieder zurückspringen. Also er geht erst auf das neue Element und wird anschließend zurück zu seinem Ursprung gesetzt. Die "OK" Ausgabe erfolgt immer so, wie ich es mir vorgestellt habe. Gibt es irgendeine Möglichkeit an der Stelle das Inputsystem zu unterbrechen, das er nicht selbst dann noch das ausführt, wodurch mein move halt für die Tonne ist? Mit Enable, oder SetActive kann man zwar pausieren, aber sobald man wieder aktiviert, macht er einfach da weiter, wo er aufgehört hat 😓 public void test(InputActionPhase phase) { var moveVector = inputDirection; if (phase == InputActionPhase.Started) { currentBtn = EventSystem.current.currentSelectedGameObject; currentParent = EventSystem.current.currentSelectedGameObject.transform.parent; } else if (phase == InputActionPhase.Performed) { newSelectable = EventSystem.current.currentSelectedGameObject.GetComponent<Selectable>().FindSelectable(moveVector); if (newSelectable != currentBtn) { newParent = newSelectable.transform.parent; if (newParent != currentParent) { EventSystem.current.SetSelectedGameObject(currentBtn); Debug.Log("OK"); } } } else if (phase == InputActionPhase.Canceled) { EventSystem.current.SetSelectedGameObject(currentBtn); } }
  11. Lol, kontrollsüchtiges Panel also 😂 Also, wenns so geht, wie ichs mir gerade vorstelle, dann wird das sicher schon werden. Vorausgesetzt, das die Eingaben nicht ganz verschwinden. Muss ja immerhin noch wissen, welche Taste nun gedrückt wurde.
  12. Ok, ich glaube ich kann dir folgen. Wäre auch ein Versuch wert, dass mal zu probieren. Zumindest bei dynamischen Listen. Wäre dann ja quasi auch sowas, als würde ich das Inputsystem neuschreiben, nur dann halt nicht mehr für Inputs, wenn ich das so richtig verstanden habe. Der Button selbst wäre ja dann nur die gesamte Liste. Das Panel müsste man dann inaktiv setzen, damit man nicht mehr navigieren kann und sobald man zurück möchte, würde man einfach wieder aktiv setzen und könnte ganz normal weiter machen. Wenn ich das so richtig verstanden habe 😅 Ach und dann auch mal eine Frage zum Slider. Die Items haben aktuell noch keinen, brauchen sie aber logischerweise noch. In dem Fall müsste ich den Slider selektieren und nicht das Item? Weil dort hatte ich auch schon das Problem, dass es nicht funktionierte, habe es aber erstmal hinten angestellt.
  13. Ok, das verstehe ich gerade nicht wirklich^^ Naja, bisher eigentlich schon. Also es war jetzt nicht mega leicht oder so, aber bisher hat alles sehr gut funktioniert. Was mich sehr überrascht hat. Das einzige Problem ist gerade echt die Sache mit dem navigieren durchs Menu. Das hätte ich mir tatsächlich nicht so krampfig vorgestellt. Da kannst du es mal sehen, es sind 3 verschiedene Menus. Einmal das obere, dann die Items und noch das der Actors.
  14. Dumm ist halt auch, das in InputSystemUIInputModule ziemlich alles private ist. Selbst ProcessNavigation(ref m_NavigationState) geht schon nicht und das ist fast die einzige Funktion in Process 😂 Würde ja schon gerne so viel es geht übernehmen. Dann bin ich mal gespannt, ob ich das schaffe. Wirkt imo sehr schwer, aber ich freue mich drauf 😁 Und ich dachte mir so zum lernen fängst mal mit dem leichtesten an - dem Menu. Dann bin ich mal gespannt, was sonst noch so auf mich zukommt 🤔
  15. Oha, vielen dank Sascha, dass werde ich sofort mal ausprobieren ☺️ Dann bleibt nur noch die Frage, soll ich dazu quasi InputSystemUIInputModule überschreiben, bzw. brauche ich das dann nicht mehr, oder soll ich das einfach in public partial class @InputManager IInputActionCollection2, IDisposable realisieren? Das ist ja das Script, was mir von Unity erstellt wurde, als ich die Keybindings gemacht habe, also die Actionmap quasi. Und wo kann ich das neue Script dann einbinden, den im EventSystem im Inspector kann ich das Script ja leider nicht verändern und damit wäre ja dann auch jede meiner Änderungen wirkungslos?
×
×
  • Create New...