2D
3D 人物移动
Transform
在这里插入代码片
刚体
在这里插入代码片
导航网格
在这里插入代码片
摄像机跟随第三人称
在这里插入代码片
工具类
单例模式
很多地方都需要使用单例模式,只要需要继承这个类,就可以在任何地方通过:类名._Instance使用类中的方法和变量。
public class SingletonBase<T> : MonoBehaviour where T : MonoBehaviour
{
protected static T _instance;
private static object _lock = new object();
/// <summary>
/// 单例
/// </summary>
/// <returns></returns>
public static T _Instance
{
get
{
lock (_lock)
{
if (_instance == null)
{
_instance = (T) FindObjectOfType(typeof(T));
if (FindObjectsOfType(typeof(T)).Length > 1)
{
return _instance;
}
if (_instance == null)
{
GameObject singleton = new GameObject();
_instance = singleton.AddComponent<T>();
singleton.name = typeof(T).ToString();
DontDestroyOnLoad(singleton);
}
}
return _instance;
}
}
}
}
上面的方法由我师傅提供。虽然他不晓得。
下面这个简单一些。
public class Singleton<T> : MonoBehaviour where T:Singleton<T>
{
public static T _Instance { get; private set; }
protected void Awake()
{
if (_Instance == null)
{
_Instance = (T)this;
DontDestroyOnLoad(gameObject);
}
else {
Destroy(gameObject);
}
}
}
调用的方式是一样的。
public class GameManager : Singleton<GameManager>//需要继承自Singleton
{
//公有字段
public string MyName = "GoodCooking";
//私有字段
private string MySex = "Boy";
//公有方法
public void SayHello()
{
Debug.Log("Hello");
}
//私有方法
private void SayError()
{
Debug.Log("Error");
}
}
调用
public class LoadTXT : MonoBehaviour
{
void Start()
{
string name = GameManager._Instance.MyName;//可以访问GameManager中使用public修饰的变量或方法
string sex = GameManager._Instance.MySex;//private 的字段会报错 ,提示有一定的访问级别
GameManager._Instance.SayHello();//public 的就可以访问
GameManager._Instance.SayError();//private 的方法会报错 ,提示有一定的访问级别
}
}
查找一个物体
本方法由我师傅提供
使用了递归,
/// <summary>
/// 查找子节点对象
/// </summary>
/// <param name="goParent">父对象</param>
/// <param name="childName">子节点名称</param>
/// <returns></returns>
public static Transform FindTheChildNode(GameObject goParent, string childName)
{
Transform searchTrans = goParent.transform.Find(childName);
if (searchTrans == null)
{
foreach (Transform trans in goParent.transform)
{
searchTrans = FindTheChildNode(trans.gameObject, childName);
if (searchTrans != null)
{
return searchTrans;
}
}
}
return searchTrans;
}
在别的地方可以通过,具体的用法和find是一样的。
FindTheChildNode(gameObject,"你找的物体的名字");
gameObject是你要找的物体的父物体,
后面需要找的子物体的名称,返回值类型是Transform.
目前是只可以查找子物体,同一级别查找不到,需要使用FindWithTag(),当物体在”DontDestroyOnLoad“下,但是需要查找不在”DontDestroyOnLoad“的物体的时候需要使用FindWithTag();
打开一个PDF
前置:需要引用名空间
using System.IO;
然后再GameManager中方法
public class GameManager : Singleton<GameManager>//使用了上面的单例
{
/// <summary>
/// 打开PDF
/// </summary>
/// <param name="fileName">文件名称</param>
public void OpenBook(string fileName)
{
string path = "file:///" + Application.dataPath + "/StreamingAssets/";
if(File.Exists(path + fileName))
{
Application.OpenURL(path + fileName);
}
else {
Debug.Log("文件不存在,请检查文件路径"+path+fileName);
}
}
}
可以在任何位置通过
GameManager._Instance.OpenBook("文件名");
调用。
方法的文档链接:File.Exists , Application.OpenURL
匹配字符串
在一大堆字符串中找到对应的字符串,使用的KMP算法,具体使用KMP算法
public class GameManager : Singleton<GameManager>
{
private void GetNext(string T, int[] next)
{
int i = 0, j = 0;
next[0] = 0;
while ((i + 1) < T.Length)
{
if (j == 0 || T[i] == T[j - 1])
{
++i;
++j;
next[i] = j;
}
else
{
j = next[j - 1];
}
}
}
/// <summary>
/// 查找字符串
/// </summary>
/// <param name="S">一大堆字符串</param>
/// <param name="T">你想找的字符串</param>
/// <returns>你要找的字符串在一大堆字符串中出现的位置</returns>
public int GetStringIndex_KMP(string S, string T)
{
int i = 0, j = 0;
int[] next = new int[T.Length];
GetNext(T, next);
while (i < S.Length && j < T.Length)
{
if (j == 0 || S[i] == T[j])
{
++j;
++i;
}
else
{
j = next[j - 1];
}
}
if (T.Length <= j)
{
return i - T.Length;
}
else
{
return -1;
}
}
}
使用示例
string LongLongString = "123123123123123123123123123123567";
string targetString = "567";
if (GameManager._Instance.GetStringIndex_KMP(LongLongString, targetString) >0)
{
Debug.Log("找到了,位置在:" + (GameManager._Instance.GetStringIndex_KMP(LongLongString, targetString)));
}
else
{
Debug.Log("没有找到目标字符串");
}
给按钮添加事件
实现的主要方式是使用"UnityAction",
说明文档=>UnityAction的官方文档黑洞 首先引用命名空间
using UnityEngine.UI;//需要使用按钮UI
using UnityEngine.Events;//需要使用UnityAction
同样GameManager需要继承单例,单例的脚本在最上面
public class GameManager : Singleton<GameManager>
方法体如下
/// <summary>
/// 为按钮添加点击事件
/// </summary>
/// <param name="buttonName">需要添加事件的按钮名称</param>
/// <param name="buttonOnClickFunc">需要添加的方法</param>
public void AnyButtonOnClickEvent(string buttonName, UnityAction buttonOnClickFunc)
{
Button OnClickButton = null;//需要增加点击事件的按钮
OnClickButton = GameObject.Find(buttonName).GetComponent<Button>();//使用如果没找到使用GameObject寻找,不过有弊端,不能有重名的, 使用GameObject.Find(buttonName)性能消耗很高,可以按照需求修改,具体就利益相关。
OnClickButton.onClick.AddListener(buttonOnClickFunc);//为按钮添加事件。
}
使用方式
GameManager._Instance.AnyButtonOnClickEvent("ButtonA", ()=>{
Debug.Log("GoodCooking");
});
GameManager._Instance.AnyButtonOnClickEvent("ButtonB", () => {
Debug.Log("ButtonB");
});
由于“GameObject.Find(buttonName)”的缘故脚本可以挂载到任何位置。
弊端:只能使用无参的方法,可有改成有一个或更多参数的,但是目前我不会。
优化:可以使用Button的主要是在UI上,所以可以有一个UI基础类,所有的UI都继承自这个UI基础类,这样就可以更加高效的调用这个方法,同样也可以修改“ GameObject.Find(buttonName)”换成更高效的查找方式。
删除列表中符合条件的东西
7-19更新。
//首先在list中添加对应的数据,用于测试
List<String> list=new List<String>();
list.Add("早上好");
list.Add("中午好");
list.Add("晚上好");
/// <summary>
///删除列表中符合条件的东西
/// </summary>
private void DeleteDate()
{
list.ForEach(p =>
{
if (p.text == "早上好")//这这里进行进行条件的判断
{
list.Remove(p);
Debug.Log("删掉了哦");
};
});
}
上面那种会有神奇的错误,比如要操作一个占用的list的时候就会抛出一个 InvalidOperationException: Collection was modified; enumeration operation may not execute. 的错误。所以我会使用另外一种方式用于代替。
for(int i=0;i<list.count;i++)
{
if(list[i]=="中午好")
{
list.RemoveAt(i);
break;//在找到之后停止循环
}
}
使用上面的方式暂时没有遇到报错。
将多个字节数组合并成一个字节数组
7-27更新
/// <summary>
/// 将多个byte[] 合并成一个
/// </summary>
/// <param name="bytesList">存储 byte[] 列表</param>
/// <returns>合并之后的 byts [] </returns>
private static byte[] MergeBytes(List<byte[]> bytesList)
{
int bytesLength = 0;//lbytesList中每一行byte元素的总长度
for (int i = 0; i < bytesList.Count; i++)
{
bytesLength = bytesLength + bytesList[i].Length;
}
int k = 0;
byte[] mergeBytes = new byte[bytesLength];//用于存储合并之后的 byts[]
for (int i = 0; i < bytesList.Count; i++)
{
for (int j = 0; j < bytesList[i].Length; j++)
{
mergeBytes[k] = (bytesList[i])[j];
k = k + 1;
}
}
return mergeBytes;
}
使用说明:
将多个 byte[] 合并成一个 byte[]
参数 bytesList :存储需要转换的字节数组的列表
返回值 mergeBytes :转换好的字节数组
文件读取
using System.IO;
/// <summary>
/// 文件读取
/// </summary>
/// <param name="fileName"></param>
/// <returns>读取到的文件的byte []</returns>
private static byte[] FileContent(string filePath)
{
if(!File.Exists(filePath))
{
Console.WriteLine("文件不存在,请检查路径是否错误");
return null;
}
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
try
{
byte[] buffur = new byte[fs.Length];
fs.Read(buffur, 0, (int)fs.Length);
fs.Flush();//刷新缓冲区
fs.Close();
return buffur;
}
catch (Exception ex)
{
throw ex;
}
}
}
使用说明:
参数
filePath :文件路径
返回值
读取到的byte []
异常
文件不存在,检查文件路径是否正确。
获取或者添加组件
/// <summary>
/// 获取或者添加一个组件
/// </summary>
/// <typeparam name="T">泛型</typeparam>
/// <param name="go"></param>
/// <returns></returns>
private static T GetOrAddComponent<T>(GameObject go) where T : Component
{
T comp = go.GetComponent<T>();
if (!comp)
{
comp = go.AddComponent<T>();
}
return comp;
}
使用说明:
参数
T :组件的名称
GameObject go :需要获取组件的GameObject
返回值:获取一个组件