欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Unity?制作一個(gè)分?jǐn)?shù)統(tǒng)計(jì)系統(tǒng)

 更新時(shí)間:2021年12月03日 15:34:05   作者:CoderZ1010  
項(xiàng)目中經(jīng)常遇到分?jǐn)?shù)統(tǒng)計(jì)的需求,例如操作正確則計(jì)分,相反則不計(jì)分失去該項(xiàng)分?jǐn)?shù),為了應(yīng)對(duì)需求需要一個(gè)分?jǐn)?shù)統(tǒng)計(jì)系統(tǒng)。本文主要介紹了通過(guò)Unity實(shí)現(xiàn)這樣的一個(gè)計(jì)分系統(tǒng),快來(lái)跟隨小編一起學(xué)習(xí)吧

項(xiàng)目中經(jīng)常遇到分?jǐn)?shù)統(tǒng)計(jì)的需求,例如我們執(zhí)行了某項(xiàng)操作或做了某個(gè)題目,操作正確則計(jì)分,相反則不計(jì)分失去該項(xiàng)分?jǐn)?shù),為了應(yīng)對(duì)需求需要一個(gè)分?jǐn)?shù)統(tǒng)計(jì)系統(tǒng)。

首先定義一個(gè)分?jǐn)?shù)信息的數(shù)據(jù)結(jié)構(gòu),使用Serializable特性使其可序列化:

using System;
using UnityEngine;
 
namespace SK.Framework
{
    /// <summary>
    /// 分?jǐn)?shù)信息
    /// </summary>
    [Serializable]
    public class ScoreInfo
    {
        /// <summary>
        /// ID
        /// </summary>
        public int id;
        /// <summary>
        /// 描述
        /// </summary>
        [TextArea]
        public string description;
        /// <summary>
        /// 分值
        /// </summary>
        public float value;
    }
}

ScoreInfo類可序列化后,創(chuàng)建ScoreProfile類繼承ScriptableObject使其作為可通過(guò)菜單創(chuàng)建的Asset資產(chǎn):

using UnityEngine;
 
namespace SK.Framework
{
    /// <summary>
    /// 分?jǐn)?shù)配置文件
    /// </summary>
    [CreateAssetMenu]
    public class ScoreProfile : ScriptableObject
    {
        public ScoreInfo[] scores = new ScoreInfo[0];
    }
}

使用ScoreIDConstant類編寫(xiě)所有分?jǐn)?shù)項(xiàng)ID常量,創(chuàng)建ScoreID特性并使用PropertyDrawer使其可在面板選擇:

namespace SK.Framework
{
    public sealed class ScoreIDConstant
    {
        public const int INVALID = -1;
    }
}
using UnityEngine;
 
#if UNITY_EDITOR
using UnityEditor;
using System;
using System.Reflection;
using System.Collections;
#endif
 
namespace SK.Framework
{
    public class ScoreIDAttribute : PropertyAttribute { }
 
#if UNITY_EDITOR
    [CustomPropertyDrawer(typeof(ScoreIDAttribute))]
    public class ScoreIDPropertyAttributeDrawer : PropertyDrawer
    {
        private int[] scoreIDArray;
        private GUIContent[] scoreIDConstArray;
 
        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            return base.GetPropertyHeight(property, label);
        }
 
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if (scoreIDConstArray == null)
            {
                ArrayList constants = new ArrayList();
                FieldInfo[] fieldInfos = typeof(ScoreIDConstant).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
                for (int i = 0; i < fieldInfos.Length; i++)
                {
                    var fi = fieldInfos[i];
                    if (fi.IsLiteral && !fi.IsInitOnly) constants.Add(fi);
                }
                FieldInfo[] fieldInfoArray = (FieldInfo[])constants.ToArray(typeof(FieldInfo));
                scoreIDArray = new int[fieldInfoArray.Length];
                scoreIDConstArray = new GUIContent[fieldInfoArray.Length];
                for (int i = 0; i < fieldInfoArray.Length; i++)
                {
                    scoreIDConstArray[i] = new GUIContent(fieldInfoArray[i].Name);
                    scoreIDArray[i] = (int)fieldInfoArray[i].GetValue(null);
                }
            }
            var index = Array.IndexOf(scoreIDArray, property.intValue);
            index = Mathf.Clamp(index, 0, scoreIDArray.Length);
            index = EditorGUI.Popup(position, label, index, scoreIDConstArray);
            property.intValue = scoreIDArray[index];
        }
    }
