Unity S老師系列課程學習


AssetBundle(創建打包)入門學習(基於Unity2017) (已看)

  分組策略

  1. 邏輯實體分組
  2. 按照類型分組
  3. 按照使用分組 

  分組策略----總結

  1. 把經常更新的資源放在一個單獨的包里面,跟不經常更新的包分離
  2. 把需要同時加載的資源放在一個包里面
  3. 可以把其他包共享的資源放在一個單獨的包里面
  4. 把一些需要同時加載的小資源打包成一個包
  5. 如果對於同一個資源有兩個版本,可以考慮通過后綴來區分

  

  BuildAssetBundleOptions

  1. BuildAssetBundleOptions.None: 使用LZMA算法壓縮,壓縮的包更小,但是加載時間更長.使用之前需要整體壓縮.一旦被解壓,這個包會使用LZ4重新壓縮.使用資源的時候不需要整體解壓.在下載的時候可以使用LZMA算法,一旦
  2. BuildAssetBundleOptions.UncompressedAssetBundle: 不壓縮,包大,加載快
  3. BuildAssetBundleOptions.ChunkBasedCompression: 使用LZ4壓縮,壓縮率沒有LZMA高,但是我們可以加載指定資源而不用解壓全部
ManifestFileVersion: 0
CRC: 1389444494
AssetBundleManifest:
    AssetBundleInfo:
        Info_0:
            Name: share.untiy3d
            Dependencies: {}
        Info_1:
            Name: capsulewall.unity3d
            Dependencies:
                Dependency_0: share.unity3d
        Info_2:
            Name: cubewall.unity3d
            Dependencies:
                Dependency_0: share.unity3d
AssetBundles.manifest

  文件校驗

  CRC MD5 SHA1
相同點:
  CRC、MD5、SHA1都是通過對數據進行計算,來生成一個校驗值,該校驗值用來校驗數據的完整性。
不同點:

  1. 算法不同。CRC采用多項式除法,MD5和SHA1使用的是替換、輪轉等方法;
  2. 校驗值的長度不同。CRC校驗位的長度跟其多項式有關系,一般為16位或32位;MD5是16個字節(128位);SHA1是20個字節(160位);
  3. 校驗值的稱呼不同。CRC一般叫做CRC值;MD5和SHA1一般叫做哈希值(Hash)或散列值;
  4. 安全性不同。這里的安全性是指檢錯的能力,即數據的錯誤能通過校驗位檢測出來。CRC的安全性跟多項式有很大關系,相對於MD5和SHA1要弱很多;MD5的安全性很高,不過大概在04年的時候被山東大學的王小雲破解了;SHA1的安全性最高。
  5. 效率不同,CRC的計算效率很高;MD5和SHA1比較慢。
  6. 用途不同。CRC一般用作通信數據的校驗;MD5和SHA1用於安全(Security)領域,比如文件校驗、數字簽名等。

 

Asset: https://docs.unity3d.com/Manual/AssetWorkflow.html

  An Asset is a representation of any item you can use in your game or Project.

  An Asset may come from a file created outside of Unity, such as a 3D Model, an audio file, an image, or any of the other file types that Unity supports.

  There are also some Asset types that you can create in Unity, such as a ProBuilder Mesh , an Animator Controller , an Audio Mixer, or a Render Texture.

SpecialFolders: https://docs.unity3d.com/Manual/SpecialFolders.html

  • Asset: The Assets folder is the main folder that contains the Assets used by a Unity project.
  • Editor: Scripts placed in a folder called Editor are treated as Editor scripts rather than runtime scripts.These scripts add functionality to the Editor during development, and are not available in builds at runtime.
  • Editor Default Resources: Editor scripts can make use of Asset files loaded-on-demand using the EditorGUIUtility.Load function. This function looks for the Asset files in a folder called Editor Default Resources. You can only have one 
  • Gizmos:  You can only have one Gizmos folder and it must be placed in the root of the Project.
  • Plug-ins: You can only have one Plugins folder and it must be placed in the root of the Project; directly within the Assets folders;
  • Resources: You can load Assets on-demand from a script instead of creating instances of Assets in a Scene for use in gameplay. You do this by placing the Assets in a folder called Resources
  • Standard Assets: When you import a Standard Asset package the Assets are placed in a folder called Standard Assets.
  • StreamingAssets: Place a file in a folder called StreamingAssets,so it is copied unchanged to the target machine, where it is then available from a specific folder.
  • Hidden Assets: During the import process, Unity completely ignores the following files and folders in the Assets folder
  1. Hidden folders
  2. Files and folders which start with '.'
  3. Files and folders which end with '~'
  4. Files and folders named cvs
  5. Files with the extension .tmp

StreamingAssets: https://docs.unity3d.com/Manual/StreamingAssets.html

  Any files placed in a folder called StreamingAssets (case-sensitive) in a Unity project will be copied verbatim to a particular folder on the target machine

    On a desktop computer:  path = Application.dataPath + "/StreamingAssets"

    On iOS, use:  path = Application.dataPath + "/Raw"

    On Android, use:  path = "jar:file://" + Application.dataPath + "!/assets/";

AssetBundles: https://docs.unity3d.com/Manual/AssetBundlesIntro.html

  AssetBundle Workflow  

    An AssetBundle is an archive file containing platform specific Assets (Models, Textures, Prefabs, Audio clips, and even entire Scenes) that can be loaded at runtime.

    AssetBundles can express dependencies between each other; e.g. a material in AssetBundle A can reference a texture in AssetBundle B.

    For efficient delivery over networks, AssetBundles can be compressed with a choice of built-in algorithms depending on use case requirements (LZMA and LZ4).

What's in an AssetBundle?

    AssetBundle can refer to two different, but related things.

      First is the actual file on disk. This we call the AssetBundle archive, or just archive for short in this document. The archive can be thought of as a container, like a folder, that holds additional files inside of it. These additional files consist of two types; the serialized file and resource files. The serialized file contains your assets broken out into their individual objects and written out to this single file. The resource files are just chunks of binary data stored separately for certain assets (textures and audio) to allow us to load them from disk on another thread efficiently.

      Second is the actual AssetBundle object you interact with via code to load assets from a specific archive. This object contains a map of all the file paths of the assets you added to this archive to the objects that belong to that asset that need to be loaded when you ask for it.

public class CRC32 {
    static UInt32[] crcTable =
    {
    0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
    0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
    0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
    0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
    0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
    0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
    0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
    0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
    0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
    0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
    0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
    0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
    0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
    0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
    0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
    0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
    0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
    0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
    0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
    0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
    0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
    0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
    0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
    0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
    0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
    0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
    0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
    0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
    0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
    0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
    0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
    0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};

    public static uint GetCRC32(string msg) {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(msg);
        uint iCount = (uint)bytes.Length;
        uint crc = 0xFFFFFFFF;

        for (uint i = 0; i < iCount; i++) {
            crc = (crc << 8) ^ crcTable[(crc >> 24) ^ bytes[i]];
        }

        return crc;
    }
}
View Code

  Preparing Assets for AssetBundles

  Building AssetBundles

  AssetBundle Dependencies

    AssetBundles can become dependent on other AssetBundles if one or more of the UnityEngine.Objects contains a reference to a UnityEngine.Object located in another bundle. A dependency does not occur if the UnityEngine.Object contains a reference to a UnityEngine.Object that is not contained in any AssetBundle. In this case, a copy of the object that the bundle would be dependent on is copied into the bundle when you build the AssetBundles. If multiple objects in multiple bundles contain a reference to the same object that isn’t assigned to a bundle, every bundle that would have a dependency on that object will make its own copy of the object and package it into the built AssetBundle.

    Should an AssetBundle contain a dependency, it is important that the bundles that contain those dependencies are loaded before the object you’re attempting to instantiate is loaded. Unity will not attempt to automatically load dependencies.

    Consider the following example, a Material in Bundle 1 references a Texture in Bundle 2:

In this example, before loading the Material from Bundle 1, you would need to load Bundle 2 into memory. It does not matter which order you load Bundle 1 and Bundle 2, the important takeaway is that Bundle 2 is loaded before loading the Material from Bundle 1.

  Using AssetBundles Natively 

  Patching with AssetBundles

  Troubleshooting

  Unity Asset Bundle Browser tool 

AssetBundle框架設計_理論篇 (已看)

AssetBundle框架設計_框架篇 (已看)

AB打包分類  

  按類型  

  按場景  包名稱 = "場景名稱/功能文件夾名"

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

namespace ABFramework {

    /// <summary>
    /// 1. 定義需要打包資源的文件夾根目錄
    /// 2. 遍歷每個"場景"文件夾(目錄)
    ///     a. 遍歷本場景目錄下所有的目錄或者文件
    ///        如果是目錄,則繼續"遞歸"訪問里面的文件,直到定位到文件
    ///     b. 找到文件,則使用AssetImporter類,標記"包名"與"后綴名"
    /// </summary>
    public class AutoSetABName {

        /// <summary>
        /// 設置AB包名稱
        /// </summary>
        [MenuItem("AssetBundleTools/Set AB Name")]
        public static void SetABName() {

            AssetDatabase.RemoveUnusedAssetBundleNames();

            string abResPath = string.Empty;
            abResPath = PathTools.GetABResourcesPath();

            DirectoryInfo[] dirScenesArray = null;  // 根目錄下的所有一級子目錄

            DirectoryInfo dirTempInfo = new DirectoryInfo(abResPath);
            dirScenesArray = dirTempInfo.GetDirectories();

            foreach (var item in dirScenesArray) {
                string tempSceneDir = abResPath + "/" + item.Name;  // 全路徑

                //DirectoryInfo tempSceneDirInfo = new DirectoryInfo(tempSceneDir);

                int tempIndex = tempSceneDir.LastIndexOf("/");
                string tempSceneName = tempSceneDir.Substring(tempIndex + 1);  // 場景名稱

                JudgeDirOrFileRecursive(item, tempSceneName);
            }


            AssetDatabase.Refresh();

            Debug.Log("AssetBundle 本次操作設置標記完成!");
        }

        private static void JudgeDirOrFileRecursive(FileSystemInfo fileSystemInfo, string sceneName) {
            if (!fileSystemInfo.Exists) {
                Debug.LogError("文件或目錄名稱: " + fileSystemInfo + "不存在,檢查");
                return;
            }

            DirectoryInfo dirInfo = fileSystemInfo as DirectoryInfo;    // 文件信息轉換為目錄信息
            FileSystemInfo[] fileSystemInfoArr = dirInfo.GetFileSystemInfos();

            foreach (var item in fileSystemInfoArr) {
                FileInfo fileInfo = item as FileInfo;

                if (fileInfo != null) {
                    SetFileABName(fileInfo, sceneName); // 設置文件的AB名
                } else {
                    JudgeDirOrFileRecursive(item, sceneName);   // 遞歸目錄
                }
            }
        }

        /// <summary>
        /// 對指定的文件設置AB包名
        /// </summary>
        private static void SetFileABName(FileInfo fileInfo, string sceneName) {
            string abName = string.Empty;
            string assetFilePath = string.Empty;    // 文件路徑(相對路徑)

            if (fileInfo.Extension == ".meta") {
                return;
            }

            abName = GetABName(fileInfo, sceneName);

            // 獲取資源文件的相對路徑
            int tempIndex = fileInfo.FullName.IndexOf("Assets");
            assetFilePath = fileInfo.FullName.Substring(tempIndex);

            AssetImporter tempImporter = AssetImporter.GetAtPath(assetFilePath);
            tempImporter.assetBundleName = abName;

            //Debug.Log("assetFilePath: " + assetFilePath);
            //Debug.Log("abName: " + abName);

            if (fileInfo.Extension == ".unity") {
                tempImporter.assetBundleVariant = "u3d";
            } else {
                tempImporter.assetBundleVariant = "ab";
            }
            //Debug.Log(fileInfo.FullName);
            //Debug.Log(tempImporter.assetBundleVariant);




            //if (fileInfo.Extension == ".unity") {
            //    // 定義AB包的擴展名

            //}

            //Debug.Log(assetFilePath);

            //AssetImporter tempImporter = AssetImporter.GetAtPath(fileInfo.FullName);
            //Debug.Log(tempImporter);
            //Debug.Log(tempImporter.)
        }

        /// <summary>
        /// 獲取AB包的名稱
        /// 
        /// AB包形成規則
        ///     文件AB包名稱 = "所在二級目錄名稱"(場景名稱) + "三級目錄名稱"(下一級的"類型名稱")
        /// </summary>
        private static string GetABName(FileInfo fileInfo, string sceneName) {
            string abName = string.Empty;

            // Win路徑
            string tempWinPath = fileInfo.FullName;
            // Unity路徑
            string tempUnityPath = tempWinPath.Replace("\\", "/");
            // 定位"場景名稱"后面字符的位置
            int tempSceneNazmePos = tempUnityPath.IndexOf(sceneName) + sceneName.Length;
            // AB包中的"類型名稱"所在區域
            string abFileNameArea = tempUnityPath.Substring(tempSceneNazmePos + 1);

            if (abFileNameArea.Contains("/")) {
                string[] tempStrArr = abFileNameArea.Split('/');
                abName = sceneName + "/" + tempStrArr[0];
            } else {
                // .unity AB包名
                abName = sceneName + "/" + sceneName;
            }

            return abName;
        }
    }
}
AutoSetABName
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

namespace ABFramework {

    public class BuildAssetBundle { 

        [MenuItem("AssetBundleTools/BuildAllAssetBundles")]
        public static void BuildAllAB() {
            string abOutPathDir = string.Empty;

            abOutPathDir = PathTools.GetABOutputPath();
        
            if (!Directory.Exists(abOutPathDir)) {
                Directory.CreateDirectory(abOutPathDir);
            }

            BuildPipeline.BuildAssetBundles(abOutPathDir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
        }
    }
}
BuildAssetBundle
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

namespace ABFramework {

    public class DeleteAssetBundle {

        [MenuItem("AssetBundleTools/DeleteAllAssetBundle")]
        public static void DelAssetBundle() {
            string deleteDir = string.Empty;

            deleteDir = PathTools.GetABOutputPath();

            if (!string.IsNullOrEmpty(deleteDir)) {
                Directory.Delete(deleteDir, true);
                File.Delete(deleteDir + " .meta");
                AssetDatabase.Refresh();
            }
        }
    }
}
DeleteAssetBundle
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    /* 委托定義 */
    public delegate void ABLoadComplete(string abName);



