Mittwoch, 4. November 2020

Unity UI Element Button selection and click simulation via script

simulate select and click

using UnityEngine.EventSystems;
using UnityEngine.UI;

...

[SerializeField] private Button myButton;

...

// simulate click : 

ExecuteEvents.Execute(myButton.gameObject, new BaseEventData(EventSystem.current), ExecuteEvents.submitHandler);

// simulate selection : 

EventSystem.current.SetSelectedGameObject(myButton.gameObject);



------------------------------------------------------------------------

List<Button> shuffling

   private GameObject[] _buttonGameObjects;
   private int _buttonIndex = -1;

..

_buttonGameObjects = GameObject.FindGameObjectsWithTag("MenuButton");

..

// select next button

            if (_buttonIndex + 1 == _buttonGameObjects.Length)
                _buttonIndex = 0;
            else
               _buttonIndex++;
  EventSystem.current.SetSelectedGameObject(_buttonGameObjects[_buttonIndex]);

..

// select previous button


            if (_buttonIndex - 1 < 0)
                _buttonIndex = _buttonGameObjects.Length - 1;
            else
                _buttonIndex--;
          EventSystem.current.SetSelectedGameObject(_buttonGameObjects[_buttonIndex]);


-----------------------------------------------------

Get all Buttons nested in a GameObject below the Canvas. The demo structure is ...Canvas, MenuPageLanguageSelection, MenuButton1...

    private Canvas myCanvas;
    private GameObject myMenuPageLanguage;
    GameObject[] myMenuButtonGameObjects;

    private void Awake()
    {
         myCanvas = GameObject.FindObjectOfType<Canvas>(); // only one in scene
        myMenuPageLanguage = myCanvas.transform.GetChild(0).gameObject; 
        myMenuButtonGameObjects = new                       GameObject[myMenuPageLanguage.transform.childCount];
        for (int i = 0; i < myMenuPageLanguage.transform.childCount; i++)
        {
            myMenuButtonGameObjects[i] =                      myMenuPageLanguage.transform.GetChild(i).gameObject;
        }
}


Freitag, 23. Oktober 2020

Unity and Visual Studio Keyboard Shortcuts

 Visual Studio Editor:

CTRL + ALT + M , then CTRL + H  : Will open Unity Scripting API Documentation inside VS

CTRL + Shift + M : Show dialog to implement new Method easily


Dienstag, 29. September 2020

Unity - InputSystem - Gamepad access etc.

2020-09-29 high level description:

open the project settings

enable preview packages

open the Package Manager

select the filter Unity Registrations 

Install the InputSystem Package

go to your project Assets folder of the inspector

choose Create the right mouse button click

choose Input Actions - this will add the InputSystem asset 'New Controls' to your project.

'New Controls' - rename it with Gameplay for instance

Doubleclick on 'Gameplay'

The Window to add the actions and bindings comes up.

Anchor the window next to the Console window etc. for a quick access.

Add a Input Map called 'MenuControl'

Add a action to the 'MenuControl' called 'moveLeft'

Add a bindung or more bindings to move the menu cursor finally to the left - so just add a binding of the left arrow key to this action 'moveLeft'.

Notice the save checkbox in top of the window. Activate it for saving. 
Also check the properties of the created asset. Doublecheck the checkbox overthere "create class".
This will generate a new proxy class for the inputSystem called 'Gameplay' here.

In your unity application create an instance of this class.

Important is to call the .enable() method of the instance of such created Input Action Asset. Just add the call of the .disable() method of the object in the OnDisable() method of the hosting gameobject.

To the instanced object register callbacks for each action of the input system map 'MenuControl' of the input system 'Gameplay'...

And / Or add direct request to the Keyboard.current or Gamepad.current objects if any key or button is pressed.

Sonntag, 2. August 2020

Unity Architecture best practice

Add a persistent manager class to the hierarchy. This class should be added to all scenes. Add this class to a scene common prefab. This class will be initiated only once in the complete lifecycle of the application. To achive this persistent behavior add the command "DontDestroyOnLoad(gameObject)" to the Awake() method of the script. The persistent manager is just an empty game object renamed to e.g. PersistentManager with such assigned characteristic script:

using UnityEngine;
using UnityEngine.SceneManagement;

public class PersistentManagerCode : MonoBehaviour
{
    public int Level;
    public delegate void GameEvent();

    public static PersistentManagerCode Instance { get; private set; }
    public static event GameEvent OnResetGame; // listeners can subscribe to this event

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this; // what creates the first instance? The gameobject which is called persistentGameManager - that is all - discover the static vars on top
            DontDestroyOnLoad(gameObject); // to be persistent, okay - is available in all scenes
            DoResetGame();
        }
        else
            Destroy(gameObject);
    }

    public void DoResetGame()
    {
        if (OnResetGame != null)
            OnResetGame(); // if there are any subscribers, then call the OnResetGame GameEvent delegate function of the subscriber
        this.Level = 0;
    }

    ...
}

to be continued...




Sonntag, 10. Mai 2020

TAG - FindGameObjectWithTag(..)

Assigning a GameObject to a script variable is often done using drag and drop in the inspector.
Another way to load a GameObject instance into a variable is to apply ...
private transform playerTransform
...
playerTransform = GameObject.FindGameObjectWithTag("MyPlayer").transform;

Sonntag, 26. April 2020

Unity - animation prefab creation

The challenge is to take over the transform position of the parent object. Approach:

Creation:

- create an empty gameObject in the hierarchy
- drop a resource like a sprite png onto the empty gameObject in the hierachy
- the gameObject covering the sprite png is now a child object of the empty one
- if not available create a subfolder in the Assets folder named prefabs
- create a subfolder in the new folder prefabs called mySampleAnimationObject
- drop the empty gameobject of the hierarchy in the prefab subfolder just created
- add a animator component to the child of the empty gameobject in the prefab
- you should be asked to create the animation
- record the animation
- create a new c# script and drop it onto the child of the empty gameobject. The gameobject including the animator now!
- add a public function like : public void AnimFinished() {  Destroy(gameObject); }
- add a event to the end of the animation / onto the last key frame add the event.
- assign the AnimFinished() method to the event.
- save

Usage:

- open the main actor script
- add a public GameObject variable to host the created prefab including the upper mentioned stuff
       public GameObject MySampleAnimPrefab;
- drop this prefab within the inspector on this new public member of the script component
- now is the prefab in general linked to the script of the main actor;
- the main actor script can now fire and forget as many prefab animation objects as desired
- this will be done using for example:
        Instantiate(MySampleAnimPrefab, collision.gameObject.transform.position, Quaternion.identity); // the second arg is any Vector3 type position

Montag, 13. April 2020

Unity - how to collect item

The item to collect is a prefab.
This prefab got a collider
The collider of the prefab is checked as 'isTrigger'!
The gameobject of this collectable item is tagged as 'Coin'.

The prefab of the player actor checks for collisions in its script:

private void OnTriggerEnter2D(Collider collision)
{
       if (collision.gameObject.CompareTag("Coin"))
       {
                Destroy(collision.gameObject);
                MyPersistentManager.Instance.DoCollectCoinAction(); // todo

        }
}