AssetBundle(创建打包)入门学习(基于Unity2017) (已看)
分组策略
- 逻辑实体分组
- 按照类型分组
- 按照使用分组
分组策略----总结
- 把经常更新的资源放在一个单独的包里面,跟不经常更新的包分离
- 把需要同时加载的资源放在一个包里面
- 可以把其他包共享的资源放在一个单独的包里面
- 把一些需要同时加载的小资源打包成一个包
- 如果对于同一个资源有两个版本,可以考虑通过后缀来区分
- BuildAssetBundleOptions.None: 使用LZMA算法压缩,压缩的包更小,但是加载时间更长.使用之前需要整体压缩.一旦被解压,这个包会使用LZ4重新压缩.使用资源的时候不需要整体解压.在下载的时候可以使用LZMA算法,一旦
- BuildAssetBundleOptions.UncompressedAssetBundle: 不压缩,包大,加载快
- 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
文件校验
CRC MD5 SHA1
相同点:
CRC、MD5、SHA1都是通过对数据进行计算,来生成一个校验值,该校验值用来校验数据的完整性。
不同点:
- 算法不同。CRC采用多项式除法,MD5和SHA1使用的是替换、轮转等方法;
- 校验值的长度不同。CRC校验位的长度跟其多项式有关系,一般为16位或32位;MD5是16个字节(128位);SHA1是20个字节(160位);
- 校验值的称呼不同。CRC一般叫做CRC值;MD5和SHA1一般叫做哈希值(Hash)或散列值;
- 安全性不同。这里的安全性是指检错的能力,即数据的错误能通过校验位检测出来。CRC的安全性跟多项式有很大关系,相对于MD5和SHA1要弱很多;MD5的安全性很高,不过大概在04年的时候被山东大学的王小云破解了;SHA1的安全性最高。
- 效率不同,CRC的计算效率很高;MD5和SHA1比较慢。
- 用途不同。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
- Hidden folders
- Files and folders which start with '.'
- Files and folders which end with '~'
- Files and folders named cvs
- 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; } }
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; } } }
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); } } }
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(); } } } }
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"; } }
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; } }
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); } } } }
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; } } }
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); } } } }
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(); } } }
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(); } } } }
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; } } }
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); } } } }
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); } } } }
Lua编程 (已看)
https://www.runoob.com/lua/lua-tutorial.html
https://github.com/rjpcomputing/luaforwindows/releases
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 () { } }
游戏热更新实战案例(基于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; } } } }
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; } } } }
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) ; } }
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); } }
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; } } }
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; } } } }
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; } } }
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); } }
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); } }
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; } }
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); } }
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); } }
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; } }
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 () { } }
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; } } }
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; } }
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); } }
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); } } }
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; } }
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]; } } }
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); } } } }
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; } }
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; } }
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; } }
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); } }
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); } }
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 () { } }
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; } }
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); } } } }
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]; } } } }
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; } } }
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() { } }
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); } }
--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)
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 游戏框架搭建 2019 第一季 C# 核心知识与简易 Manager Of Managers 框架搭建 (已看)
Unity 游戏框架搭建 2019 第二季 模块/系统设计、命名、测试(资源管理/热更新)
相关文章