    public class ABDefine {
        public static readonly string ASSETBUNDLEMANIFEST = "AssetBundleManifest";
    }
}
ABDefine
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PathTools {

    /* 路徑常量 */
    public const string AB_RESOURCES = "AB_Res";

    /// <summary>
    /// 獲取AB資源的輸入目錄
    /// </summary>
    public static string GetABResourcesPath() {
        return Application.dataPath + "/" + AB_RESOURCES;
    }

    /// <summary>
    /// 獲取AB資源的輸出目錄
    ///     1. 平台路徑
    ///     2. 平台的名稱
    /// </summary>
    public static string GetABOutputPath() {
        return GetPlatformPath() + "/" + GetPlatformName();
    }

    /// <summary>
    /// 獲取平台路徑
    /// </summary>
    private static string GetPlatformPath() {
        string platformPath = string.Empty;

        switch (Application.platform) {
            case RuntimePlatform.WindowsPlayer:
            case RuntimePlatform.WindowsEditor:
                platformPath = Application.streamingAssetsPath;
                break;
            case RuntimePlatform.IPhonePlayer:
            case RuntimePlatform.Android:
                platformPath = Application.persistentDataPath;
                break;
        }
        return platformPath;
    }

    /// <summary>
    /// 獲取平台名稱
    /// </summary>
    public static string GetPlatformName() {
        string platformName = string.Empty;

        switch (Application.platform) {
            case RuntimePlatform.WindowsPlayer:
            case RuntimePlatform.WindowsEditor:
                platformName = "Windows";
                break;
            case RuntimePlatform.IPhonePlayer:
                platformName = "iPhone";
                break;
            case RuntimePlatform.Android:
                platformName = "Android";
                break;
        }
        return platformName;
    }

    /// <summary>
    /// 獲取WWW下載(AB包)路徑
    /// </summary>
    public static string GetWWWPath() {
        string WWWPath = string.Empty;

        switch (Application.platform) {
            case RuntimePlatform.WindowsPlayer:
            case RuntimePlatform.WindowsEditor:
                WWWPath = "file://" + GetABOutputPath();
                break;
            case RuntimePlatform.Android:
                WWWPath = "jar:file://" + GetABOutputPath();
                break;
            case RuntimePlatform.IPhonePlayer:
                WWWPath = GetABOutputPath() + "/Raw/";
                break;
        }

        return WWWPath;
    }
}
PathTools
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    /// <summary>
    /// 讀取AssetBundle依賴關系文件
    /// </summary>
    public class ABManifestLoader : System.IDisposable {

        private static ABManifestLoader instance;

        private AssetBundleManifest manifest;

        private string manifestPath;

        // 讀取Manifest的AB
        private AssetBundle manifestAB;

        private bool isLoaded;


        public bool IsLoaded {
            get {
                return isLoaded;
            }
        }

        public static ABManifestLoader Instance {
            get {
                if (instance == null) {
                    instance = new ABManifestLoader();
                }
                return instance;
            }
        }


        private ABManifestLoader() {
            manifestPath = PathTools.GetWWWPath() + "/" + PathTools.GetPlatformName();

            manifest = null;
            manifestAB = null;
            isLoaded = false;
        }

        /// <summary>
        /// 加載Manifest清單文件
        /// </summary>
        /// <returns></returns>
        public IEnumerator LoadManifest() {
            using (WWW www = new WWW(manifestPath)) {
                yield return www;

                if (www.progress >= 1) {
                    AssetBundle ab = www.assetBundle;

                    if (ab != null) {
                        manifestAB = ab;
                        manifest = manifestAB.LoadAsset(ABDefine.ASSETBUNDLEMANIFEST) as AssetBundleManifest;    // "AssetBundleManifest"固定寫法
                        isLoaded = true;
                    } else {
                        Debug.Log(GetType() + "/LoadManifest()/WWW下載出錯,請檢查! manifestPath = " + manifestPath + " 錯誤信息: " + www.error);
                    }
                }
            }
        }

        /// <summary>
        /// 獲取Manifest
        /// </summary>
        public AssetBundleManifest GetABManifest() {
            if (isLoaded) {
                if (manifest != null) {
                    return manifest;
                } else {
                    Debug.Log(GetType() + "/GetABManifest()/manifest == null!請檢查");
                }
            } else {
                Debug.Log(GetType() + "/GetABManifest()/isLoaded == false,Manifest沒有加載完畢!請檢查");
            }

            return null;
        }

        /// <summary>
        /// 獲取Manifest中指定包名的依賴項
        /// </summary>
        /// <returns></returns>
        public string[] GetAllDependency(string abName) {
            if (manifest != null && !string.IsNullOrEmpty(abName)) {
                return manifest.GetAllDependencies(abName);
            }
            return null;
        }

        /// <summary>
        /// 釋放資源
        /// </summary>
        public void Dispose() {
            if (manifestAB != null) {
                manifestAB.Unload(true);
            }
        }
    }
}
ABManifestLoader
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    /// <summary>
    /// 1. 存儲指定AB包的所有依賴關系包
    /// 2. 存儲指定AB包的所有被引用關系包
    /// </summary>
    public class ABRelation {

        // 當前AB包名
        private string abName;
        // 當前AB包的所有依賴包
        private List<string> dependencyABList;
        // 當前AB包的所有被引用包
        private List<string> referenceABList;


        public ABRelation(string abName) {
            if (!string.IsNullOrEmpty(abName)) {
                this.abName = abName;
            }

            dependencyABList = new List<string>();
            referenceABList = new List<string>();


        }

        /* 依賴關系 */

        /// <summary>
        /// 增加依賴關系
        /// </summary>
        public void AddDependency(string abName) {
            if (!dependencyABList.Contains(abName)) {
                dependencyABList.Add(abName);
            }
        }

        /// <summary>
        /// 移除依賴關系
        /// </summary>
        /// <returns>
        /// true    此AB沒有依賴項
        /// false   此AB還有依賴項
        /// </returns>
        public bool RemoveDependency(string abName) {
            if (dependencyABList.Contains(abName)) {
                dependencyABList.Remove(abName);
            }

            if (dependencyABList.Count > 0) {
                return false;
            } else {
                return true;
            }
        }

        /// <summary>
        /// 獲取所有依賴關系
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllDependency() {
            return dependencyABList;
        }


        /* 被引用關系 */


        /// <summary>
        /// 增加被引用關系
        /// </summary>
        public void AddReference(string abName) {
            if (!referenceABList.Contains(abName)) {
                referenceABList.Add(abName);
            }
        }

        /// <summary>
        /// 移除被引用關系
        /// </summary>
        /// <returns>
        /// true    此AB沒有被引用項
        /// false   此AB還有被引用項
        /// </returns>
        public bool RemoveReference(string abName) {
            if (referenceABList.Contains(abName)) {
                referenceABList.Remove(abName);
            }

            if (dependencyABList.Count > 0) {
                return false;
            } else {
                return true;
            }
        }

        /// <summary>
        /// 獲取所有被引用關系
        /// </summary>
        /// <returns></returns>
        public List<string> GetAllReference() {
            return referenceABList;
        }
    }
}
ABRelation
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    /// <summary>
    /// 框架主流程(4): 所有場景的AssetBundle管理
    /// 
    /// 1. 讀取Manifest
    /// 2. 以場景為單位,管理整個項目中所有的AssetBundle包
    /// </summary>
    public class AssetBundleMgr : MonoBehaviour {

        private static AssetBundleMgr instance;

        private Dictionary<string, MultiABMgr> multiABMgrDict = new Dictionary<string, MultiABMgr>();

        private AssetBundleManifest manifest = null;


        public static AssetBundleMgr Instance() {
            if (instance == null) {
                instance = new GameObject("AssetBundleMgr").AddComponent<AssetBundleMgr>();
            }
            return instance;
        }

        private AssetBundleMgr() {

        }

        private void Awake() {
            StartCoroutine(ABManifestLoader.Instance.LoadManifest());
        }

        public IEnumerator LoadAssetBundle(string sceneName, string abName, ABLoadComplete abLoadComplete) {
            // 參數檢查
            if (string.IsNullOrEmpty(sceneName) || string.IsNullOrEmpty(abName)) {
                Debug.LogError(GetType() + "/LoadAssetBundle()/sceneName or abName == null,請檢查!");
                yield return null;
            }

            // 等待Manifest文件加載完成
            while (!ABManifestLoader.Instance.IsLoaded) {
                yield return null;
            }
            manifest = ABManifestLoader.Instance.GetABManifest();
            if (manifest == null) {
                Debug.LogError(GetType() + "/LoadAssetBundle()/manifest == null,請檢查!");
                yield return null;
            }

            // 加入當前場景
            if (!multiABMgrDict.ContainsKey(sceneName)) {
                MultiABMgr multiABMgr = new MultiABMgr(sceneName, abName, abLoadComplete);
                multiABMgrDict.Add(sceneName, multiABMgr);
            }

            // 調用下一層(多包管理)
            MultiABMgr tempMultiABMgr = multiABMgrDict[sceneName];

            if (tempMultiABMgr == null) {
                Debug.LogError(GetType() + "/LoadAssetBundle()/tempMultiABMgr == null,請檢查!");
            }

            yield return tempMultiABMgr.LoadAssetBundle(abName);
        }

        /// <summary>
        /// 加載(AB包中)資源
        /// </summary>
        public UnityEngine.Object LoadAsset(string sceneName, string abName, string assetName, bool isCache) {
            if (multiABMgrDict.ContainsKey(sceneName)) {
                MultiABMgr multiABMgr = multiABMgrDict[sceneName];
                return multiABMgr.LoadAsset(abName, assetName, isCache);
            }

            Debug.LogError(GetType() + "/LoadAsset()/找不到場景名稱,無法加載資源,請檢查! sceneName: " + sceneName);

            return null;
        }


        /// <summary>
        /// 釋放資源
        /// </summary>
        public void DisposeAllAsset(string sceneName) {
            if (multiABMgrDict.ContainsKey(sceneName)) {
                MultiABMgr multiABMgr = multiABMgrDict[sceneName];
                multiABMgr.DisposeAllAsset();
            } else {
                Debug.LogError(GetType() + "/LoadAsset()/找不到場景名稱,無法釋放資源,請檢查! sceneName: " + sceneName);
            }
        }

    }
}
AssetBundleMgr
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    /// <summary>
    /// 框架主流程 1. AB資源加載類
    /// 
    /// AB包內資源的加載
    /// 
    /// 功能:
    ///     1. 管理與加載指定AB的資源
    ///     2. 加載具有"緩存功能"的資源,帶選用參數
    ///     3. 卸載,釋放AB資源
    ///     4. 查看當前AB資源
    /// </summary>
    public class AssetLoader : System.IDisposable {

        private AssetBundle currentAB;

        private Dictionary<string, Object> ht;


        public AssetLoader(AssetBundle ab) {
            if (ab != null) {
                currentAB = ab;
                ht = new Dictionary<string, Object>();
            } else {
                Debug.LogError(GetType() + "/構造函數 AssetBundle()/ 參數 ab == null!,請檢查");
            }
        }

        /// <summary>
        /// 加載當前包中指定的資源
        /// </summary>
        public UnityEngine.Object LoadAsset(string assetName, bool isCache = false) {
            return LoadResource<UnityEngine.Object>(assetName, isCache);
        }

        /// <summary>
        /// 加載當前AB包的資源
        /// </summary>
        private T LoadResource<T>(string assetName, bool isCahce) where T: UnityEngine.Object {
            if (ht.ContainsKey(assetName)) {
                return ht[assetName] as T;
            }

            T tempRes = currentAB.LoadAsset<T>(assetName);

            if (tempRes != null && isCahce) {
                ht.Add(assetName, tempRes);
            } else if (tempRes == null) {
                Debug.LogError(GetType() + "/LoadResource<T>/參數 tempRes==null, 請檢查");
            }

            return tempRes;
        }

        /// <summary>
        /// 卸載指定資源
        /// </summary>
        public bool UnLoadAsset(UnityEngine.Object asset) {
            if (asset != null) {
                Resources.UnloadAsset(asset);
                return true;
            }

            Debug.LogError(GetType() + "/UnLoadAsset()/參數 asset == null, 請檢查");
            return false;
        }

        /// <summary>
        /// 釋放當前AssetBundle內存鏡像資源
        /// </summary>
        public void Dispose() {
            currentAB.Unload(false);    
        }

        /// <summary>
        /// 釋放當前AssetBundle內存鏡像資源,且釋放內存資源
        /// </summary>
        public void DisposeAll() {
            currentAB.Unload(true);
        }

        /// <summary>
        /// 查詢當前AssetBundle中包含的所有資源名稱
        /// </summary>
        /// <returns></returns>
        public string[] GetAllAssetName() {
            return currentAB.GetAllAssetNames();
        }
    }
}
AssetLoader
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    /// <summary>
    /// 主流程(3): (一個場景中)多個AssetBundle管理
    /// 
    /// 1. 獲取AB包的依賴與引用
    /// 2. 管理AB包之間的自動連鎖(遞歸)加載機制
    /// </summary>
    public class MultiABMgr {

        private SingleABLoader singleABLoader;

        // 緩存AB包,防止重復加載
        private Dictionary<string, SingleABLoader> singleABLoaderDict;

        // 當前場景(調試使用)
        private string currentSceneName;

        private string currentABName;

        private Dictionary<string, ABRelation> abRelationDict;

        private ABLoadComplete loadCompleteHandler;

        public MultiABMgr(string sceneName, string abName, ABLoadComplete abLoadComplete) {
            currentSceneName = sceneName;
            currentABName = abName;
            singleABLoaderDict = new Dictionary<string, SingleABLoader>();
            abRelationDict = new Dictionary<string, ABRelation>();

            loadCompleteHandler = abLoadComplete;
        }

        /// <summary>
        /// 完成指定AB包的調用
        /// </summary>
        /// <param name="abName"></param>
        private void LoadABCompleted(string abName) {
            //Debug.Log(GetType() + "/當前完成ABName:" + abName);
            if (abName.Equals(currentABName)) {
                if (loadCompleteHandler != null) {
                    loadCompleteHandler(abName);
                }
            }
        }

        /// <summary>
        /// 加載AB包
        /// </summary>
        public IEnumerator LoadAssetBundle(string abName) {
            // AB包關系的建立
            if (!abRelationDict.ContainsKey(abName)) {
                ABRelation abRelation = new ABRelation(abName);
                abRelationDict.Add(abName, abRelation);
            }

            ABRelation tempABRelation = abRelationDict[abName];

            // 得到指定AB包所有的依賴關系(查詢manifest文件)
            string[] abDependencyArr = ABManifestLoader.Instance.GetAllDependency(abName);

            foreach (var item in abDependencyArr) {

                Debug.Log("abName: " + abName + ", depenABName: " + item);

                // 添加依賴項
                tempABRelation.AddDependency(item);
                // 添加被引用項
                yield return LoadReference(item, abName);
            }

            //Debug.Log(tempABRelation.GetAllDependency());
            //Debug.Log(tempABRelation.GetAllReference());


            // 真正加載AB包
            if (singleABLoaderDict.ContainsKey(abName)) {
                yield return singleABLoaderDict[abName].LoadAssetBundle();
            } else {
                singleABLoader = new SingleABLoader(abName, LoadABCompleted);
                singleABLoaderDict.Add(abName, singleABLoader);

                yield return singleABLoader.LoadAssetBundle();
            }
        }

        /// <summary>
        /// 加載被引用AB包
        /// </summary>
        private IEnumerator LoadReference(string abName, string refABName) {
            
            if (abRelationDict.ContainsKey(abName)) {
                ABRelation tempABRelation = abRelationDict[abName];
                // 添加AB包被引用關系(被依賴)
                tempABRelation.AddReference(refABName);
            } else {
                ABRelation tempABRelation = new ABRelation(abName);
                tempABRelation.AddReference(refABName);
                abRelationDict.Add(abName, tempABRelation);

                // 開始加載依賴的包
                yield return LoadAssetBundle(abName);
            }
        }

        /// <summary>
        /// 加載(AB包中)資源
        /// </summary>
        public UnityEngine.Object LoadAsset(string abName, string assetName, bool isCache) {
            foreach (var item in singleABLoaderDict.Keys) {
                if (abName == item) {
                    return singleABLoaderDict[item].LoadAsset(assetName, isCache);
                }
            }

            Debug.LogError(GetType() + "/LoadAsset()/找不到AssetBundle包,無法加載資源,請檢查! abName = " + abName + ", assetName = " + assetName);

            return null;
        }

        /// <summary>
        /// 釋放本場景中所有的資源
        /// </summary>
        public void DisposeAllAsset() {
            try {
                foreach (var item in singleABLoaderDict.Values) {
                    item.DisposeAll();
                }
            } finally {
                singleABLoaderDict.Clear();
                singleABLoaderDict = null;

                abRelationDict.Clear();
                abRelationDict = null;

                currentABName = null;
                currentSceneName = null;
                loadCompleteHandler = null;

                Resources.UnloadUnusedAssets();
                System.GC.Collect();
            }
        }
    }
}
MultiABMgr
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace ABFramework {

    /// <summary>
    /// 框架主流程
    ///     2. WWW 加載AssetBundle
    /// 
    /// AB包內資源的加載
    /// 
    /// 功能:
    ///     1. 管理與加載指定AB的資源
    ///     2. 加載具有"緩存功能"的資源,帶選用參數
    ///     3. 卸載,釋放AB資源
    ///     4. 查看當前AB資源
    /// </summary>
    public class SingleABLoader : System.IDisposable {

        private AssetLoader assetLoader;

        private ABLoadComplete abLoadCompleteHandler;

        private string abName;

        private string abDownloadPath;


        public SingleABLoader(string abName, ABLoadComplete loadComplete) {
            assetLoader = null;

            abLoadCompleteHandler = loadComplete;

            this.abName = abName;
            abDownloadPath = PathTools.GetWWWPath() + "/" + abName;

        }

        public IEnumerator LoadAssetBundle() {
            using (WWW www = new WWW(abDownloadPath)) {
                yield return www;

                if (www.progress >= 1) {
                    AssetBundle ab = www.assetBundle;

                    if (ab != null) {
                        assetLoader = new AssetLoader(ab);

                        if (abLoadCompleteHandler != null) {
                            abLoadCompleteHandler(abName);
                        }

                    } else {
                        Debug.LogError(GetType() + "/LoadAssetBundle()/www下載出錯,請檢查! AssetBundle URL: " + abDownloadPath + " 錯誤信息: " + www.error);
                    }
                }
            }
        }

        /// <summary>
        /// 加載(AB包內)資源
        /// </summary>
        public UnityEngine.Object LoadAsset(string assetName, bool isCache) {
            if (assetLoader != null) {
                return assetLoader.LoadAsset(assetName, isCache);
            }
            Debug.LogError(GetType() + "/LoadAsset/assetLoader==null!, 請檢查!");
            return null;
        }

        /// <summary>
        /// 卸載(AB包內)資源
        /// </summary>
        public void UnLoadAsset(UnityEngine.Object asset) {
            if (assetLoader != null) {
                assetLoader.UnLoadAsset(asset);
            } else {
                Debug.LogError(GetType() + "/UnLoadAsset()/參數 assetLoader == null, 請檢查!");
            }
        }

        /// <summary>
        /// 釋放資源
        /// </summary>
        public void Dispose() {
            if (assetLoader != null) {
                assetLoader.Dispose();
                assetLoader = null;
            } else {
                Debug.LogError(GetType() + "/Dispose()/參數 assetLoader == null, 請檢查!");
            }
        }

        /// <summary>
        /// 釋放當前AssetBundle資源包,且卸載所有資源
        /// </summary>
        public void DisposeAll() {
            if (assetLoader != null) {
                assetLoader.DisposeAll();
                assetLoader = null;
            } else {
                Debug.LogError(GetType() + "/DisposeAll()/參數 assetLoader == null, 請檢查!");
            }
        }

        /// <summary>
        /// 查詢當前AssetBundle包中所有的資源
        /// </summary>
        public string[] GetAllAssetName() {
            if (assetLoader != null) {
                return assetLoader.GetAllAssetName();
            }
            Debug.LogError(GetType() + "/RetrieveAllAssetName()/參數 assetLoader == null, 請檢查!");

            return null;
        }
    }
}
SingleABLoader
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    public class Test_SingleABLoader : MonoBehaviour {

        private SingleABLoader loader = null;

        private string dependABName1 = "scene_1/textures.ab";
        private string dependABName2 = "scene_1/materials.ab";
        private string abName1 = "scene_1/prefabs.ab";
        

        private string assetName1 = "TestCubePrefab.prefab";

        #region 簡單(無依賴包)預設的加載

        //void Start() {
        //    loader = new SingleABLoader(abName1, LoadComplete);
        //    StartCoroutine(loader.LoadAssetBundle());
        //}

        //private void LoadComplete(string abName) {

        //    var prefab = loader.LoadAsset(assetName1, false);
        //    GameObject.Instantiate(prefab);
        //}

        #endregion

        void Start() {
            //SingleABLoader dependABLoader = new SingleABLoader(dependABName1, LoadDependAB1Complete);
            //StartCoroutine(dependABLoader.LoadAssetBundle());

            //StartCoroutine(ABManifestLoader.Instance.LoadManifest());
        }

        void Update() {
            if (Input.GetKeyDown(KeyCode.A)) {
                Debug.Log("釋放資源");
                //loader.Dispose();
                loader.DisposeAll();
            }    
        }

        private void LoadDependAB1Complete(string abName) {
            Debug.Log(abName + "加載完成");

            SingleABLoader dependABLoader = new SingleABLoader(dependABName2, LoadDependAB2Complete);
            StartCoroutine(dependABLoader.LoadAssetBundle());
        }

        private void LoadDependAB2Complete(string abName) {
            Debug.Log(abName + "加載完成");

            loader = new SingleABLoader(abName1, LoadAB1Complete);
            StartCoroutine(loader.LoadAssetBundle());
        }

        private void LoadAB1Complete(string abName) {
            Debug.Log(abName + "加載完成");

            var prefab = loader.LoadAsset(assetName1, false);
            GameObject.Instantiate(prefab);

            string[] arr = loader.GetAllAssetName();

            foreach (var item in arr) {
                Debug.Log(item);
            }
        }

    }
}
Test_SingleABLoader
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ABFramework {

    public class Test_Framework : MonoBehaviour {

        private string sceneName = "scene_1";

        private string abName = "scene_1/prefabs.ab";

        private string assetName = "TestCubePrefab.prefab";


        private void Start() {
            Debug.Log("開始 ABFramework 測試");

            // 調用AB包(連鎖智能調用AB包)
            StartCoroutine(AssetBundleMgr.Instance().LoadAssetBundle(sceneName, abName, LoadALLABComplete));
        }

        private void LoadALLABComplete(string abName) {
            Debug.Log("所有的AB包都已經加載完畢了");

            Object tempObj = AssetBundleMgr.Instance().LoadAsset(sceneName, abName, assetName, false);

            if (tempObj != null) {
                Instantiate(tempObj);
            }
        }

        private void Update() {
            if (Input.GetKeyDown(KeyCode.A)) {
                Debug.Log("測試銷毀資源");
                AssetBundleMgr.Instance().DisposeAllAsset(sceneName);
            }
        }
    }
}
Test_Framework

 

 