#endif
}

有了ScoreID特性后,用于ScoreInfo中的id字段:

using System;
using UnityEngine;
 
namespace SK.Framework
{
    /// <summary>
    /// 分?jǐn)?shù)信息
    /// </summary>
    [Serializable]
    public class ScoreInfo
    {
        /// <summary>
        /// ID
        /// </summary>
        [ScoreID]
        public int id;
        /// <summary>
        /// 描述
        /// </summary>
        [TextArea]
        public string description;
        /// <summary>
        /// 分值
        /// </summary>
        public float value;
    }
}

數(shù)據(jù)可配置后,創(chuàng)建分?jǐn)?shù)項(xiàng)Score類,聲明以下字段:Flag表示該分?jǐn)?shù)項(xiàng)的標(biāo)識(shí),注冊(cè)分?jǐn)?shù)項(xiàng)時(shí)返回該標(biāo)識(shí),用于后續(xù)獲取或取消該分?jǐn)?shù)項(xiàng)分值;Description即分?jǐn)?shù)項(xiàng)的描述;Value表示該分?jǐn)?shù)項(xiàng)的分值;IsObtained用于標(biāo)記該分?jǐn)?shù)項(xiàng)的分值是否已經(jīng)獲得。

namespace SK.Framework
{
    /// <summary>
    /// 分?jǐn)?shù)項(xiàng)
    /// </summary>
    public class Score
    {
        /// <summary>
        /// 標(biāo)識(shí)
        /// </summary>
        public string Flag { get; private set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        /// <summary>
        /// 分值
        /// </summary>
        public float Value { get; private set; }
        /// <summary>
        /// 是否已經(jīng)獲得分值
        /// </summary>
        public bool IsObtained { get; set; }
 
        public Score(string flag, string description, float value)
        {
            Flag = flag;
            Description = description;
            Value = value;
        }
    }
}

為了實(shí)現(xiàn)一個(gè)分?jǐn)?shù)組合,例如某項(xiàng)操作,通過(guò)A操作方式可獲得5分,通過(guò)B操作方式可獲得3分,它們之間是互斥的,即獲得了前者的5分,就不會(huì)獲得后者的3分,創(chuàng)建ScoreGroup類:

using System.Collections.Generic;
 
namespace SK.Framework
{
    /// <summary>
    /// 分?jǐn)?shù)組合
    /// </summary>
    public class ScoreGroup
    {
        /// <summary>
        /// 組合描述
        /// </summary>
        public string Description { get; private set; }
        /// <summary>
        /// 計(jì)分模式
        /// Additive表示組合內(nèi)分值進(jìn)行累加
        /// MutuallyExclusive表示組內(nèi)各分?jǐn)?shù)項(xiàng)互斥 獲得其中一項(xiàng)分值 則取消其它項(xiàng)分值
        /// </summary>
        public ValueMode ValueMode { get; private set; }
 
        public List<Score> Scores { get; private set; }
 
        public ScoreGroup(string description, ValueMode valueMode, params Score[] scores)
        {
            Description = description;
            ValueMode = valueMode;
            Scores = new List<Score>(scores);
        }
 
