-

   rss_rss_hh_new

 - e-mail

 

 -

 LiveInternet.ru:
: 17.03.2011
:
:
: 51

:


Unity:

, 05 2017 . 19:48 +
. . , TES Fallout . , :
1) . , .
2) , .

. -? generic singleton. MonoBehaviour
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenericSingleton : MonoBehaviour {
    static GenericSingleton instance;
    public static GenericSingleton Instance { get { return instance; } }

	void Awake () {
		if (instance && instance != this)
        {
            Destroy(this);
            return;
        }
        instance = this;
	}
}


public class TestSingletoneA : GenericSingleton {

	// Use this for initialization
	void Start () {
        Debug.Log("A");
	}
}


.. Generic , .
. , . .

. , SetValues ( ) . ?

/// 
/// Voloshin Game Framework: basic scripts supposed to be reusable
/// 
namespace VGF
{    
    //[System.Serializable]
    public interface AbstractModel where T : AbstractModel, new()
    {
        /// 
        /// Copy fields from target
        /// 
        /// Source model
        void SetValues(T model);            
    }

    public static class AbstratModelMethods
    {
        /// 
        /// Initialize model with source, even if model is null
        /// 
        /// 
        /// Target model, can be null
        /// Source model
        public static void InitializeWith(this T model, T source) where T: AbstractModel, new ()
        {
            //model = new T();
            if (source == null)
                return;
            model.SetValues(source);
        }
    }
}


, , .

, . , , . !

? . - SaveLoadManager .

.
1) protected
2) All, -
3) , All .

.
using System.Collections.Generic;
using UnityEngine;

namespace VGF
{
    /* Why abstract class instead of interface?
     * 1) Incapsulate all save, load, init, loadinit functions inside class, make them protected, mnot public
     * 2) Create static ALL collection and static ALL methods
     * */
     //TODO: create a similar abstract class for non-mono classes. For example, PlayerController needs not to be a MonoBehaviour
    /// 
    /// Abstract class for all MonoBehaiour classes that support save and load
    /// 
    public abstract class SaveLoadBehaviour : CachedBehaviour
    {
        /// 
        /// Collection that stores all SaveLoad classes in purpose of providing auto registration and collective save and load
        /// 
        static List AllSaveLoadObjects = new List();

        protected override void Awake()
        {
            base.Awake();
            Add(this);
        }

        static void Add(SaveLoadBehaviour item)
        {
            if (AllSaveLoadObjects.Contains(item))
            {
                Debug.LogError(item + "  element is already in All list");
            }
            else
                AllSaveLoadObjects.Add(item);
        }

        public static void LoadAll()
        {
            foreach (var item in AllSaveLoadObjects)
            {
                if (item == null)
                {
                    Debug.LogError("empty element in All list");
                    continue;
                }
                else
                    item.Load();
            }
        }

        public static void SaveAll()
        {
            Debug.Log(AllSaveLoadObjects.Count);
            foreach (var item in AllSaveLoadObjects)
            {
                if (item == null)
                {
                    Debug.LogError("empty element in All list");
                    continue;
                }
                else
                    item.Save();
            }
        }

        public static void LoadInitAll()
        {
            foreach (var item in AllSaveLoadObjects)
            {
                if (item == null)
                {
                    Debug.LogError("empty element in All list");
                    continue;
                }
                else
                    item.LoadInit();
            }
        }

        protected abstract void Save();

        protected abstract void Load();

        protected abstract void Init();

        protected abstract void LoadInit();
    }
}

using UnityEngine;

namespace VGF
{
    /// 
    /// Controller for abstract models, providing save, load, reset model
    /// 
    /// AbstractModel child type
    public class GenericModelBehaviour : SaveLoadBehaviour where T: AbstractModel, new()
    {
        [SerializeField]
        protected T InitModel;
        //[SerializeField]
        protected T CurrentModel, SavedModel;

        protected override void Awake()
        {
            base.Awake();
            //Init();
        }

        void Start()
        {
            Init();
        }