Lua編程 (已看)

  https://www.lua.org/

  https://www.runoob.com/lua/lua-tutorial.html

  https://github.com/rjpcomputing/luaforwindows/releases

  http://luadist.org/

 

xLua游戲中的熱更新(基於Unity2017) (已看)

  https://gameinstitute.qq.com/community/detail/111400

  https://github.com/Tencent/xLua

CSharpCallLua.lua.txt

print('hi')

a = 100
str = "siki"
isDie = false

person = {
    name = "siki1",
    11,
    22,
    33,
    44,
    age = 10,
    eat = function(self, a, b)
        print(a + b)
    end
}

function add(a, b)
    print(a + b)
    return a + b, a, b
end

--[[

function person:eat(a,b)
    print(a + b)
end

--]]

CSharpCallLua.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System;


public class CSharpCallLua : MonoBehaviour {

    void Start() {
        LuaEnv luaEnv = new LuaEnv();
        luaEnv.DoString("require 'CSharpCallLua'");

        int a = luaEnv.Global.Get<int>("a");
        print(a);

        string str = luaEnv.Global.Get<string>("str");
        print(str);

        bool isDie = luaEnv.Global.Get<bool>("isDie");
        print(isDie);

        //Person p = luaEnv.Global.Get<Person>("person");
        //print(p.name + "-" + p.age);

        //IPerson p = luaEnv.Global.Get<IPerson>("person");
        //print(p.name + "-" + p.age);
        //p.name = "Sikiedu.com";
        //p.eat(12, 34);
        //luaEnv.DoString("print(person.name)");
        //luaEnv.Dispose();


        //Dictionary<string,object> dict = luaEnv.Global.Get<Dictionary<string, object>>("person");

        //foreach (string key in dict.Keys) {
        //    print(key + "-" + dict[key]);
        //}

        //List<object> list = luaEnv.Global.Get<List<object>>("person");

        //foreach (object o in list) {
        //    print(o);
        //}

        //LuaTable tab = luaEnv.Global.Get<LuaTable>("person");
        //print(tab.Get<string>("name"));
        //print(tab.Length);

        //Action<int, int> act = luaEnv.Global.Get<Action<int, int>>("add");
        //act(1, 2);

        //Add add = luaEnv.Global.Get<Add>("add");
        //int resa, resb;
        //int res = add(1, 2, out resa, out resb);
        //print(res + " " + resa + " " + resb);

        LuaFunction func = luaEnv.Global.Get<LuaFunction>("add");
        object[] os = func.Call(1, 2);
        foreach (object o in os) {
            print(o);
        }


        luaEnv.Dispose();
    }

    [CSharpCallLua]
    delegate int Add(int a, int b, out int resa, out int resb);

    class Person {
        public string name;
        public int age;
    }

    [CSharpCallLua]
    interface IPerson {
        string name { get; set; }
        int age { get; set; }
        void eat(int a, int b);
    }
}


LuaCallCSharp.lua.txt

CS.UnityEngine.GameObject("new by lua")

print(CS.UnityEngine.Time.deltaTime)

local camera = CS.UnityEngine.GameObject.Find("Main Camera")
camera.name = "update"

local cameraCom = camera:GetComponent("Camera")
CS.UnityEngine.GameObject.Destroy(cameraCom)

LuaCallCSharp.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class LuaCallCSharp : MonoBehaviour {

    // Use this for initialization
    void Start () {
        LuaEnv luaEnv = new LuaEnv();

        luaEnv.DoString("require 'LuaCallCSharp'");

        luaEnv.Dispose();
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}
View Code

 

游戲熱更新實戰案例(基於xLua) (已看)

1.0版本

Effect

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 星星閃耀的特效
/// </summary>
public class Shine : MonoBehaviour {

    private Image img;
    public float speed=4;
    private bool add;

    public void Awake()
    {
        img = GetComponent<Image>();
    }
    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        transform.Rotate(Vector3.forward * 4, Space.World);
        if (!add)
        {
            img.color -= new Color(0, 0, 0, Time.deltaTime * speed);
            if (img.color.a <=0.2f)
            {
                add = true;
            }
        }
        else
        {
            img.color += new Color(0, 0, 0, Time.deltaTime * speed);
            if (img.color.a >=0.8f)
            {
                add = false;
            }
        }
        

       
        

        
        
    }
}
Shine  Main/Canvas/Panel/UI_Stars/Img_Star
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 隱藏顯示閃耀UI的特效,比如槍,星星
/// </summary>
public class ShineHide : MonoBehaviour {
    private float timeVal = 0;
    private bool isAdd = false;
    private Image img;
    public float defineTime = 3;
    void Awake()
    {
        img = GetComponent<Image>();

    }

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        timeVal += Time.deltaTime;
        if (!isAdd)
        {
            img.color -= new Color(0, 0, 0, Time.deltaTime * 5);
            if (timeVal > defineTime)
            {
                img.color = new Color(img.color.r, img.color.g, img.color.b, 0);
                isAdd = true;
                timeVal = 0;
            }
        }
        else
        {
            img.color += new Color(0, 0, 0, Time.deltaTime * 5);
            if (timeVal > defineTime)
            {
                img.color = new Color(img.color.r, img.color.g, img.color.b, 1);
                isAdd = false;
                timeVal = 0;
            }

        }
    }

}

    

            
        

    
ShineHide  Main/Canvas/Panel/UI_StartGame/But_StartGame
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 爆炸特效
/// </summary>
public class Explosion : MonoBehaviour {

    public float DestoryTime = 0.2f;

    // Use this for initialization
    void Start () {
        Destroy(this.gameObject, DestoryTime);
    }
    