        public bool Obtain(string flag)
        {
            var target = Scores.Find(m => m.Flag == flag);
            if (target != null)
            {
                switch (ValueMode)
                {
                    case ValueMode.Additive: target.IsObtained = true; break;
                    case ValueMode.MutuallyExclusive:
                        for (int i = 0; i < Scores.Count; i++)
                        {
                            Scores[i].IsObtained = Scores[i] == target;
                        }
                        break;
                    default: break;
                }
                if (ScoreMaster.DebugMode)
                {
                    ScoreMaster.LogInfo($"獲取分?jǐn)?shù)組合 [{Description}] 中標(biāo)識(shí)為 [{flag}] 的分值 [{target.Description}]");
                }
                return true;
            }
            if (ScoreMaster.DebugMode)
            {
                ScoreMaster.LogError($"分?jǐn)?shù)組合 [{Description}] 中不存在標(biāo)識(shí)為 [{flag}] 的分?jǐn)?shù)項(xiàng).");
            }
            return false;
        }
        public bool Cancle(string flag)
        {
            var target = Scores.Find(m => m.Flag == flag);
            if (target != null)
            {
                if (ScoreMaster.DebugMode)
                {
                    ScoreMaster.LogInfo($"取消分?jǐn)?shù)組合 [{Description}] 中標(biāo)識(shí)為 [{flag}] 的分?jǐn)?shù)項(xiàng)分值 [{target.Description}]");
                }
                target.IsObtained = false;
                return true;
            }
            if (ScoreMaster.DebugMode)
            {
                ScoreMaster.LogError($"分?jǐn)?shù)組合 [{Description}] 中不存在標(biāo)識(shí)為 [{flag}] 的分?jǐn)?shù)項(xiàng).");
            }
            return false;
        }
    }
}
namespace SK.Framework
{
    /// <summary>
    /// 計(jì)分方式
    /// </summary>
    public enum ValueMode
    {
        /// <summary>
        /// 累加的
        /// </summary>
        Additive,
        /// <summary>
        /// 互斥的
        /// </summary>
        MutuallyExclusive,
    }
}

最終編寫(xiě)分?jǐn)?shù)管理類,封裝Create、Obtain、Cancle、GetSum函數(shù),分別用于創(chuàng)建分?jǐn)?shù)組合、獲取分?jǐn)?shù)、取消分?jǐn)?shù)、獲取總分,實(shí)現(xiàn)Editor類使分?jǐn)?shù)信息在Inspector面板可視化:

using System;
using UnityEngine;
using System.Collections.Generic;
 
#if UNITY_EDITOR
using UnityEditor;
using System.Reflection;
#endif
 
namespace SK.Framework
{
    public class ScoreMaster : MonoBehaviour
    {
        #region NonPublic Variables
        private static ScoreMaster instance;
        [SerializeField] private ScoreProfile profile;
        private readonly Dictionary<string, ScoreGroup> groups = new Dictionary<string, ScoreGroup>();
        #endregion
 
