[RESOLU][CF] Scriptable Assetdatabase generique

Pour les scripts écrits en C#
Règles du forum
Merci de respecter la NOMENCLATURE suivante pour vos TITRES de messages :

Commencez par le niveau de vos scripts
DB = Débutant
MY = Moyen
CF = Confirmé

Puis le domaine d'application
-RS = Réseau
-AL = Algorithmie

Exemple :

[DB-RS] Mouvement perso multijoueur
Avatar de l’utilisateur
realitynauts
Messages : 23
Inscription : 15 Août 2012 09:42
Contact :

[RESOLU][CF] Scriptable Assetdatabase generique

Message par realitynauts » 18 Avr 2017 11:41

Bonjour à tous :hello: ,

Apres ce nom de sujet uniquement remplis de mots clefs, je vais vous exposer mon problème~

Tout d’abord je suis sur la conceptions classique d'une base de données pour mon jeu.

/!\ toutes les modifications ce font coté editeur et non runtime~

J'utilise donc nos amis les ScriptableObject et AssetDatabase.

Je crée donc de manière générique des assets qui servent de base de données et donc avec aucun script reelement attaché.

Ici une base de données de livres :
Image
Image

Mais le problème vient du redémarrage de Unity, mon asset n'est plus accessible~
Image

Pour les intéressés :

Scriptable_DB_Objet

Code : Tout sélectionner

using UnityEngine;
using System.Linq;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace BugQuest.DBSystem
{
    [System.Serializable]
    public class Scriptable_DB_Objet<T> : ScriptableObject where T : class
    {
        [SerializeField]
        protected List<T> _objets = new List<T>();

        public List<T> Objets
        {
			get { return _objets; }
        }

        public int Count
        {
			get { return _objets.Count; }
        }

        public T Get(int i)
        {
			return (T)System.Activator.CreateInstance(typeof(T), _objets.ElementAt(i));
        }

        public T GetRandom()
        {
			return (T)System.Activator.CreateInstance(typeof(T), Random.Range(0, _objets.Count - 1));
        }
    }
}
DB_Editor

Code : Tout sélectionner

using UnityEditor;
using UnityEngine;

namespace BugQuest.DBSystem.Editor
{
    public class DB_Editor<D, T> where D : Scriptable_DB_Objet<T> where T : DB_Object, new()
    {
        [SerializeField]
        private D _database;
        [SerializeField]
        private string _name;
        [SerializeField]
        private string _path = @"Databases";

        private int _selectedIndex = -1;
        private T _tmpItem = new T();
        private bool _showDetails = false;
        private Vector2 _srollPos = Vector2.zero;
        private string _itemType = "";

        public DB_Editor(string name)
        {
            _name = name;
        }

        public void OnEnable(string itemType)
        {
            _itemType = itemType;

            if (_database == null)
                LoadDatabase();
        }

        private void LoadDatabase()
        {
            string fullPath = @"Assets/" + _path + "/" + _name;

            _database = AssetDatabase.LoadAssetAtPath(fullPath, typeof(D)) as D;

            if (_database == null)
            {
                CreateDatabase(fullPath);
            }

        }

        private void CreateDatabase(string fullPath)
        {
            //Verification dossiée
            if (!AssetDatabase.IsValidFolder("Assets/" + _path))
                AssetDatabase.CreateFolder("Assets", _path);

            //Creation de la base de donnée et mise à jour du fichier
            _database = ScriptableObject.CreateInstance<D>() as D;
            AssetDatabase.CreateAsset(_database, fullPath);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }

        public void OnGUI(Vector2 buttonSize, int listViewWidth)
        {
            ListView(buttonSize, listViewWidth);
            Details();
        }