    // Update is called once per frame
    void Update () {
        transform.localScale +=new Vector3(Time.deltaTime*10, Time.deltaTime*10, Time.deltaTime*10) ;
    }
}
Explosion  Prefabs/Effects/explosion...
using UnityEngine;
using System.Collections;

public class Pao : MonoBehaviour {
/// <summary>
/// 游戲中產生的泡泡
/// </summary>
    public int moveSpeed;
    public bool isGamePao;

    // Use this for initialization
    void Start () {
        
        
        if (isGamePao)
        {
            moveSpeed = Random.Range(2, 4);
            Destroy(this.gameObject, Random.Range(0.5f, 1f));
        }
        else
        {
            moveSpeed = Random.Range(40, 100);
            Destroy(this.gameObject, Random.Range(7f, 10f));
        }
    }
    
    // Update is called once per frame
    void Update () {
        transform.Translate(-transform.right*moveSpeed*Time.deltaTime,Space.World);
    }
}
Pao  Prefabs/Effects/Pao
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// boss攻擊玩家產生的震動方法
/// </summary>
public class Shake : MonoBehaviour {


    private float cameraShake = 2;
    public GameObject UI;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        if (Gun.Instance.bossAttack)
        {

            UI.SetActive(true);
            transform.position = new Vector3((Random.Range(0f, cameraShake)) - cameraShake*0.5f, transform.position.y, transform.position.z);
            transform.position = new Vector3(transform.position.x, transform.position.y, (Random.Range(0f, cameraShake)) - cameraShake * 0.5f);
            cameraShake = cameraShake / 1.05f;
            if (cameraShake<0.05f)
            {

                cameraShake= 0;
                UI.SetActive(false);
                Gun.Instance.bossAttack = false;
            }
        }
        else
        {
            cameraShake = 5;
        }
    }
}
Shake  Fish/Main Camera
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 隱藏顯示閃耀UI的特效,比如槍,星星
/// </summary>
public class ShineHide : MonoBehaviour {
    private float timeVal = 0;
    private bool isAdd = false;
    private Image img;
    public float defineTime = 3;
    void Awake()
    {
        img = GetComponent<Image>();

    }

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        timeVal += Time.deltaTime;
        if (!isAdd)
        {
            img.color -= new Color(0, 0, 0, Time.deltaTime * 5);
            if (timeVal > defineTime)
            {
                img.color = new Color(img.color.r, img.color.g, img.color.b, 0);
                isAdd = true;
                timeVal = 0;
            }
        }
        else
        {
            img.color += new Color(0, 0, 0, Time.deltaTime * 5);
            if (timeVal > defineTime)
            {
                img.color = new Color(img.color.r, img.color.g, img.color.b, 1);
                isAdd = false;
                timeVal = 0;
            }

        }
    }

}

    

            
        

    
ShineHide  Fish/Canvas/Img_Gun/Img_GunLight
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 水紋播放的特效
/// </summary>
public class Water : MonoBehaviour {

    private SpriteRenderer sr;

    public Sprite[] pictures;

    private int count=0;

    // Use this for initialization
    void Start () {
        sr = GetComponent<SpriteRenderer>();
    }
    
    // Update is called once per frame
    void Update () {
        sr.sprite = pictures[count];
        count++;
        if (count==pictures.Length)
        {
            count = 0;
        }
    }
}
Water  Prefabs/Enemy/Fish1/Fire

Enemy

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 擋子彈的氣泡
/// </summary>
public class Qipao : MonoBehaviour {

    //屬性
    public float moveSpeed = 2;


    //計時器
    private float rotateTime;

    // Use this for initialization
    void Start()
    {
        Destroy(this.gameObject, 14);
    }

    // Update is called once per frame
    void Update()
    {
       
        fishMove();
    }

    public void fishMove()
    {
        transform.Translate(transform.right * moveSpeed * Time.deltaTime, Space.World);
        if (rotateTime >= 5)
        {
            transform.Rotate(transform.forward * Random.Range(0, 361), Space.World);
            rotateTime = 0;
        }
        else
        {
            rotateTime += Time.deltaTime;
        }
    }

    public void TakeDamage(int attackValue)
    {
        Destroy(this.gameObject);
    }
}
Qipao  Prefabs/Enemy/Qipao
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// boss腳本
/// </summary>

public class Boss : MonoBehaviour
{

    public int hp = 50;

    public GameObject deadEeffect;
    public int GetGold = 10;
    public int GetDiamands = 10;
    public GameObject diamands;
    public GameObject gold;
    public float moveSpeed = 2;
    protected int m_reduceGold;
    protected int m_reduceDiamond;

    protected Transform playerTransform;

    protected GameObject fire;
    protected GameObject ice;
    protected Animator iceAni;
    protected Animator gameObjectAni;
    protected AudioSource bossAudio;

    //計時器
    private float rotateTime;
    private float timeVal;

    protected bool hasIce;
    protected bool isAttack;

    void Start()
    {
        fire = transform.Find("Fire").gameObject;
        ice = transform.Find("Ice").gameObject;
        iceAni = ice.transform.GetComponent<Animator>();
        gameObjectAni = GetComponent<Animator>();
        bossAudio = GetComponent<AudioSource>();
        playerTransform = Gun.Instance.transform;
        m_reduceGold = 10;
        m_reduceDiamond = 0;
    }

    // Update is called once per frame
    void Update()
    {
        //冰凍效果
        if (Gun.Instance.Ice)
        {
            gameObjectAni.enabled = false;
            ice.SetActive(true);
            if (!hasIce)
            {
                iceAni.SetTrigger("Ice");
                hasIce = true;
            }


        }
        else
        {
            gameObjectAni.enabled = true;
            hasIce = false;
            ice.SetActive(false);
        }
        //灼燒效果
        if (Gun.Instance.Fire)
        {
            fire.SetActive(true);

        }
        else
        {
            fire.SetActive(false);
        }
        if (Gun.Instance.Ice)
        {
            return;
        }
        //boss的行為方法
        Attack(m_reduceGold, m_reduceDiamond);
        if (!isAttack)
        {
            fishMove();
        }

    }

    public virtual void TakeDamage(int attackValue)
    {
        if (Gun.Instance.Fire)
        {
            attackValue *= 2;
        }

        hp -= attackValue;
        if (hp <= 0)
        {
            Instantiate(deadEeffect, transform.position, transform.rotation);
            Gun.Instance.GoldChange(GetGold * 10);
            Gun.Instance.DiamandsChange(GetDiamands * 10);

            for (int i = 0; i < 11; i++)
            {
                GameObject itemGo = Instantiate(gold, transform.position, Quaternion.Euler(transform.eulerAngles + new Vector3(0, 18 + 36 * (i - 1), 0)));
                itemGo.GetComponent<Gold>().bossPrize = true;
            }
            for (int i = 0; i < 11; i++)
            {
                GameObject itemGo = Instantiate(diamands, transform.position, Quaternion.Euler(transform.eulerAngles + new Vector3(0, 36 + 36 * (i - 1), 0)));
                itemGo.GetComponent<Gold>().bossPrize = true;
            }
            Destroy(this.gameObject);
        }
    }
    public void fishMove()
    {
        transform.Translate(transform.right * moveSpeed * Time.deltaTime, Space.World);
        if (rotateTime >= 5)
        {
            transform.Rotate(transform.forward * Random.Range(0, 361), Space.World);
            rotateTime = 0;
        }
        else
        {
            rotateTime += Time.deltaTime;
        }
    }


    public void Attack(int reduceGold, int reduceDiamond)
    {
        if (timeVal > 20)
        {
            transform.LookAt(playerTransform);
            transform.eulerAngles += new Vector3(90, -90, 0);

            isAttack = true;
            timeVal = 0;
        }
        else
        {
            timeVal += Time.deltaTime;
        }
        if (isAttack)
        {

            gameObjectAni.SetBool("isAttack", true);
            transform.position = Vector3.Lerp(transform.position, playerTransform.position, 1 / Vector3.Distance(transform.position, playerTransform.position) * Time.deltaTime * moveSpeed);
            if (Vector3.Distance(transform.position, playerTransform.position) <= 4)
            {
                if (reduceGold != 0)
                {
                    Gun.Instance.GoldChange(reduceGold);
                }
                if (reduceDiamond != 0)
                {
                    Gun.Instance.DiamandsChange(reduceDiamond);
                }

                gameObjectAni.SetBool("isAttack", false);
                isAttack = false;
                Gun.Instance.BossAttack();
                rotateTime = 0;
                Invoke("ReturnAngle", 4);
            }
        }
    }





    public void ReturnAngle()
    {
        transform.eulerAngles = new Vector3(90, 0, 0);
    }
}
Boss  Prefabs/Enemy/Boss2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 產魚器
/// </summary>

public class CreateFish : MonoBehaviour
{

    //引用
    public GameObject[] fishList;
    public GameObject[] item;
    public GameObject boss;
    public GameObject boss2;
    public GameObject boss3;
    public Transform[] CreateFishPlace;


    private float ItemtimeVal = 0;//游戲物體計時器
    private float createManyFish;
    private float timeVals = 0;

    //成員變量
    private int num;
    private int ItemNum;
    private int placeNum;
    private int CreateMorden;



    //x:-26  -   26
    //z:-16  -   16
    private void Awake()
    {

    }
    // Use this for initialization
    void Start()
    {


    }

    void Update()
    {



        //魚群的生成
        CreateALotOfFish();


        //單種魚的生成
        if (ItemtimeVal >= 0.5)
        {
            //位置隨機數
            num = Random.Range(0, 4);
            //游戲物體隨機數
            ItemNum = Random.Range(1, 101);


            //產生氣泡
            if (ItemNum < 20)
            {
                CreateGameObject(item[3]);
                CreateGameObject(fishList[6]);
            }
            //貝殼10% 85-94 
            //第一種魚42% 42
            if (ItemNum <= 42)
            {
                CreateGameObject(fishList[0]);
                CreateGameObject(item[0]);
                CreateGameObject(fishList[3]);
                CreateGameObject(item[0]);
            }
            //第二種魚30% 43-72
            else if (ItemNum >= 43 && ItemNum < 72)
            {
                CreateGameObject(fishList[1]);
                CreateGameObject(item[0]);
                CreateGameObject(fishList[4]);
            }
            //第三種魚10% 73-84
            else if (ItemNum >= 73 && ItemNum < 84)
            {
                CreateGameObject(fishList[2]);
                CreateGameObject(fishList[5]);
            }

            //第一種美人魚5%,第二種3%  95-98  99-100


            else if (ItemNum >= 94 && ItemNum <= 98)
            {
                CreateGameObject(item[1]);
            }

            else if (ItemNum >= 84 && ItemNum < 86)
            {

                CreateGameObject(boss2);
            }

            else if (ItemNum > 98 && ItemNum < 100)
            {
                CreateGameObject(item[2]);
                CreateGameObject(boss);
            }


            else
            {
                CreateGameObject(item[0]);
                CreateGameObject(boss3);
            }
            ItemtimeVal = 0;
        }
        else
        {
            ItemtimeVal += Time.deltaTime;
        }

    }

    //生成魚群
    private void CreateALotOfFish()
    {
        if (createManyFish >= 15)
        {


            if (CreateMorden == 2)
            {
                GameObject go = fishList[Random.Range(2, fishList.Length)];
                for (int i = 0; i < 11; i++)
                {
                    GameObject itemGo = Instantiate(go, transform.position, Quaternion.Euler(transform.eulerAngles + new Vector3(0, 45 * i, 0)));
                    itemGo.GetComponent<Fish>().cantRotate = true;
                }
                createManyFish = 0;
            }
            else if (CreateMorden == 0 || CreateMorden == 1)
            {
                createManyFish += Time.deltaTime;
                if (createManyFish >= 18)
                {
                    createManyFish = 0;
                }
                if (timeVals >= 0.2f)
                {
                    int num = Random.Range(0, 2);
                    GameObject itemGo = Instantiate(fishList[num], CreateFishPlace[placeNum].position + new Vector3(0, 0, Random.Range(-2, 2)), CreateFishPlace[placeNum].rotation);
                    itemGo.GetComponent<Fish>().cantRotate = true;
                    timeVals = 0;
                }
                else
                {
                    timeVals += Time.deltaTime;
                }
            }



        }
        else
        {
            createManyFish += Time.deltaTime;
            placeNum = Random.Range(0, 2);
            CreateMorden = Random.Range(0, 3);
        }
    }

    private void CreateFishs(GameObject go)
    {
        Instantiate(go, RandomPos(num), Quaternion.Euler(go.transform.eulerAngles));
    }

    //產生游戲物體
    private void CreateGameObject(GameObject go)
    {
        Instantiate(go, RandomPos(num), Quaternion.Euler(RandomAngle(num) + go.transform.eulerAngles));
    }
    //隨機位置
    private Vector3 RandomPos(int num)
    {
        Vector3 Vpositon = new Vector3();

        switch (num)
        {
            case 0:
                Vpositon = new Vector3(-24, 1, Random.Range(-14f, 14f));//-30  -  30
                break;
            case 1:
                Vpositon = new Vector3(Random.Range(-24f, 24f), 1, 14);//60 - 120
                break;
            case 2:
                Vpositon = new Vector3(24, 1, Random.Range(-14f, 14f));//150-210
                break;
            case 3:
                Vpositon = new Vector3(Random.Range(-24f, 24f), 1, -14);//-60-  -120
                break;
            default:
                break;
        }
        return Vpositon;
    }
    //隨機角度
    private Vector3 RandomAngle(int num)
    {
        Vector3 Vangle = new Vector3();
        switch (num)
        {
            case 0:
                Vangle = new Vector3(0, Random.Range(-30f, 30f), 0);//-30  -  30
                break;
            case 1:
                Vangle = new Vector3(0, Random.Range(60f, 120f), 0);//60 - 120
                break;
            case 2:
                Vangle = new Vector3(0, Random.Range(150f, 210f), 0);//150-210
                break;
            case 3:
                Vangle = new Vector3(0, Random.Range(-60f, -120f), 0);//-60-  -120
                break;
            default:
                break;
        }
        return Vangle;
    }

}
CreateFish  Fish/CreateFish/Place/FishCreate
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 有護盾的boss
/// </summary>
public class DeffendBoss : Boss
{

    private bool isDeffend = false;

    private float deffendTime = 0;

    public GameObject deffend;