        #region Public Properties
        public static ScoreMaster Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = FindObjectOfType<ScoreMaster>();
                }
                if (instance == null)
                {
                    instance = new GameObject("[SKFramework.Score]").AddComponent<ScoreMaster>();
                    instance.profile = Resources.Load<ScoreProfile>("Score Profile");
                    if (instance.profile == null && DebugMode)
                    {
                        LogError("加載分?jǐn)?shù)信息配置表失敗.");
                    }
                }
                return instance;
            }
        }
        #endregion
 
        #region NonPublic Methods
        private string[] CreateScore(string description, ValueMode valueMode, params int[] idArray)
        {
            Score[] scores = new Score[idArray.Length];
            string[] flags = new string[idArray.Length];
            for (int i = 0; i < idArray.Length; i++)
            {
                var info = Array.Find(profile.scores, m => m.id == idArray[i]);
                if (info != null)
                {
                    var flag = Guid.NewGuid().ToString();
                    flags[i] = flag;
                    scores[i] = new Score(flag, info.description, info.value);
                    if (DebugMode) LogInfo($"創(chuàng)建分?jǐn)?shù)ID為 [{idArray[i]}] 的分?jǐn)?shù)項(xiàng) [{info.description}] flag: {flag}");
                }
                else if (DebugMode)
                {
                    LogError($"配置中不存在ID為 [{idArray[i]}] 的分?jǐn)?shù)信息.");
                }
            }
            ScoreGroup group = new ScoreGroup(description, valueMode, scores);
            groups.Add(description, group);
            if (DebugMode)
            {
                LogInfo($"創(chuàng)建分?jǐn)?shù)組合 [{description}] 計(jì)分模式[{valueMode}]");
            }
            return flags;
        }
        private bool ObtainValue(string groupDescription, string flag)
        {
            if (groups.TryGetValue(groupDescription, out ScoreGroup target))
            {
                return target.Obtain(flag);
            }
            if (DebugMode)
            {
                LogError($"不存在分?jǐn)?shù)組合 [{groupDescription}].");
            }
            return false;
        }
        private bool CancleValue(string groupDescription, string flag)
        {
            if (groups.TryGetValue(groupDescription, out ScoreGroup target))
            {
                return target.Cancle(flag);
            }
            if (DebugMode)
            {
                LogError($"不存在分?jǐn)?shù)組合 [{groupDescription}].");
            }
            return false;
        }
        private float GetSumValue()
        {
            float retV = 0f;
            foreach (var kv in groups)
            {
                var scores = kv.Value.Scores;
                for (int i = 0; i < scores.Count; i++)
                {
                    var score = scores[i];
                    if (score.IsObtained)
                    {
                        retV += score.Value;
                    }
                }
            }
            return retV;
        }
        #endregion
 
        #region Public Methods
        /// <summary>
        /// 創(chuàng)建分?jǐn)?shù)組合
        /// </summary>
        /// <param name="description">分?jǐn)?shù)組合描述</param>
        /// <param name="valueMode">分?jǐn)?shù)組計(jì)分方式</param>
        /// <param name="idArray">分?jǐn)?shù)信息ID組合</param>
        /// <returns>返回分?jǐn)?shù)項(xiàng)標(biāo)識(shí)符組合</returns>
        public static string[] Create(string description, ValueMode valueMode, params int[] idArray)
        {
            return Instance.CreateScore(description, valueMode, idArray);
        }
        /// <summary>
        /// 獲取分?jǐn)?shù)組合中指定標(biāo)識(shí)分?jǐn)?shù)項(xiàng)的分值
        /// </summary>
        /// <param name="groupDescription">分?jǐn)?shù)組合</param>
        /// <param name="flag">分?jǐn)?shù)項(xiàng)標(biāo)識(shí)</param>
        /// <returns>獲取成功返回true 否則返回false</returns>
        public static bool Obtain(string groupDescription, string flag)
        {
            return Instance.ObtainValue(groupDescription, flag);
        }
        /// <summary>
        /// 取消分?jǐn)?shù)組合中指定標(biāo)識(shí)分?jǐn)?shù)項(xiàng)的分值
        /// </summary>
        /// <param name="groupDescription">分?jǐn)?shù)組合</param>
        /// <param name="flag">分?jǐn)?shù)項(xiàng)標(biāo)識(shí)</param>
        /// <returns></returns>
        public static bool Cancle(string groupDescription, string flag)
        {
            return Instance.CancleValue(groupDescription, flag);
        }
        /// <summary>
        /// 獲取總分值
        /// </summary>
        /// <returns>總分值</returns>
        public static float GetSum()
        {
            return Instance.GetSumValue();
        }
        #endregion
 
        #region Debugger
        public static bool DebugMode = true;
 
        public static void LogInfo(string info)
        {
            Debug.Log($"<color=cyan><b>[SKFramework.Score.Info]</b></color> --> {info}");
        }
        public static void LogWarn(string warn)
        {
            Debug.Log($"<color=yellow><b>[SKFramework.Score.Warn]</b></color> --> {warn}");
        }
        public static void LogError(string error)
        {
            Debug.Log($"<color=red><b>[SKFramework.Score.Error]</b></color> --> {error}");
        }
        #endregion
    }
 
