游戏脚本
Unity在开发模式下,它使用Mono来跨平台地编译和解析C#脚本。游戏发布之后,Unity还提供自动将DLL转成IL2CPP的方式,可以提升代码编译后的执行效率及稳定性。
- 创建脚本
可以在Project试图创建在出Editor以外的任意目录和子目录下,因为Editor的代码会被系统认为是编辑模式的代码,在打包后会自动剥离。
其中除了C#脚本还有两类脚本,分别是Testing和Playables。其中,testing是用来做单元测试的,Playables是Timeline中用于管理时间线上的每一帧的动画、声音和视频等。
1.ScriptableObject
创建出来的ScriptableObject只用于保存数据,并且可以通过Inspector面板对它进行编辑。
使用Script_04_12.cs创建出的first.asset就是创建的资源,把它放在Resources目录下,方便运行时读取。
但是在把以下这段代码进行实现之后,发现在Inspector面板并没有出现可以编辑的试图。
[CreateAssetMenu]
public class Script_04_12 : ScriptableObject
{
[SerializeField]
public List<PlayerInfo> m_PlayerInfo;
[System.Serializable]
public class PlayerInfo
{
public int id;
public string name;
public GameObject prefab;
}
}
可以看见代码中使用了[SerializeField],它标记了所有私有属性的对象,这样外部就无法访问了。若需要在脚本的Inspector界面上显示出可编辑的试图,要使用UnityEditor对其进行处理。对于这样的对象,想要使用拓展编辑器来编辑这些数据,可以使用SerializedObject和SerializedProperty来获取设置数据。在代码中,只需要通过serializedObject.FindProperty()来访问私有属性,只需要传入他们的名称即可。
#if UNITY_EDITOR
using UnityEditor;
#endif
#if UNITY_EDITOR
[CustomEditor(typeof(Script_04_12))]
public class ScriptInsector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
{
serializedObject.Update();
SerializedProperty property = serializedObject.FindProperty("m_PlayerInfo");
property.intValue = EditorGUILayout.IntField("id", property.intValue);
property.serializedObject.FindProperty("name");
property.stringValue = EditorGUILayout.TextField("name", property.stringValue);
property.serializedObject.FindProperty("prefab");
property.objectReferenceValue = EditorGUILayout.ObjectField("gameobject", property.objectReferenceValue,typeof(GameObject),true);
serializedObject.ApplyModifiedProperties();
}
}
}
#endif
这样就可以把属性都显示出来并且进行编辑
现在,只需要把Main脚本挂在任意对象上运行即可。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Main : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Script_04_12 script = Resources.Load<Script_04_12>("first");
Debug.LogFormat("name:{0} id:{1}", script.m_PlayerInfo[0].name, script.m_PlayerInfo[0].id);
}
}
也可以使用代码进行创建,在需要批量创的时候用点击Create就很呆,这时候通过以下代码,直接使用AssertDatabase.SaveAssets()即可保存
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Create : MonoBehaviour
{
[MenuItem("Assets/Create ScriptableObject")]
static void CreateScriptableObject()
{
Script_04_12 script = ScriptableObject.CreateInstance<Script_04_12>();
script.m_PlayerInfo = new List<Script_04_12.PlayerInfo>();
script.m_PlayerInfo.Add(new Script_04_12.PlayerInfo() { id = 10, name = "test"});//如何创建一个prefab还未解决。
AssetDatabase.CreateAsset(script, "Asset/Resources/Create Script_04_12.asset");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
2.单例脚本
适用于功能单一且需要用到脚本生命周期的方法(?),它必须依赖游戏对象,并且保证这个游戏对象不能被卸载掉。
如以下脚本所示:Global脚本在其直接的static构造方法中创建对象,并且设置了DontDestoryOnLoad(),这个方法可以保证对象不被主动卸载掉,并且构造方法只会执行一次。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Grobal : MonoBehaviour
{
public static Grobal instance;
static Grobal()
{
GameObject go = new GameObject("#Globa#");
DontDestroyOnLoad(go);
instance = go.AddComponent<Grobal>();
}
public void DoSomeThings()
{
Debug.Log("DoSomeThing")
}
// Start is called before the first frame update
void Start()
{
Debug.Log("start");
}
}
Global脚本不需要再编辑模式下绑定在某个对象上,运行时直接获取它的实例就能操作了。
Global.instance.DoSameThings();
单例脚本类似于一个C#的类,可以通过这样的方式来进行调用。