    void Start()
    {
        fire = transform.Find("Fire").gameObject;
        ice = transform.Find("Ice").gameObject;
        iceAni = ice.transform.GetComponent<Animator>();
        gameObjectAni = GetComponent<Animator>();
        bossAudio = GetComponent<AudioSource>();
        playerTransform = Gun.Instance.transform;
    }

    // Update is called once per frame
    void Update()
    {
        //冰凍效果
        if (Gun.Instance.Ice)
        {
            gameObjectAni.enabled = false;
            ice.SetActive(true);
            if (!hasIce)
            {
                iceAni.SetTrigger("Ice");
                hasIce = true;
            }


        }
        else
        {
            gameObjectAni.enabled = true;
            hasIce = false;
            ice.SetActive(false);
        }
        //灼燒效果
        if (Gun.Instance.Fire)
        {
            fire.SetActive(true);

        }
        else
        {
            fire.SetActive(false);
        }
        if (Gun.Instance.Ice)
        {
            return;
        }
        //boss的行為方法
        Attack(m_reduceGold, m_reduceDiamond);
        if (!isAttack)
        {
            fishMove();
        }
        //保護方法
        if (deffendTime >= 10)
        {
            deffendTime = 0;
            DeffenMe();
        }
        else
        {
            deffendTime += Time.deltaTime;
        }
    }

    void DeffenMe()
    {
        isDeffend = true;
        deffend.SetActive(true);
        Invoke("CloseDeffendMe", 3);
    }

    private void CloseDeffendMe()
    {
        deffend.SetActive(false);
        isDeffend = false;
    }

    public override void TakeDamage(int attackValue)
    {
        if (isDeffend)
        {
            return;
        }
        base.TakeDamage(attackValue);
    }

}
DeffendBoss  Prefabs/Enemy/Boss1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 普通魚的類
/// </summary>

public class Fish : MonoBehaviour
{


    //屬性
    public float moveSpeed = 2;
    public int GetCold = 10;
    public int GetDiamands = 10;
    public int hp = 5;

    //計時器
    private float rotateTime;
    private float timeVal;

    //引用
    public GameObject gold;
    public GameObject diamands;
    private GameObject fire;
    private GameObject ice;
    private Animator iceAni;
    private Animator gameObjectAni;
    private SpriteRenderer sr;
    public GameObject pao;

    //開關
    private bool hasIce = false;
    public bool isnet;
    private bool isDead = false;
    public bool cantRotate = false;

    // Use this for initialization
    void Start()
    {
        fire = transform.Find("Fire").gameObject;
        ice = transform.Find("Ice").gameObject;
        iceAni = ice.transform.GetComponent<Animator>();
        gameObjectAni = GetComponent<Animator>();
        sr = GetComponent<SpriteRenderer>();
        Destroy(this.gameObject, 20);

    }

    // Update is called once per frame
    void Update()
    {
        if (timeVal >= 14 || isDead)
        {
            sr.color -= new Color(0, 0, 0, Time.deltaTime);
        }
        else
        {
            timeVal += Time.deltaTime;
        }

        if (isDead)
        {
            return;
        }
        //冰凍效果
        if (Gun.Instance.Ice)
        {
            gameObjectAni.enabled = false;
            ice.SetActive(true);
            if (!hasIce)
            {
                iceAni.SetTrigger("Ice");
                hasIce = true;
            }


        }
        else
        {
            gameObjectAni.enabled = true;
            hasIce = false;
            ice.SetActive(false);
        }

        //灼燒方法
        if (Gun.Instance.Fire)
        {
            fire.SetActive(true);

        }
        else
        {
            fire.SetActive(false);
        }

        if (Gun.Instance.Ice)
        {
            return;
        }
        if (isnet)
        {
            Invoke("Net", 0.5f);
            return;
        }
        fishMove();
    }
    public void Net()
    {
        if (isnet)
        {
            isnet = false;
        }

    }

    public void fishMove()
    {
        transform.Translate(transform.right * moveSpeed * Time.deltaTime, Space.World);
        if (cantRotate)
        {
            return;
        }
        if (rotateTime >= 5)
        {
            transform.Rotate(transform.forward * Random.Range(0, 361), Space.World);
            rotateTime = 0;
        }
        else
        {
            rotateTime += Time.deltaTime;
        }
    }
    public void TakeDamage(int attackValue)
    {
        if (Gun.Instance.Fire)
        {
            attackValue *= 2;
        }
        hp -= attackValue;
        if (hp <= 0)
        {
            isDead = true;
            for (int i = 0; i < 9; i++)
            {
                Instantiate(pao, transform.position, Quaternion.Euler(transform.eulerAngles + new Vector3(0, 45 * i, 0)));
            }

            gameObjectAni.SetTrigger("Die");
            Invoke("Prize", 0.7f);
        }
    }
    private void Prize()
    {
        Gun.Instance.GoldChange(GetCold);
        if (GetDiamands != 0)
        {
            Gun.Instance.DiamandsChange(GetDiamands);
            Instantiate(diamands, transform.position, transform.rotation);
        }

        Instantiate(gold, transform.position, transform.rotation);

        Destroy(this.gameObject);
    }
}
Fish  Prefabs/Enemy/Fish
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 會隱藏的boss
/// </summary>
public class InvisibleBoss : Boss
{

    private bool isInvisible = false;

    private float invisibleTime = 0;
    private float recoverTime = 0;

    private BoxCollider box;
    private SpriteRenderer sr;


    void Start()
    {
        fire = transform.Find("Fire").gameObject;
        ice = transform.Find("Ice").gameObject;
        iceAni = ice.transform.GetComponent<Animator>();
        gameObjectAni = GetComponent<Animator>();
        box = GetComponent<BoxCollider>();
        sr = GetComponent<SpriteRenderer>();
        bossAudio = GetComponent<AudioSource>();
        playerTransform = Gun.Instance.transform;
    }

    // Update is called once per frame
    void Update()
    {
        //冰凍效果
        if (Gun.Instance.Ice)
        {
            gameObjectAni.enabled = false;
            ice.SetActive(true);
            if (!hasIce)
            {
                iceAni.SetTrigger("Ice");
                hasIce = true;
            }


        }
        else
        {
            gameObjectAni.enabled = true;
            hasIce = false;
            ice.SetActive(false);
        }
        //灼燒效果
        if (Gun.Instance.Fire)
        {
            fire.SetActive(true);

        }
        else
        {
            fire.SetActive(false);
        }
        if (Gun.Instance.Ice)
        {
            return;
        }
        //boss的行為方法
        Attack(m_reduceGold, m_reduceDiamond);
        if (!isAttack)
        {
            fishMove();
        }
        //隱形方法
        if (invisibleTime >= 10)
        {
            invisibleTime = 0;
            Invisible();
        }
        else
        {
            invisibleTime += Time.deltaTime;
        }
        if (isInvisible)
        {
            sr.color -= new Color(0, 0, 0, Time.deltaTime);
            box.enabled = false;
        }
        else
        {
            sr.color += new Color(0, 0, 0, Time.deltaTime);
            if (recoverTime >= 3)
            {
                recoverTime = 0;
                sr.color = new Color(sr.color.r, sr.color.g, sr.color.b, 1);
            }
            else
            {
                recoverTime += Time.deltaTime;
            }
            box.enabled = true;
        }
    }

    private void Invisible()
    {
        isInvisible = true;
        Invoke("CloseInvisible", 3);
    }

    private void CloseInvisible()
    {
        isInvisible = false;
    }
}
InvisibleBoss  Prefabs/Enemy/Boss3

Item

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 鋪到貝殼的道具卡
/// </summary>
public class Card : MonoBehaviour {

    private Transform playerTransform;

    public int num;

    public Sprite[] cards;

    private SpriteRenderer sr;

    private AudioSource audios;
    

    // Use this for initialization
    void Start () {
        Destroy(this.gameObject,1);
        audios = GetComponent<AudioSource>();
        sr = GetComponent<SpriteRenderer>();
        sr.sprite = cards[num];
        audios.Play();

    }
    
    // Update is called once per frame
    void Update () {
        
            
        
    }
}
Card  Prefabs/Item/Card
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 漁網
/// </summary>
public class FishNet : MonoBehaviour {


    // Use this for initialization
    void Start () {
        Destroy(this.gameObject,0.2f);
    }
    
    // Update is called once per frame
    void Update () {
        //transform.Translate(-Vector3.up * moveSpeed * Time.deltaTime,Space.World);
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag=="fish")
        {
            other.GetComponent<Fish>().isnet = true;
            
        }
        
    }
}
FishNet  Prefabs/Item/Net
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 金幣,鑽石
/// </summary>
public class Gold : MonoBehaviour
{

    public enum ThePlaceTo
    {
        gold,
        diamands,
        imageGold,
        imageDiamands
    }
    public ThePlaceTo thePlaceTo;
    private Transform playerTransform;
    public float moveSpeed = 3;
    public GameObject star2;

    private AudioSource audios;
    public AudioClip goldAudio;
    public AudioClip diamandsAudio;

    private float timeVal2;
    public float defineTime2;
    private float timeBecome;
    private float timeVal3;

    public bool bossPrize = false;
    private bool beginMove = false;
    // Use this for initialization
    private void Awake()
    {
        audios = GetComponent<AudioSource>();
        switch (thePlaceTo)
        {
            case ThePlaceTo.gold:
                playerTransform = Gun.Instance.goldPlace;
                audios.clip = goldAudio;
                break;
            case ThePlaceTo.diamands:
                playerTransform = Gun.Instance.diamondsPlace;
                audios.clip = diamandsAudio;
                break;
            case ThePlaceTo.imageGold:
                playerTransform = Gun.Instance.imageGoldPlace;
                audios.clip = goldAudio;
                break;
            case ThePlaceTo.imageDiamands:
                playerTransform = Gun.Instance.imageDiamandsPlace;
                audios.clip = diamandsAudio;
                break;
            default:
                break;
        }
        audios.Play();

    }

    void Start()
    {


    }

    // Update is called once per frame
    void Update()
    {

        if (timeBecome >= 0.5f)
        {
            beginMove = true;
        }
        else
        {
            timeBecome += Time.deltaTime;
        }
        if (beginMove)
        {
            transform.position = Vector3.Lerp(transform.position, playerTransform.position, 1 / Vector3.Distance(transform.position, playerTransform.position) * Time.deltaTime * moveSpeed);
            if (thePlaceTo == ThePlaceTo.imageDiamands || thePlaceTo == ThePlaceTo.imageGold)
            {
                if (Vector3.Distance(transform.position, playerTransform.position) <= 2)
                {
                    Destroy(this.gameObject);
                }
                return;
            }
            if (transform.position == playerTransform.position)
            {
                Destroy(this.gameObject);
            }

            timeVal2 = InistStar(timeVal2, defineTime2, star2);
        }
        else
        {
            transform.localScale += new Vector3(Time.deltaTime * 3, Time.deltaTime * 3, Time.deltaTime * 3);
            if (bossPrize)
            {
                if (timeVal3 <= 0.3f)
                {
                    timeVal3 += Time.deltaTime;
                    transform.Translate(transform.right * moveSpeed * Time.deltaTime, Space.World);
                }

            }
        }

    }


    private float InistStar(float timeVals, float defineTimes, GameObject stars)
    {

        if (timeVals >= defineTimes)
        {
            Instantiate(stars, this.transform.position, Quaternion.Euler(this.transform.eulerAngles.x, this.transform.eulerAngles.y, this.transform.eulerAngles.z + Random.Range(-40f, 40f)));
            timeVals = 0;
        }
        else
        {
            timeVals += Time.deltaTime;
        }

        return timeVals;
    }
}
Gold  Prefabs/Item/Gold
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 美人魚
/// </summary>
public class Missile : MonoBehaviour {

    //屬性
    public int hp=15;
    public int GetGold = 10;
    public float moveSpeed=5;

    //引用
    public GameObject gold;
    private GameObject fire;
    private GameObject ice;
    private Animator iceAni;
    private Animator gameObjectAni;
    public GameObject deadEeffect;
    private SpriteRenderer sr;
    //計時器
    private float rotateTime;

    //開關
    private bool hasIce = false;
    private float timeVal;

    // Use this for initialization
    void Start () {
        fire = transform.Find("Fire").gameObject;
        ice = transform.Find("Ice").gameObject;
        iceAni = ice.transform.GetComponent<Animator>();
        gameObjectAni = GetComponent<Animator>();
        sr = GetComponent<SpriteRenderer>();
        Destroy(this.gameObject, 8);
    }
    
    // Update is called once per frame
    void Update () {
        if (timeVal >= 7)
        {
            sr.color -= new Color(0, 0, 0, Time.deltaTime);
        }
        else
        {
            timeVal += Time.deltaTime;
        }
        //冰凍效果
        if (Gun.Instance.Ice)
        {
            gameObjectAni.enabled = false;
            ice.SetActive(true);
            if (!hasIce)
            {
                iceAni.SetTrigger("Ice");
                hasIce = true;
            }


        }
        else
        {
            gameObjectAni.enabled = true;
            hasIce = false;
            ice.SetActive(false);
        }

        //灼燒效果
        if (Gun.Instance.Fire)
        {
            fire.SetActive(true);

        }
        else
        {
            fire.SetActive(false);
        }

        if (Gun.Instance.Ice)
        {
            return;
        }
        transform.Translate(transform.right * moveSpeed * Time.deltaTime, Space.World);
        if (rotateTime >= 5)
        {
            transform.Rotate(transform.forward * Random.Range(0, 361), Space.World);
            rotateTime = 0;
        }
        else
        {
            rotateTime += Time.deltaTime;
        }
    }

    public void Lucky(int attckValue)
    {

        Gun.Instance.GoldChange(GetGold);
        Instantiate(gold, transform.position, transform.rotation);
        if (Gun.Instance.Fire)
        {
            attckValue *= 2;
        }
        hp -= attckValue;
        if (hp<=0)
        {
            Instantiate(deadEeffect, transform.position, transform.rotation);
            gameObjectAni.SetTrigger("Die");
            Invoke("Prize", 0.7f);
            
        }
    }
    private void Prize()
    {
        Gun.Instance.GoldChange(GetGold * 10);
        for (int i = 0; i < 5; i++)
        {
            Instantiate(gold, transform.position + new Vector3(-5f + i, 0, 0), transform.rotation);
        }
        Destroy(this.gameObject);
    }
}
Missile  Prefabs/Item/Missile
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 貝殼
/// </summary>
public class Shell : MonoBehaviour {
    //計時器
    private float rotateTime;
    private float timeVal = 0;//無敵狀態計時器
    
    //屬性
    public float moveSpeed = 5;