#if UNITY_EDITOR
    [CustomEditor(typeof(ScoreMaster))]
    public class ScoreMasterInspector : Editor
    {
        private SerializedProperty profile;
        private Dictionary<string, ScoreGroup> groups;
        private Dictionary<ScoreGroup, bool> groupFoldout;
 
        private void OnEnable()
        {
            profile = serializedObject.FindProperty("profile");
        }
 
        public override void OnInspectorGUI()
        {
            EditorGUILayout.PropertyField(profile);
            if (GUI.changed)
            {
                serializedObject.ApplyModifiedProperties();
                EditorUtility.SetDirty(target);
            }
 
            if (!Application.isPlaying) return;
            Color color = GUI.color;
            GUI.color = Color.cyan;
            OnRuntimeGUI();
            GUI.color = color;
        }
        private void OnRuntimeGUI()
        {
            if (groupFoldout == null)
            {
                groups = typeof(ScoreMaster).GetField("groups", BindingFlags.Instance | BindingFlags.NonPublic)
                    .GetValue(ScoreMaster.Instance) as Dictionary<string, ScoreGroup>;
                groupFoldout = new Dictionary<ScoreGroup, bool>();
            }
 
            foreach (var kv in groups)
            {
                if (!groupFoldout.ContainsKey(kv.Value))
                {
                    groupFoldout.Add(kv.Value, false);
                }
 
                ScoreGroup group = kv.Value;
                groupFoldout[group] = EditorGUILayout.Foldout(groupFoldout[group], group.Description);
                if (groupFoldout[group])
                {
                    GUILayout.Label($"計(jì)分模式: {(group.ValueMode == ValueMode.Additive ? "累加" : "互斥")}");
                    for (int i = 0; i < group.Scores.Count; i++)
                    {
                        Score score = group.Scores[i];
                        GUILayout.BeginVertical("Box");
                        GUI.color = score.IsObtained ? Color.green : Color.cyan;
                        GUILayout.Label($"描述: {score.Description}");
                        GUILayout.Label($"標(biāo)識(shí): {score.Flag}");
                        GUILayout.BeginHorizontal();
                        GUILayout.Label($"分值: {score.Value}   {(score.IsObtained ? "√" : "")}");
                        GUI.color = Color.cyan;
                        GUILayout.FlexibleSpace();
                        GUI.color = Color.yellow;
                        if (GUILayout.Button("Obtain", "ButtonLeft", GUILayout.Width(50f)))
                        {
                            ScoreMaster.Obtain(group.Description, score.Flag);
                        }
                        if (GUILayout.Button("Cancle", "ButtonRight", GUILayout.Width(50f)))
                        {
                            ScoreMaster.Cancle(group.Description, score.Flag);
                        }
                        GUI.color = Color.cyan;
                        GUILayout.EndHorizontal();
                        GUILayout.EndVertical();
                    }
                }
            }
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.Label($"總分: {ScoreMaster.GetSum()}", "LargeLabel");
            GUILayout.Space(50f);
            GUILayout.EndHorizontal();
        }
    }
#endif
}

測(cè)試:

namespace SK.Framework
{
    public sealed class ScoreIDConstant
    {
        public const int INVALID = -1;
 
        public const int TEST_A = 0;
        public const int TEST_B = 1;
        public const int TEST_C = 2;
        public const int TEST_D = 3;
    }
}

using UnityEngine;
using SK.Framework;
 
public class Foo : MonoBehaviour
{
    private string[] flags;
 
    private void Start()
    {
        flags = ScoreMaster.Create("測(cè)試", ValueMode.MutuallyExclusive,
            ScoreIDConstant.TEST_A, ScoreIDConstant.TEST_B, 
            ScoreIDConstant.TEST_C, ScoreIDConstant.TEST_D);
    }
 
    private void OnGUI()
    {
        if (GUILayout.Button("A", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
            ScoreMaster.Obtain("測(cè)試", flags[0]);
        }
        if (GUILayout.Button("B", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
            ScoreMaster.Obtain("測(cè)試", flags[1]);
        }
        if (GUILayout.Button("C", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
            ScoreMaster.Obtain("測(cè)試", flags[2]);
        }
        if (GUILayout.Button("D", GUILayout.Width(200f), GUILayout.Height(50f)))
        {
            ScoreMaster.Obtain("測(cè)試", flags[3]);
        }
        GUILayout.Label($"總分: {ScoreMaster.GetSum()}");
    }
}

?

以上就是Unity 制作一個(gè)分?jǐn)?shù)統(tǒng)計(jì)系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于Unity的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論