        public void Details()
        {
            GUILayout.BeginVertical("Box", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
            GUILayout.BeginVertical(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));

            if (_showDetails)
                _tmpItem.OnGUI();

            GUILayout.EndVertical();

            GUILayout.Space(50);
            GUILayout.BeginHorizontal("Box", GUILayout.ExpandWidth(true));
            DisplayButtons();
            GUILayout.EndHorizontal();
            GUILayout.EndVertical();
        }

        private void DisplayButtons()
        {
            if (_showDetails)
            {
                SaveButton();

                if (_selectedIndex > -1)
                    DeleteButton();

                CancelButton();
            }
            else
            {
                CreateButtons();
            }
        }

        private void CreateButtons()
        {
            if (GUILayout.Button("New " + _itemType))
            {
                _tmpItem = new T();
                _selectedIndex = -1;
                _showDetails = true;
                GUI.FocusControl("CancelButton");
            }
        }

        private void SaveButton()
        {
            if (GUILayout.Button("Save"))
            {
                if (_selectedIndex == -1)
                    Add(_tmpItem);
                else
                    Replace(_selectedIndex, _tmpItem);

                _selectedIndex = -1;
                _showDetails = false;
                _tmpItem = new T();
                GUI.FocusControl("CancelButton");
            }
        }

        private void CancelButton()
        {
            GUI.SetNextControlName("CancelButton");
            if (GUILayout.Button("Cancel"))
            {
                _selectedIndex = -1;
                _showDetails = false;
                _tmpItem = new T();
                GUI.FocusControl("CancelButton");

            }
        }

        private void DeleteButton()
        {
            if (GUILayout.Button("Delete") && _selectedIndex != -1)
            {
                if (EditorUtility.DisplayDialog("Delete " + _itemType, " Delete : " + _tmpItem.Name + " ?", "Yes", "Cancel"))
                {
                    Remove(_selectedIndex);

                    _selectedIndex = -1;
                    _showDetails = false;
                    _tmpItem = new T();
                    GUI.FocusControl("CancelButton");
                }
            }
        }

        public void ListView(Vector2 buttonSize, int listViewWidth)
        {
            _srollPos = EditorGUILayout.BeginScrollView(_srollPos, "Box", GUILayout.ExpandHeight(true), GUILayout.Width(listViewWidth));
            for (int i = 0; i < _database.Count; i++)
            {
                if (GUILayout.Button(_database.Get(i).Name, "Box", GUILayout.Width(buttonSize.x), GUILayout.Height(buttonSize.y)))
                {
                    _selectedIndex = i;
                    _tmpItem = new T();
                    _tmpItem.SetFromDatabase(_database.Get(i));
                    _showDetails = true;
                }
            }
            EditorGUILayout.EndScrollView();
        }

        public void Add(T item)
        {
            _database.Objets.Add(item);
            EditorUtility.SetDirty(_database);
        }

        public void Insert(int i, T item)
        {
            _database.Objets.Insert(i, item);
            EditorUtility.SetDirty(_database);
        }

        public void Remove(T i)
        {
            _database.Objets.Remove(i);
            EditorUtility.SetDirty(_database);
        }

        public void Remove(int i)
        {
            _database.Objets.RemoveAt(i);
            EditorUtility.SetDirty(_database);
        }

        public void Replace(int i, T item)
        {
            _database.Objets[i] = item;
            EditorUtility.SetDirty(_database);
        }

        public static U GetDatabase<U>(string path, string name) where U : ScriptableObject
        {
            string fullPath = @"Assets/" + path + "/" + name;

            U database = AssetDatabase.LoadAssetAtPath(fullPath, typeof(U)) as U;

            if (database == null)
            {
                //Verification dossiée
                if (!AssetDatabase.IsValidFolder("Assets/" + path))
                    AssetDatabase.CreateFolder("Assets", path);

                //Creation de la base de donnée et mise à jour du fichier
                database = ScriptableObject.CreateInstance<U>() as U;
                AssetDatabase.CreateAsset(database, fullPath);
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            }

            return database;
        }
    }
}
Une idée ? une évidence ?
Pourriez vous m'aidez s'il vous plait~