    //開關
    private bool isDeffend=true;
    private bool hasIce = false;

   
    //引用
    public GameObject card;
    private GameObject fire;
    private GameObject ice;
    private Animator iceAni;
    private Animator gameObjectAni;
    private SpriteRenderer sr;
    private float timeVals;
    

    // Use this for initialization
    void Start () {
        fire = transform.Find("Fire").gameObject;
        ice = transform.Find("Ice").gameObject;
        iceAni = ice.transform.GetComponent<Animator>();
        gameObjectAni = GetComponent<Animator>();
        sr = GetComponent<SpriteRenderer>();
        Destroy(this.gameObject,10);
    }
    
    // Update is called once per frame
    void Update () {

        if (timeVals >= 9)
        {
            sr.color -= new Color(0, 0, 0, Time.deltaTime);
        }
        else
        {
            timeVals += Time.deltaTime;
        }
        //灼燒效果
        if (Gun.Instance.Fire)
        {
            fire.SetActive(true);

        }
        else
        {
            fire.SetActive(false);
        }
        //冰凍效果
        if (Gun.Instance.Ice)
        {
            gameObjectAni.enabled = false;
            ice.SetActive(true);
            if (!hasIce)
            {
                iceAni.SetTrigger("Ice");
                hasIce = true;
            }
            

        }
        else
        {
            gameObjectAni.enabled = true;
            hasIce = false;
            ice.SetActive(false);
        }

        if (Gun.Instance.Ice)
        {
            return;
        }
        transform.Translate(transform.right * moveSpeed * Time.deltaTime, Space.World);
        if (rotateTime >= 5)
        {
            transform.Rotate(transform.forward * Random.Range(0, 361), Space.World);
            rotateTime = 0;
        }
        else
        {
            rotateTime += Time.deltaTime;
        }
        if (timeVal<1)
        {
           
            timeVal += Time.deltaTime;
        }
        else if (timeVal>=1&&timeVal<1.5)
        {
           
            timeVal += Time.deltaTime;
            isDeffend = false;
        }
        else if (timeVal>=1.5)
        {
         
            isDeffend = true;
            timeVal = 0;
        }
    }

    public void GetEffects()
    {
        if (isDeffend)
        {
           
            return;
        }
        else
        {
            int num = Random.Range(0, 3);
            
            switch (num)
            {
                case 0:Gun.Instance.CanShootForFree();
                    break;
                case 1:Gun.Instance.CanGetDoubleGold();
                    break;
                case 2:Gun.Instance.CanShootNoCD();
                    break;
                default:
                    break;
            }
            GameObject go= Instantiate(card, transform.position, card.transform.rotation) as GameObject;
            go.GetComponent<Card>().num = num;
            Destroy(this.gameObject);
        }
    }
}
Shell  Prefabs/Item/Shell

Player

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
////// </summary>

public class Gun : MonoBehaviour
{




    //屬性
    public int gold = 100;
    public int diamands = 50;
    public int gunLevel = 1;
    private float rotateSpeed = 5f;
    public float attackCD = 1;
    private float GunCD = 4;
    public int level = 1;

    //引用

    public AudioClip[] bullectAudios;
    private AudioSource bullectAudio;
    public Transform attackPos;
    public GameObject[] Bullects;
    public GameObject net;
    public GunChange[] gunChange;


    public Transform goldPlace;
    public Transform diamondsPlace;
    public Transform imageGoldPlace;
    public Transform imageDiamandsPlace;


    public Text goldText;
    public Text diamandsText;


    //開關
    private bool canShootForFree = false;
    private bool canGetDoubleGold = false;
    public bool canShootNoCD = false;
    public bool canChangeGun = true;
    public bool bossAttack = false;
    public bool Fire = false;
    public bool Ice = false;
    public bool Butterfly = false;
    public bool attack = false;


    public bool changeAudio;


    private static Gun instance;
    public static Gun Instance
    {
        get
        {
            return instance;
        }

        set
        {
            instance = value;
        }
    }

    private void Awake()
    {
        instance = this;
        gold = 1000;
        diamands = 1000;
        level = 2;
        bullectAudio = GetComponent<AudioSource>();
    }

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {



        goldText.text = gold.ToString();
        diamandsText.text = diamands.ToString();


        //旋轉槍的方法

        RotateGun();





        if (GunCD <= 0)
        {
            canChangeGun = true;
            GunCD = 4;

        }
        else
        {
            GunCD -= Time.deltaTime;
        }



        //攻擊的方法

        if (canShootNoCD)
        {
            Attack();
            attack = true;
            return;
        }

        if (attackCD >= 1 - gunLevel * 0.3)
        {
            Attack();
            attack = true;
        }
        else
        {
            attackCD += Time.deltaTime;
        }
    }

    /// <summary>
    /// 以下是方法的定義
    /// </summary>




    //旋轉槍

    private void RotateGun()
    {

        float h = Input.GetAxisRaw("Mouse Y");
        float v = Input.GetAxisRaw("Mouse X");

        transform.Rotate(-Vector3.forward * v * rotateSpeed);
        transform.Rotate(Vector3.forward * h * rotateSpeed);




        ClampAngle();
        //245,115
    }

    //換槍的方法

    public void UpGun()
    {
        gunLevel += 1;
        if (gunLevel == 4)
        {
            gunLevel = 1;
        }
        gunChange[0].ToGray();
        gunChange[1].ToGray();
        canChangeGun = false;
    }

    public void DownGun()
    {
        gunLevel -= 1;
        if (gunLevel == 0)
        {
            gunLevel = 3;
        }
        gunChange[0].ToGray();
        gunChange[1].ToGray();
        canChangeGun = false;
    }


    //限制角度
    private void ClampAngle()
    {
        float y = transform.eulerAngles.y;
        if (y <= 35)
        {
            y = 35;
        }
        else if (y >= 150)
        {
            y = 150;
        }

        transform.eulerAngles = new Vector3(transform.eulerAngles.x, y, transform.eulerAngles.z);
    }

    //攻擊方法

    private void Attack()
    {

        if (Input.GetMouseButtonDown(0))
        {

            bullectAudio.clip = bullectAudios[gunLevel - 1];
            bullectAudio.Play();

            if (Butterfly)
            {
                Instantiate(Bullects[gunLevel - 1], attackPos.position, attackPos.rotation * Quaternion.Euler(0, 0, 20));
                Instantiate(Bullects[gunLevel - 1], attackPos.position, attackPos.rotation * Quaternion.Euler(0, 0, -20));
            }

            Instantiate(Bullects[gunLevel - 1], attackPos.position, attackPos.rotation);


            if (!canShootForFree)
            {
                GoldChange(-1 - (gunLevel - 1) * 2);

            }
            attackCD = 0;
            attack = false;
        }

    }

    //增減金錢

    public void GoldChange(int number)
    {
        if (canGetDoubleGold)
        {
            if (number > 0)
            {
                number *= 2;
            }
        }


        gold += number;
    }

    //增減鑽石

    public void DiamandsChange(int number)
    {


        diamands += number;
    }

    /// <summary>
    /// 貝殼觸發的一些效果方法
    /// </summary>


    public void CanShootForFree()
    {
        canShootForFree = true;
        Invoke("CantShootForFree", 5);
    }

    public void CantShootForFree()
    {
        canShootForFree = false;
    }

    public void CanGetDoubleGold()
    {
        canGetDoubleGold = true;
        Invoke("CantGetDoubleGold", 5);
    }

    public void CantGetDoubleGold()
    {
        canGetDoubleGold = false;
    }

    public void CanShootNoCD()
    {
        canShootNoCD = true;
        Invoke("CantShootNoCD", 5);
    }

    public void CantShootNoCD()
    {
        canShootNoCD = false;
    }

    //boss攻擊的方法
    public void BossAttack()
    {
        bossAttack = true;
    }
}
Gun  Fish/PlayerManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 切槍的按鈕
/// </summary>
public class GunChange : MonoBehaviour
{

    public bool add;
    private Button button;
    private Image image;
    public Sprite[] buttonSprites;//0.+   1.灰色的+  2.-  3.灰色的-

    // Use this for initialization
    void Start()
    {
        button = transform.GetComponent<Button>();
        button.onClick.AddListener(ChangeGunLevel);
        image = GetComponent<Image>();

    }

    // Update is called once per frame
    void Update()
    {
        if (Gun.Instance.canChangeGun)
        {
            if (add)
            {
                image.sprite = buttonSprites[0];

            }
            else
            {
                image.sprite = buttonSprites[2];
            }

        }
    }

    public void ChangeGunLevel()
    {
        if (Gun.Instance.canChangeGun)
        {
            if (add)
            {
                Gun.Instance.UpGun();
            }
            else
            {
                Gun.Instance.DownGun();
            }
        }
    }

    public void ToGray()
    {
        if (add)
        {
            image.sprite = buttonSprites[1];

        }
        else
        {
            image.sprite = buttonSprites[3];

        }

    }

}
GunChange  Fish/Canvas/UI_LeftTable/AddGunLevel
using UnityEngine;
using System.Collections;

public class Bullect : MonoBehaviour {

    public GameObject explosions;

    public GameObject star;
    public GameObject star1;
    public GameObject star2;
    public float moveSpeed;
    private float timeVal;
    public float defineTime;
    private float timeVal1;
    public float defineTime1;
    private float timeVal2;
    public float defineTime2;
    public Transform CreatePos;
    public GameObject net;
    public int level;

    public float attackValue;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        timeVal=InistStar(timeVal,defineTime,star);
        timeVal1=InistStar(timeVal1,defineTime1,star1);
        timeVal2=InistStar(timeVal2,defineTime2,star2);
        transform.Translate(transform.up*moveSpeed*Time.deltaTime,Space.World);
    }

    private float InistStar(float timeVals,float defineTimes,GameObject stars)
    {
        
        if (timeVals>=defineTimes) {
            Instantiate(stars, CreatePos.transform.position, Quaternion.Euler(CreatePos.transform.eulerAngles.x, CreatePos.transform.eulerAngles.y, CreatePos.transform.eulerAngles.z+Random.Range(-40f,40f)));
            timeVals=0;
        }
        else {
            timeVals+=Time.deltaTime;
        }

        return timeVals;
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "fish" || other.tag == "boss")
        {
            other.SendMessage("TakeDamage", attackValue);
            GameObject go = Instantiate(net, transform.position + new Vector3(0, 1, 0), transform.rotation);
            go.transform.localScale = new Vector3(level, level, level);
            Instantiate(explosions, transform.position, transform.rotation);
            Destroy(this.gameObject);
        }
        else if (other.tag == "missile")
        {
            other.SendMessage("Lucky", attackValue);
            GameObject go = Instantiate(net, transform.position + new Vector3(0, 1, 0), transform.rotation);
            go.transform.localScale = new Vector3(level, level, level);
            Instantiate(explosions, transform.position, transform.rotation);
            Destroy(this.gameObject);
        }
        else if (other.tag == "Shell")
        {
            other.SendMessage("GetEffects");
            GameObject go = Instantiate(net, transform.position + new Vector3(0, 1, 0), transform.rotation);
            go.transform.localScale = new Vector3(level, level, level);
            Instantiate(explosions, transform.position, transform.rotation);
            Destroy(this.gameObject);
        }
        else if (other.tag == "Qipao")
        {
            GameObject go = Instantiate(net, transform.position + new Vector3(0, 1, 0), transform.rotation);
            go.transform.localScale = new Vector3(level, level, level);
            Instantiate(explosions, transform.position, transform.rotation);
            Destroy(this.gameObject);
        }
        /*else*/
        if (other.tag == "Wall")
        {
            float angleValue = Vector3.Angle(transform.up, other.transform.up);
            if (angleValue < 90)
            {
                transform.eulerAngles += new Vector3(0, 0, 2*angleValue);
            }
            else if (Vector3.Angle(transform.up, other.transform.up) > 90)
            {
                transform.eulerAngles -= new Vector3(0, 0, 360-2 * angleValue);
            }
            else
            {
                transform.eulerAngles += new Vector3(0, 0, 180);
            }
        }
    }
}
Bullet  Prefabs/Player/Bullet1,2,3

  PlayerUI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 灼燒
/// </summary>
public class Fire : MonoBehaviour
{

    private Button but;
    private float timeVal = 15;
    private bool canUse = true;
    private float totalTime = 15;

    public Slider cdSlider;
    private int reduceDiamands;

    private void Awake()
    {
        but = transform.GetComponent<Button>();
        but.onClick.AddListener(Attack);

    }

    // Use this for initialization

    void Start()
    {
        reduceDiamands = 10;
    }

    // Update is called once per frame
    void Update()
    {
        if (timeVal >= 15)
        {
            timeVal = 15;
        }
        cdSlider.value = timeVal / totalTime;
        if (timeVal >= 15)
        {

            canUse = true;
            cdSlider.transform.Find("Background").gameObject.SetActive(false);
        }
        else
        {

            timeVal += Time.deltaTime;
        }
    }

    private void Attack()
    {
        if (canUse)
        {
            if (!Gun.Instance.Ice && !Gun.Instance.Fire)
            {

                if (Gun.Instance.diamands <= reduceDiamands)
                {
                    return;
                }

                Gun.Instance.DiamandsChange(-reduceDiamands);
                Gun.Instance.Fire = true;
                canUse = false;
                cdSlider.transform.Find("Background").gameObject.SetActive(true);
                timeVal = 0;
                Invoke("CloseFire", 6);
            }
        }

    }

    //關閉必殺的方法
    private void CloseFire()
    {
        Gun.Instance.Fire = false;
    }


}
Fire  Fish/Canvas/UI_Skills/Img_Fire/But_Fire
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 冰凍
/// </summary>
public class Ice : MonoBehaviour
{


    private float timeVal = 10;
    private bool canUse = true;

    public Slider cdSlider;
    private float totalTime = 10;
    Button but;
    private AudioSource fireAudio;
    private int reduceDiamands;
    // Use this for initialization
    private void Awake()
    {
        but = transform.GetComponent<Button>();
        but.onClick.AddListener(ice);
        fireAudio = GetComponent<AudioSource>();
    }


    void Start()
    {
        reduceDiamands = 10;
    }

    private void Update()
    {
        if (timeVal >= 10)
        {
            timeVal = 10;
        }
        cdSlider.value = timeVal / totalTime;
        if (timeVal >= 10)
        {
            cdSlider.transform.Find("Background").gameObject.SetActive(false);
            canUse = true;
        }
        else
        {

            timeVal += Time.deltaTime;
        }
    }

