第一次写博客,新的开始
毕业两年了,一直都想着什么时候开始写自己的博客,但是都忙于工作,心有余而力不足。最近换了一份不怎么加班的工作,所以决定开始写博客,也是从现在开始记录下自己的成长历程吧。
新工作的第一个问题
从我毕业工作到现在,所经历的项目基本都是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,然后把上面那些解析到的值给序列化出来,就能大公告成了
这边附上最后的效果图,可以提供给策划去调整。