Je vous remercie d'avance !

Nazarick
Messages : 60
Inscription : 03 Avr 2017 21:44

Re: [CF] Scriptable Assetdatabase generique

Message par Nazarick » 18 Avr 2017 11:55

Image
Tu n'a rien d'affiché dans ta console ? Vérifie aussi l'exactitude entre les noms de tes deux fichiers et les noms inscrit dans tes classes. Des fois, une légère différence à peine visible dans l'orthographe peut tout ruiner.

Avatar de l’utilisateur
realitynauts
Messages : 23
Inscription : 15 Août 2012 09:42
Contact :

Re: [CF] Scriptable Assetdatabase generique

Message par realitynauts » 18 Avr 2017 12:36

Bonjour Nazarik,

Absolument aucunes erreurs dans la console, ni de warning ni même de simples messages.

La classe de la base est declarée comme ceci:

Code : Tout sélectionner

public class DB_Book : Scriptable_DB_Object<Item.Book>{}
L'asset est crée comme ceci en suivant la class générique DB_Editor:

Code : Tout sélectionner

private DB_Editor<DB_Book, DBSystem.Item.Book> _DB_Book = new DB_Editor<DB_Book, DBSystem.Item.Book>("DB_Book.asset");
Tout les noms on été corrigés et sont identiques

J'utilise book comme exemple, mais le résultat est le même peu importe l'objet et le nom.

Aucun script ne sera jamais attaché l'asset puisque il est crée de manière générique, ce qui ne semble pas gêner unity puisqu'il affiche correctement les objets serializés et marque même "None (Mono script)" (voir second screen dans le premier post) à l'emplacement du script dans l'asset,.
C'est au redémarrage que unity n'arrive plus à faire le lien.

Je me demande si le problème viens du faite que je déclare toute mes bases dans le même fichier comme ceci :

Code : Tout sélectionner

namespace BugQuest.DBSystem
{
    [System.Serializable]
    public class DB_Object
	{
		public DB_Object (){}
		public virtual string Name { get; set; }
		public virtual void SetFromDatabase (DB_Object db_object){}
		public virtual void OnGUI (){}
	}

	/*======= Item =======*/
	public class DB_Equipement : Scriptable_DB_Object<Item.Equipment>{}
	public class DB_Weapon : Scriptable_DB_Object<Item.Weapon>{}
	public class DB_Potion : Scriptable_DB_Object<Item.Potion>{}
	public class DB_Belt : Scriptable_DB_Object<Item.Belt>{}
	public class DB_Book : Scriptable_DB_Object<Item.Book>{}


	/*======= Donjon =======*/
	public class DB_Level : Scriptable_DB_Object<Dungeon.Level>{}
}

Avatar de l’utilisateur
realitynauts
Messages : 23
Inscription : 15 Août 2012 09:42
Contact :

Re: [CF] Scriptable Assetdatabase generique

Message par realitynauts » 18 Avr 2017 16:17

Problème résolut !

Le problème était bien en accord ma supposition de mon dernier message, en mettant chaque déclaration dans son fichier (avec le même nom ;3), unity est capable de retrouver le bon script et charger l'asset~

Je laisse le script libre d’accès, mais n'en faites pas votre gloire, il est plutôt simple et a été fait avec l'aide d'un tuto sur youtube il y 2 ans il me semble~

Merci ! Et soyez créatif pour le monde de demain !

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6243
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: [CF] Scriptable Assetdatabase generique

Message par boubouk50 » 18 Avr 2017 16:40

realitynauts a écrit :Problème résolu!
Salut realitynauts,

Lorsque le problème est résolu, merci d'ajouter [RESOLU] en début du titre du premier post pour signaler aux autres membres que la solution a été trouvée.
Je m'en occupe cette fois-ci.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Répondre

Revenir vers « (C#) CSharp »