    private void ice()
    {
        //必殺的方法
        if (canUse)
        {
            if (!Gun.Instance.Fire && !Gun.Instance.Ice)
            {

                if (Gun.Instance.diamands <= reduceDiamands)
                {
                    return;
                }
                if (fireAudio.isPlaying)
                {
                    return;
                }
                fireAudio.Play();
                Gun.Instance.DiamandsChange(-reduceDiamands);
                Gun.Instance.Ice = true;
                canUse = false;
                cdSlider.transform.Find("Background").gameObject.SetActive(true);
                timeVal = 0;
                Invoke("CloseIce", 4);
            }
        }

    }

    //關閉必殺的方法
    private void CloseIce()
    {

        Gun.Instance.Ice = false;
    }
}
Ice  Fish/Canvas/UI_Skills/UI_Ice/But_Ice
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 散彈按鈕
/// </summary>
public class ButterFly : MonoBehaviour
{

    Button but;

    private float timeVal = 15;
    private bool canUse = true;
    private float totalTime = 15;
    public GameObject uiView;

    public Slider cdSlider;
    private int reduceDiamands;

    private void Awake()
    {
        but = transform.GetComponent<Button>();
        but.onClick.AddListener(Fire);

    }


    void Start()
    {
        reduceDiamands = 10;
    }

    // Update is called once per frame
    void Update()
    {
        if (timeVal >= 15)
        {
            timeVal = 15;
        }
        cdSlider.value = timeVal / totalTime;
        if (timeVal >= 15)
        {

            canUse = true;
            cdSlider.transform.Find("Background").gameObject.SetActive(false);
        }
        else
        {

            timeVal += Time.deltaTime;
        }
    }

    private void Fire()
    {
        if (canUse)
        {

            if (Gun.Instance.diamands <= reduceDiamands)
            {
                return;
            }
            Gun.Instance.DiamandsChange(-reduceDiamands);


            Gun.Instance.Butterfly = true;
            canUse = false;
            cdSlider.transform.Find("Background").gameObject.SetActive(true);
            timeVal = 0;
            Invoke("CloseFire", 8);
            uiView.SetActive(true);

        }

    }

    //關閉必殺的方法
    private void CloseFire()
    {
        uiView.SetActive(false);
        Gun.Instance.Butterfly = false;
    }


}
ButterFly  Fish/Canvas/UI_Skills/UI_ButterflyShoot/But_ButterflyShoot
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 負責UI顯示的槍
/// </summary>
public class GunImage : MonoBehaviour
{

    public Sprite[] Guns;
    private Image img;

    public Transform idlePos;
    public Transform attackPos;

    private float rotateSpeed = 5f;


    private void Awake()
    {
        img = transform.GetComponent<Image>();
    }
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        //旋轉槍的方法

        RotateGun();
        img.sprite = Guns[Gun.Instance.gunLevel - 1];


        //攻擊的方法



        if (Gun.Instance.attack)
        {
            if (Input.GetMouseButtonDown(0))
            {
                attack();
            }
        }

    }

    private void attack()
    {

        transform.position = Vector3.Lerp(transform.position, attackPos.position, 0.5f);
        Invoke("idle", 0.4f);
    }
    private void idle()
    {

        transform.position = Vector3.Lerp(transform.position, idlePos.position, 0.2f);

    }
    //旋轉槍

    private void RotateGun()
    {

        float h = Input.GetAxisRaw("Mouse Y");
        float v = Input.GetAxisRaw("Mouse X");

        transform.Rotate(-Vector3.forward * v * rotateSpeed);
        transform.Rotate(Vector3.forward * h * rotateSpeed);





        ClampAngle();

    }

    //限制角度
    private void ClampAngle()
    {
        float z = transform.eulerAngles.z;
        if (z <= 35)
        {
            z = 35;
        }
        else if (z >= 150)
        {
            z = 150;
        }

        transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, z);
    }
}
GunImage  Fish/Canvas/Img_Gun 

  UI

using UnityEngine;
using System.Collections;

/// <summary>
/// 產生UI泡泡
/// </summary>
public class CreatePao : MonoBehaviour
{

    public GameObject pao;
    public Transform panel;
    private float timeVal = 6;


    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

        if (timeVal >= 6)
        {
            for (int i = 0; i < 4; i++)
            {
                Invoke("InstPao", 1);
            }
            timeVal = 0;
        }
        else
        {
            timeVal += Time.deltaTime;
        }
    }

    private void InstPao()
    {

        GameObject itemGo = Instantiate(pao, transform.position, Quaternion.Euler(0, 0, Random.Range(-80, 0))) as GameObject;
        itemGo.transform.SetParent(panel);
    }
}
CreatePao  Main/Canvas/Panel/CreatePao
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class StartGame : MonoBehaviour {

    private Button but;

    // Use this for initialization
    void Start () {
        but = GetComponent<Button>();
        but.onClick.AddListener(StartGames);
    }

    private void StartGames()
    {
        SceneManager.LoadScene(1);
    }

    // Update is called once per frame
    void Update () {
        
    }
}
StartGame  Main/Canvas/Panel/UI_StartGame/But_StartGame
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoadGame : MonoBehaviour {

    public Slider processView;

    // Use this for initialization
    void Start () {
        LoadGameMethod();
        
    }
    
    // Update is called once per frame
    void Update () {
        

    }
    public void LoadGameMethod()
    {
        StartCoroutine(StartLoading_4(2));
    }

    private IEnumerator StartLoading_4(int scene)
    {
        int displayProgress = 0;
        int toProgress = 0;
        AsyncOperation op = SceneManager.LoadSceneAsync(scene); 
        op.allowSceneActivation = false;
        while (op.progress < 0.9f)
        {
            toProgress = (int)op.progress * 100;
            while (displayProgress < toProgress)
            {
                ++displayProgress;
                SetLoadingPercentage(displayProgress);
                yield return new WaitForEndOfFrame();
            }
        }

        toProgress = 100;
        while (displayProgress < toProgress)
        {
            ++displayProgress;
            SetLoadingPercentage(displayProgress);
            yield return new WaitForEndOfFrame();
        }
        op.allowSceneActivation = true;
    }

    private void SetLoadingPercentage(float v)
    {
        processView.value = v / 100;
    }

   
}
LoadGame  Loading/Canvas/Panel/LoadGame
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 寶藏
/// </summary>
public class Treasour : MonoBehaviour
{

    private Button but;
    private Image img;

    public GameObject gold;
    public GameObject diamands;
    public GameObject cdView;

    public Transform cavas;
    private bool isDrease;


    private void Awake()
    {
        but = GetComponent<Button>();
        but.onClick.AddListener(OpenTreasour);
        img = GetComponent<Image>();
    }

    void OpenTreasour()
    {
        if (img.color.a != 1)
        {
            return;
        }
        cdView.SetActive(true);
        Gun.Instance.GoldChange(Random.Range(100, 200));
        Gun.Instance.DiamandsChange(Random.Range(10, 50));
        CreatePrize();
        isDrease = true;
    }
    private void CreatePrize()
    {
        for (int i = 0; i < 5; i++)
        {
            GameObject go = Instantiate(gold, transform.position + new Vector3(-10f + i * 30, 0, 0), transform.rotation);
            go.transform.SetParent(cavas);
            GameObject go1 = Instantiate(diamands, transform.position + new Vector3(0, 30, 0) + new Vector3(-10f + i * 30, 0, 0), transform.rotation);
            go1.transform.SetParent(cavas);
        }
    }

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (isDrease)
        {
            img.color -= new Color(0, 0, 0, Time.deltaTime * 10);
            if (img.color.a <= 0.2)
            {
                img.color = new Color(img.color.r, img.color.g, img.color.b, 0);
                isDrease = false;
            }
        }
        else
        {
            img.color += new Color(0, 0, 0, Time.deltaTime * 0.01f);
            if (img.color.a >= 0.9)
            {
                img.color = new Color(img.color.r, img.color.g, img.color.b, 1);
                cdView.SetActive(false);
            }
        }

    }
}
Treasour  Fish/Canvas/UI_Treasour/But_Treasour
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 地圖背景
/// </summary>
public class Ground : MonoBehaviour
{

    private MeshRenderer mr;

    public Material[] materialList;

    private AudioSource audioSource;
    public AudioClip[] audioClips;


    // Use this for initialization
    void Start()
    {
        mr = GetComponent<MeshRenderer>();
        audioSource = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Gun.Instance.changeAudio)
        {
            audioSource.clip = audioClips[Gun.Instance.level - 1];
            audioSource.Play();
            Gun.Instance.changeAudio = false;
        }
        if (Gun.Instance.level == 1)
        {
            if (Gun.Instance.Fire)
            {
                mr.material = materialList[1];
            }
            else if (Gun.Instance.Ice)
            {
                mr.material = materialList[2];
            }
            else
            {
                mr.material = materialList[0];
            }
        }
        else if (Gun.Instance.level == 2)
        {
            if (Gun.Instance.Fire)
            {
                mr.material = materialList[4];
            }
            else if (Gun.Instance.Ice)
            {
                mr.material = materialList[5];
            }
            else
            {
                mr.material = materialList[3];
            }
        }
        else if (Gun.Instance.level == 3)
        {
            if (Gun.Instance.Fire)
            {
                mr.material = materialList[7];
            }
            else if (Gun.Instance.Ice)
            {
                mr.material = materialList[8];
            }
            else
            {
                mr.material = materialList[6];
            }
        }
    }
}
Ground  Fish/Plane
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Mylight : MonoBehaviour {

    public Sprite[] lights;
    private Image img;
    private int i;
    private float timeVal;

    private void Awake()
    {
        img = GetComponent<Image>();

    }


    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        if (timeVal>=0.08f)
        {
            img.sprite = lights[i];
            i++;
            if (i == lights.Length)
            {
                i = 0;
            }
            timeVal = 0;
        }
        else
        {
            timeVal += Time.deltaTime;
        }
            
    }
}
Mylight  Fish/Canvas/Img_Gun/Img_GunEffectRight
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class ReturnMain : MonoBehaviour {

    private Button but;

    // Use this for initialization
    void Start()
    {
        but = GetComponent<Button>();
        but.onClick.AddListener(StartGames);
    }

    public void StartGames()
    {
        SceneManager.LoadScene(0);
    }

    // Update is called once per frame
    void Update()
    {

    }
}
ReturnMain  Fish/Canvas/UI_ReturnMenu/But_ReturnMenu
using UnityEngine;
using System.Collections;

public class Star : MonoBehaviour {

    public float moveSpeed=1;

    // Use this for initialization
    void Start () {
        Destroy(gameObject,Random.Range(0.4f,1));
    }
    
    // Update is called once per frame
    void Update () {
        //transform.Translate(-transform.right*moveSpeed*Time.deltaTime,Space.World);
    }
}
Star  Prefabs/Effects/star...
--1.1 點擊寶箱領取的金幣鑽石太擁擠,分散一點。

local UnityEngine=CS.UnityEngine
xlua.hotfix(CS.Treasour,'CreatePrize',function(self)
    for i=0,4,1 do
        local go=UnityEngine.GameObject.Instantiate(self.gold,self.transform.position+UnityEngine.Vector3(-10+i*40,0,0),self.transform.rotation)
        go.transform.SetParent(go.transform,self.cavas)
        local go1=UnityEngine.GameObject.Instantiate(self.diamands,self.transform.position+UnityEngine.Vector3(0,40,0)+UnityEngine.Vector3(-10+i*40,0,0),self.transform.rotation)
        go1.transform.SetParent(go1.transform,self.cavas)
    end
end)

--******************************************************************



--1.1 玩家金幣鑽石不夠時沒有相應處理。

xlua.private_accessible(CS.Gun)
xlua.hotfix(CS.Gun,'Attack',function(self)
    if UnityEngine.Input.GetMouseButtonDown(0) then
        
        --1.2 與UI交互時不能發射子彈

        if UnityEngine.EventSystems.EventSystem.current:IsPointerOverGameObject() then
            return
        end

        --[[
        if self.gold<1+(self.gunLevel-1)*2 or gold==0 then
            return
        end
        --]]

        --1.3 炮台3太強,且鑽石沒用處,不削弱,只有氪金才可使用 

        if self.gunLevel==3 and self.diamands<3 then

          return

        elseif self.gunLevel~=3 then

            if self.gold<1+(self.gunLevel-1)*2 or gold==0 then
                return
            end
        end


        self.bullectAudio.clip=self.bullectAudios[self.gunLevel-1]
        self.bullectAudio:Play()

        if self.Butterfly then
            UnityEngine.GameObject.Instantiate(self.Bullects[self.gunLevel-1],self.attackPos.position,self.attackPos.rotation*UnityEngine.Quaternion.Euler(0,0,20))
            UnityEngine.GameObject.Instantiate(self.Bullects[self.gunLevel-1],self.attackPos.position,self.attackPos.rotation*UnityEngine.Quaternion.Euler(0,0,-20))
        end

        UnityEngine.GameObject.Instantiate(self.Bullects[self.gunLevel-1],self.attackPos.position,self.attackPos.rotation)

        if not self.canShootForFree then
            if self.gunLevel==3 then
                self:DiamandsChange(-3)
            else
                self:GoldChange(-1-(self.gunLevel-1)*2)
            end
        end
        self.attackCD=0
        self.attack=false
    end

end)



--******************************************************************

-- 1.2 技能扣鑽石太多。

xlua.private_accessible(CS.Fire)
xlua.hotfix(CS.Fire,'Start',function(self)
    self.reduceDiamands = 8;
end)

xlua.private_accessible(CS.Ice)
xlua.hotfix(CS.Ice,'Start',function(self)
    self.reduceDiamands = 8;
end)

xlua.private_accessible(CS.ButterFly)
xlua.hotfix(CS.ButterFly,'Start',function(self)
    self.reduceDiamands = 5;
end)

--*************************************************************

-- 1.2 boss撞擊玩家數值變動一樣且不是減少是增加。

local util=require 'util'

xlua.private_accessible(CS.Boss)
util.hotfix_ex(CS.Boss,'Start',function(self)
    self.Start(self)
    self.m_reduceGold=self.m_reduceGold-20
end)


xlua.private_accessible(CS.DeffendBoss)
util.hotfix_ex(CS.DeffendBoss,'Start',function(self)
    self.Start(self)
    self.m_reduceGold=self.m_reduceGold-30
end)


