游戏脚本

Unity在开发模式下,它使用Mono来跨平台地编译和解析C#脚本。游戏发布之后,Unity还提供自动将DLL转成IL2CPP的方式,可以提升代码编译后的执行效率及稳定性。

  1. 创建脚本
    可以在Project试图创建在出Editor以外的任意目录和子目录下,因为Editor的代码会被系统认为是编辑模式的代码,在打包后会自动剥离。

    其中除了C#脚本还有两类脚本,分别是Testing和Playables。其中,testing是用来做单元测试的,Playables是Timeline中用于管理时间线上的每一帧的动画、声音和视频等。
1.ScriptableObject

创建出来的ScriptableObject只用于保存数据,并且可以通过Inspector面板对它进行编辑。

使用Script_04_12.cs创建出的first.asset就是创建的资源,把它放在Resources目录下,方便运行时读取。

unity可编程脚本 unity支持的脚本_System


但是在把以下这段代码进行实现之后,发现在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

这样就可以把属性都显示出来并且进行编辑

unity可编程脚本 unity支持的脚本_System_02


现在,只需要把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#的类,可以通过这样的方式来进行调用。