        protected override void Init()
        {
            //Debug.Log(InitModel);
            if (InitModel == null)
                return;
            //Debug.Log(gameObject.name + " : Init current model");
            if (CurrentModel == null)
                CurrentModel = new T();
            CurrentModel.InitializeWith(InitModel);
            //Debug.Log(CurrentModel);
            //Debug.Log("Init saved model");
            SavedModel = new T();
            SavedModel.InitializeWith(InitModel);
        }

        protected override void Load()
        {
            //Debug.Log(gameObject.name + "   saved");
            LoadFrom(SavedModel);
        }

        protected override void LoadInit()
        {
            LoadFrom(InitModel);
        }

        void LoadFrom(T source)
        {
            if (source == null)
                return;
            CurrentModel.SetValues(source);
        }

        protected override void Save()
        {
            //Debug.Log(gameObject.name + "   saved");
            if (CurrentModel == null)
                return;
            if (SavedModel == null)
                SavedModel.InitializeWith(CurrentModel);
            else
                SavedModel.SetValues(CurrentModel);
        }
    }
}


:
public abstract class AbstractAliveController : GenericModelBehaviour, IAlive
    {
        //TODO: create separate unity implementation where put all the [SerializeField] attributes
        [SerializeField]
        bool Immortal;
        static Dictionary All = new Dictionary();
        public static bool GetAliveControllerForTransform(Transform tr, out AbstractAliveController aliveController)
        {
            return All.TryGetValue(tr, out aliveController);
        }

        DamageableController[] BodyParts;
        
        public bool IsAlive { get { return Immortal || CurrentModel.HealthCurrent > 0; } }
        public bool IsAvailable { get { return IsAlive && myGO.activeSelf; } }
        public virtual Vector3 Position { get { return myTransform.position; } }

        public static event Action OnDead;
        /// 
        /// Sends the current health of this alive controller
        /// 
        public event Action OnDamaged;

        //TODO: create 2 inits
        protected override void Awake()
        {
            base.Awake();
            All.Add(myTransform, this);            
        }

        protected override void Init()
        {
            InitModel.Position = myTransform.position;
            InitModel.Rotation = myTransform.rotation;
            base.Init();
            
            BodyParts = GetComponentsInChildren();
            foreach (var bp in BodyParts)
                bp.OnDamageTaken += TakeDamage;
        }

        protected override void Save()
        {
            CurrentModel.Position = myTransform.position;
            CurrentModel.Rotation = myTransform.rotation;
            base.Save();
        }

        protected override void Load()
        {
            base.Load();
            LoadTransform();
        }

        protected override void LoadInit()
        {
            base.LoadInit();
            LoadTransform();
        }

        void LoadTransform()
        {
            myTransform.position = CurrentModel.Position;
            myTransform.rotation = CurrentModel.Rotation;
            myGO.SetActive(true);
        }

        public void Respawn()
        {
            LoadInit();
        }

        public void TakeDamage(int damage)
        {
            if (Immortal)
                return;
            CurrentModel.HealthCurrent -= damage;
            OnDamaged.CallEventIfNotNull(CurrentModel.HealthCurrent);
            if (CurrentModel.HealthCurrent <= 0)
            {
                OnDead.CallEventIfNotNull(this);
                Die();
            }
        }

        public int CurrentHealth
        {
            get { return CurrentModel == null? InitModel.HealthCurrent: CurrentModel.HealthCurrent; }
        }

        protected abstract void Die();

    }


namespace VGF.Action3d
{
    [System.Serializable]
    public class AliveModelTransform : AliveModelBasic, AbstractModel
    {
        [HideInInspector]
        public Vector3 Position;
        [HideInInspector]
        public Quaternion Rotation;

        public void SetValues(AliveModelTransform model)
        {
            Position = model.Position;
            Rotation = model.Rotation;
            base.SetValues(model);
        }
    }
}


.
1) () . , .
: .
2) . json, . . , json-?
: . json . , , //. .

( ):
FPSProject


, , .
.
.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330278/

:  

: [1] []
 

:
: 

: ( )

:

  URL