xlua.private_accessible(CS.InvisibleBoss)
util.hotfix_ex(CS.InvisibleBoss,'Start',function(self)
    self.Start(self)
    self.m_reduceDiamond=self.m_reduceDiamond-5
end)

--********************************************************************

-- 1.3 boss撞擊玩家當鑽石金幣不夠時會產生負數。

util.hotfix_ex(CS.Gun,'GoldChange',function(self,number)
        self.GoldChange(self,number)
        if self.gold<-number then
            self.gold=0
            return
        end
end)

util.hotfix_ex(CS.Gun,'DiamandsChange',function(self,number)
        self.DiamandsChange(self,number)
        if self.diamands<-number then
            self.diamands=0
            return
        end
end)

--******************************************************************

-- 1.3 大魚太多

local canCreateNewFish=true
local changeMapTimeval=0


xlua.hotfix(CS.CreateFish,'Start',function(self)
        --self.hotFixScript:LoadResource('level3fish3','gameobject\\enemy.ab')
        --self.hotFixScript:LoadResource('SeaWave','gameobject\\wave.ab')
end)
   
xlua.private_accessible(CS.CreateFish)
xlua.hotfix(CS.CreateFish,'Update',function(self)
    
    -- 2.0 生成海浪

    if canCreateNewFish then
        
        if changeMapTimeval >=50 then
            go=CS.HotFixScript.GetGameObject('SeaWave')
            UnityEngine.GameObject.Instantiate(go)
            canCreateNewFish=false
            changeMapTimeval=0
        else
            changeMapTimeval=changeMapTimeval+UnityEngine.Time.deltaTime
        end
    else
        return
    end

    self:CreateALotOfFish()

    --單種魚的生成
        if self.ItemtimeVal>=0.5 then
        
            --位置隨機數
            self.num =UnityEngine.Mathf.Floor(UnityEngine.Random.Range(0, 4)
            ) 
            --游戲物體隨機數
            self.ItemNum =UnityEngine.Mathf.Floor(UnityEngine.Random.Range(1, 101))

            local halfLength=self.fishList.Length/2

            local littlefishTypeIndex=UnityEngine.Mathf.Floor(UnityEngine.Random.Range(0,halfLength))

            local bigfishTypeIndex=UnityEngine.Mathf.Floor(UnityEngine.Random.Range(halfLength,self.fishList.Length))

            local itemTypeIndex=UnityEngine.Mathf.Floor(UnityEngine.Random.Range(0,self.item.Length))
            
            --產生氣泡
            if self.ItemNum<20 then
            
                self:CreateGameObject(self.item[3])
                
            end
         
            if  self.ItemNum <= 42 then
                for i=0,2,1 do
                    self:CreateGameObject(self.fishList[littlefishTypeIndex])
                end
                self:CreateGameObject(self.item[itemTypeIndex])
                
            elseif self.ItemNum >= 43 and self.ItemNum < 72 then
                for i=0,1,1 do
                    self:CreateGameObject(self.fishList[bigfishTypeIndex])
                end
                self:CreateGameObject(self.item[itemTypeIndex])
--2.0 新魚
            elseif self.ItemNum >= 73 and self.ItemNum < 83 then

                newFish=CS.HotFixScript.GetGameObject('level3fish3')
                self:CreateGameObject(newFish)
            
            elseif self.ItemNum >= 84 and self.ItemNum < 86 then
            
                self:CreateGameObject(self.boss)


            elseif self.ItemNum >= 87 and self.ItemNum <= 88 then
            
                self:CreateGameObject(self.boss2)
            

            elseif self.ItemNum==100 then
            

                self:CreateGameObject(self.boss3)

            else
            
                self:CreateGameObject(self.item[0]);         
             
            end
            
            self.ItemtimeVal = 0
        else
        
            self.ItemtimeVal =self.ItemtimeVal+CS.UnityEngine.Time.deltaTime;
        end

end)

--**********************************************************************************

-- 1.4 撲魚是考慮了魚的血量與子彈的傷害來模擬概率,這樣玩家體驗不好,要使用傳統的概率來撲魚。

xlua.private_accessible(CS.Fish)
xlua.hotfix(CS.Fish,'TakeDamage',function(self,attackValue)
        
        if UnityEngine.Gun.Instance.Fire then
        
            attackValue=attackValue*2;

        end
        local catchValue=UnityEngine.Mathf.Floor(UnityEngine.Random.Range(0,100))
        if catchValue<=(50-(self.hp-attackValue))/2 then
        
            self.isDead = true
            for i=0,8,1 do
                UnityEngine.GameObject.Instantiate(self.pao, self.transform.position, UnityEngine.Quaternion.Euler(self.transform.eulerAngles + UnityEngine.Vector3(0, 45 * i, 0)))
            end

            self.gameObjectAni:SetTrigger("Die")
            self:Invoke("Prize", 0.7)
        end
end)

xlua.hotfix(CS.Boss,'TakeDamage',function(self,attackValue)
        if UnityEngine.Gun.Instance.Fire then
        
            attackValue=attackValue*2;
        end

        local catchValue=UnityEngine.Mathf.Floor(UnityEngine.Random.Range(0,100))
        if catchValue<=(attackValue*3-self.hp/10) then
        
            UnityEngine.GameObject.Instantiate(self.deadEeffect, self.transform.position, self.transform.rotation)
            CS.Gun.Instance:GoldChange(self.GetGold * 10)
            CS.Gun.Instance:DiamandsChange(self.GetDiamands * 10)

            for i=0,10,1 do
            
                local itemGo =UnityEngine.GameObject.Instantiate(self.gold, self.transform.position, UnityEngine.Quaternion.Euler(self.transform.eulerAngles + UnityEngine.Vector3(0, 18 + 36 * (i - 1), 0)))
                itemGo:GetComponent('Gold').bossPrize = true
            end
            for i=0,10,1 do
                                    
                local itemGo1 =UnityEngine.GameObject.Instantiate(self.diamands,self.transform.position, UnityEngine.Quaternion.Euler(self.transform.eulerAngles + UnityEngine.Vector3(0, 36 + 36 * (i - 1), 0)))
                itemGo1:GetComponent('Gold').bossPrize = true
            end
            UnityEngine.Object.Destroy(self.gameObject)
        
        end
end)

-- ***********************************************************************************

-- 1.4 炮台移動是根據鼠標的水平數值滑動來模擬跟隨的,改為玩家按下ad鍵來旋轉炮台

xlua.hotfix(CS.Gun,'RotateGun',function(self)
        if UnityEngine.Input.GetKey(UnityEngine.KeyCode.A) then
            self.transform:Rotate(UnityEngine.Vector3.forward * self.rotateSpeed)
        elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.D) then
            self.transform:Rotate(-UnityEngine.Vector3.forward * self.rotateSpeed)
        end
        self:ClampAngle()
end)

xlua.private_accessible(CS.GunImage)
xlua.hotfix(CS.GunImage,'RotateGun',function(self)
        if UnityEngine.Input.GetKey(UnityEngine.KeyCode.A) then
            self.transform:Rotate(UnityEngine.Vector3.forward * self.rotateSpeed)
        elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.D) then
            self.transform:Rotate(-UnityEngine.Vector3.forward * self.rotateSpeed)
        end
        self:ClampAngle()
end)

-- 2.0 海浪

xlua.private_accessible(CS.HotFixEmpty)
xlua.hotfix(CS.HotFixEmpty,'Start',function(self)
    self:Invoke("BehaviourMethod",8)
end)

xlua.hotfix(CS.HotFixEmpty,'Update',function(self)
    self.transform:Translate(-self.transform.right*4*UnityEngine.Time.deltaTime,UnityEngine.Space.World)
end)


xlua.hotfix(CS.HotFixEmpty,'OnTriggerEnter',function(self,other)
    if other.tag~="Untagged" and other.tag~="Wall" then
        UnityEngine.Object.Destroy(other.gameObject)
    end
end)



xlua.hotfix(CS.HotFixEmpty,'BehaviourMethod',function(self)
    CS.Gun.Instance.level=CS.Gun.Instance.level+1
    if CS.Gun.Instance.level==4 then
        CS.Gun.Instance.level=1
    end
    canCreateNewFish=true
    CS.Gun.Instance.changeAudio=true
    UnityEngine.Object.Destroy(self.gameObject)

end)



xlua.hotfix(CS.Treasour,'CreatePrize',nil)

xlua.hotfix(CS.Gun,'Attack',nil)

xlua.hotfix(CS.Ice,'Start',nil)

xlua.hotfix(CS.Fire,'Start',nil)

xlua.hotfix(CS.ButterFly,'Start',nil)

xlua.hotfix(CS.Boss,'Start',nil)

xlua.hotfix(CS.DeffendBoss,'Start',nil)

xlua.hotfix(CS.InvisibleBoss,'Start',nil)

xlua.hotfix(CS.Gun,'GoldChange',nil)

xlua.hotfix(CS.Gun,'DiamandsChange',nil)

xlua.hotfix(CS.CreateFish,'Update',nil)

xlua.hotfix(CS.Fish,'TakeDamage',nil)

xlua.hotfix(CS.Boss,'TakeDamage',nil)

xlua.hotfix(CS.Gun,'RotateGun',nil)

xlua.hotfix(CS.GunImage,'RotateGun',nil)

xlua.hotfix(CS.CreateFish,'Start',nil)

xlua.hotfix(CS.HotFixEmpty,'Start',nil)

xlua.hotfix(CS.HotFixEmpty,'Update',nil)

xlua.hotfix(CS.HotFixEmpty,'OnTriggerEnter',nil)

xlua.hotfix(CS.HotFixEmpty,'BehaviourMethod',nil)
View Code

 

 

Unity商業游戲底層資源加載框架(Unity2018.1)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ResourceTest : MonoBehaviour
{
    //public GameObject m_Prefab;

    void Start() {
        //GameObject obj = GameObject.Instantiate(Resources.Load("Attack") as GameObject);    

        //AssetBundle assetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/attack");
        //GameObject obj = GameObject.Instantiate(assetBundle.LoadAsset<GameObject>("attack"));

        GameObject obj = GameObject.Instantiate(UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/GameData/Prefabs/Attack.prefab"));
    }
}
常用四種加載方式
TestSerialize

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml.Serialization;

[System.Serializable]
public class TestSerialize {

    [XmlAttribute("Id")]
    public int Id { get; set; }

    [XmlAttribute("Name")]
    public string Name { get; set; }

    [XmlElement("List")]
    public List<int> List { get; set; }
}

AssetSerialize

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "TestAssets", menuName = "CreateAssets", order = 0)]
public class AssetSerialize : ScriptableObject {
    public int Id;
    public string Name;
    public List<string> TestList;
}

ResourceTest

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class ResourceTest : MonoBehaviour
{

    void Start() {

        // SerializeTest();
        // DeSerializeTest();
        // BinarySerializeTest();
        //BinaryDeserializeTest();
        ReadTestAssets();
    }

    void ReadTestAssets() {
        AssetSerialize assets = UnityEditor.AssetDatabase.LoadAssetAtPath<AssetSerialize>("Assets/Scripts/TestAssets.asset");
        Debug.Log(assets.Id);
        Debug.Log(assets.Name);
        foreach (string str in assets.TestList) {
            Debug.Log(str);
        }
    }

    void SerializeTest() {
        TestSerialize testSerialize = new TestSerialize();
        testSerialize.Id = 1;
        testSerialize.Name = "測試";
        testSerialize.List = new List<int>();
        testSerialize.List.Add(2);
        testSerialize.List.Add(3);
        XmlSerialize(testSerialize);
    }

    void DeSerializeTest() {
        TestSerialize testSerialize = XmlDeSerialize();
        Debug.Log(testSerialize.Id + " " + testSerialize.Name);
        foreach (int a in testSerialize.List) {
            Debug.Log(a);
        }
    }

    void XmlSerialize(TestSerialize testSerialize) {
        FileStream fileStream = new FileStream(Application.dataPath + "/test.xml", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
        StreamWriter sw = new StreamWriter(fileStream, System.Text.Encoding.UTF8);
        XmlSerializer xml = new XmlSerializer(testSerialize.GetType());
        xml.Serialize(sw, testSerialize);
        sw.Close();
        fileStream.Close();
    }

    TestSerialize XmlDeSerialize() {
        FileStream fs = new FileStream(Application.dataPath + "/test.xml", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
        XmlSerializer xs = new XmlSerializer(typeof(TestSerialize));
        TestSerialize testSerialize = (TestSerialize)xs.Deserialize(fs);
        fs.Close();
        return testSerialize;
    }

    void BinarySerializeTest() {
        TestSerialize testSerialize = new TestSerialize();
        testSerialize.Id = 2;
        testSerialize.Name = "二進制測試";
        testSerialize.List = new List<int>();
        testSerialize.List.Add(10);
        testSerialize.List.Add(18);
        BinarySerialize(testSerialize);

    }

    void BinaryDeserializeTest() {
        TestSerialize testSerialize = BinaryDeserialize();
        Debug.Log(testSerialize.Id + " " + testSerialize.Name);
        foreach (int a in testSerialize.List) {
            Debug.Log(a);
        }
    }

    void BinarySerialize(TestSerialize serialize) {
        FileStream fs = new FileStream(Application.dataPath + "/test.bytes", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(fs, serialize);
        fs.Close();
    }

    TestSerialize BinaryDeserialize() {
        TextAsset textAsset = UnityEditor.AssetDatabase.LoadAssetAtPath<TextAsset>("Assets/test.bytes");
        MemoryStream stream = new MemoryStream(textAsset.bytes);
        BinaryFormatter bf = new BinaryFormatter();
        TestSerialize testSerialize = (TestSerialize)bf.Deserialize(stream);
        stream.Close();
        return testSerialize;
    }
}
序列化

 

 

Unity資源熱更及代碼熱更(ILRuntime)

 

 

Unity 游戲框架搭建 2019 第一季 C# 核心知識與簡易 Manager Of Managers 框架搭建 (已看)

Unity 游戲框架搭建 2019 第二季 模塊/系統設計、命名、測試(資源管理/熱更新)

 

游戲開發中的設計模式

 

 

 

 

相關文章

unity 打包AssetBundle

unity 熱更新思路和實現

AssetBundle資源打包加載管理

 

http://tonytang1990.github.io/2018/10/24/AssetBundle%E8%B5%84%E6%BA%90%E6%89%93%E5%8C%85%E5%8A%A0%E8%BD%BD%E7%AE%A1%E7%90%86%E5%AD%A6%E4%B9%A0/?tdsourcetag=s_pctim_aiomsg


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM