第一次写博客,新的开始

毕业两年了,一直都想着什么时候开始写自己的博客,但是都忙于工作,心有余而力不足。最近换了一份不怎么加班的工作,所以决定开始写博客,也是从现在开始记录下自己的成长历程吧。

新工作的第一个问题

从我毕业工作到现在,所经历的项目基本都是Unity C# + lua,lua这门语言被大量的运用到游戏中来,我们的很多逻辑都放到了lua层去处理。比如一个相机的视角操作我们就是放在lua层,但是这个操作有很多的参数需要策划或者美术去调整,以前我们的做法就是配置数值表,这种方法是很不方便的,策划需要改一个数值,就导表一次。
我们leader给我安排的第一个工作就是想办法简化流程,也就是把lua变量想办法序列化到unity Inspector面板显示,并且方便修改保存。

解决方案

  • 监听lua代码变化
    我们都知道在c#脚本里面定义个public 的变量,unity会编译然后显示到Inspector面板,方便修改(原理自己去找,不是我今天的重点,我这里就不再啰嗦了),我们希望lua也能做到这一点。
    首先想到的是lua代码改变了,我们的程序能知道,然后去刷新代码,我们是用的是继承一个编辑器类AssetPostprocessor的方式,监听lua代码改变,这里我直接上代码:
public class LuaFilePostProcess : AssetPostprocessor
{
    public static Action<string> OnImport;

    static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
    {
        foreach (var file in importedAssets)
        {
            if (OnImport != null && file.EndsWith(".lua"))
                OnImport(file);
        }
    }
}

这样我只要监听OnImport这个action就可以知道lua代码是否改变了。

  • 分析lua代码的语法 这里我们可以自定义自己的识别块,在lua代码中添加如下
•  –[[
AttToUnityDefine =
 {
 translateSpeed | float | 移动速度,
 dampingSpeed | float | 阻尼速度,
 rollSpeed | float | 滚轮速度,
 }
 ]]

我就是这么定义的,其中第一个为参数名,第二个为类型,第三个注释,在做的时候可以按照自己方便的格式去书写。
然后就是分析了,我们c#这边监听到了lua代码的变化,就会去识别他,这里我用的正则匹配去匹配这一段代码string matchString = @"AttToUnityDefine\s*=\s*\{([^}]*)\}";当拿到这个代码段我们就可以去解析它,直接上代码了

abstract class PropBase
    {
        public string PropertyName;

        public abstract void Draw();

        public abstract object GetValue();
    }

 class ValueTypeProp : PropBase
    {
        public Type type;
        public SerializedProperty SP;
        public string des;
        public CacheValueProp cache_prop;
        GUIContent m_label;

        public override void Draw()
        {
            if (m_label == null)
                m_label = new GUIContent(PropertyName);
            object cache = GetCacheValue();
            if (cache != null && cache != GetValue())
            {
                SetCacheValue();
            }
            if(!string.IsNullOrEmpty(des))
            {
                EditorGUILayout.PrefixLabel(des);
            }
            EditorGUILayout.PropertyField(SP, m_label);        
        }
        public override object GetValue()
        {
            if (type == typeof(float))
            {
                return SP.floatValue;
            }
            else if (type == typeof(string))
            {
                return SP.stringValue;
            }
            else if (type == typeof(Vector3))
            {
                return SP.vector3Value;
            }
            else if (type == typeof(Color))
            {
                return SP.colorValue;
            }
            else if (type == typeof(int))
            {
                return SP.intValue;
            }
            else
            {
                throw new NotSupportedException(string.Format("Not support property type '{0}'", type.Name));
            }
        }

        public object GetCacheValue()
        {
            if (cache_prop == null)
            {
                return null;
            }
            if (type == typeof(float))
            {
                return cache_prop.num_value;
            }
            else if (type == typeof(string))
            {
                return cache_prop.str_value;
            }
            else if (type == typeof(Vector3))
            {
                return cache_prop.vec_value;
            }
            else if (type == typeof(Color))
            {
                return cache_prop.color_value;
            }
            else if (type == typeof(int))
            {
                return cache_prop.int_value;
            }
            else
            {
                throw new NotSupportedException(string.Format("Not support property type '{0}'", type.Name));
            }
        }

        public void SetCacheValue()
        {
            if (cache_prop == null)
            {
                return;
            }
            if (type == typeof(float))
            {
                SP.floatValue = cache_prop.num_value;
            }
            else if (type == typeof(string))
            {
                SP.stringValue = cache_prop.str_value;
            }
            else if (type == typeof(Vector3))
            {
                SP.vector3Value = cache_prop.vec_value;
            }
            else if (type == typeof(Color))
            {
                SP.colorValue = cache_prop.color_value;
            }
            else if (type == typeof(int))
            {
                SP.intValue = cache_prop.int_value;
            }
            else
            {
                throw new NotSupportedException(string.Format("Not support property type '{0}'", type.Name));
            }
            cache_prop = null;
        }



        //public void Set
    }

LuaComponent 那边会存储这边序列化的值,这里就不再啰嗦了。

  • 自定义面板显示
    CustomEditor这个是unity的一个特性,不懂得可以自己去查下,它可以在OnInspectorGUI自定义Unity Inspector按照自己的需求去显示,但是也不是今天介绍的重点,直接上代码了。
[CustomEditor(typeof(LuaComponent))]
public class LuaComponentInspector : Editor
{
	public override void OnInspectorGUI()
	{
	}
}

这样定义就是控制 LuaComponent 的显示规则,当然LuaComponent必须继承MonoBehaviour,然后把上面那些解析到的值给序列化出来,就能大公告成了

Unity 如何监听scrollRect停止滑动_c#

这边附上最后的效果图,可以提供给策划去调整。