Unity脚本基础
文章目录
- 1、脚本基本规则
- 1、创建规则
- 2、MonoBehavior基类
- 3、不继承MonoBehavior的类
- 4、执行的先后顺序
- 5、默认脚本内容
- 2、生命周期函数
- 1、概念
- 2、生命周期函数有哪些
- 3、生命周期函数支持继承多态
- 3、Inspector窗口可编辑的变量
- 4、Mono中的重要内容
- 1、重要成员
- 2、重要方法
1、脚本基本规则
1、创建规则
2、MonoBehavior基类
1、创建脚本继承MonoBehavior,才能挂载在GameObject上2、继承了MonoBehavior的脚本不能new对象,不能写构造函数3、继承了MonoBehavior的脚本可以挂载多个,(DisallowMultipleComponent特性除外)4、继承MonoBehavior的类可以再被继承,遵循多态
3、不继承MonoBehavior的类
1、不能挂载在GameObject上
2、需要new
3、一般是单例模式的类(用于管理模块)或者数据结构类(用于存储数据)
4、不用保留默认出现的函数
4、执行的先后顺序
Execution Order设置
5、默认脚本内容
Editor\Data\Resources\ScriptTemplates
2、生命周期函数
游戏本质是一个循环,一帧就是一次循环
FPS(Frames Per Second)每秒钟帧数
FPS 60 :一秒更新60次画面
人眼可视帧数每秒24帧
1、概念
所有继承MonoBehavior的脚本最终都会挂载到GameObject游戏对象上
生命周期函数就是该脚本对象依附的GameObject对象从出生到消亡整个生命周期中
会通过反射自动调用的一些特殊函数Unity帮助我们记录了一个GameObject对象依附了哪些脚本
会自动得到这些对象,通过反射去执行一个固定名字的函数
这些固定名字的函数就是生命周期函数
2、生命周期函数有哪些
访问修饰符一般为private和protected
不需要外部调用,Unity调用
对象出生
AWake(调用一次)出生时调用,类似构造函数,一个对象只调用一次
OnEnable(激活时调用)依附的GameObject对象每次激活时调用
Start(调用一次)从自己被创建出来后,第一次帧更新之前调用一个对象只会调用一次
FixedUpdate(循环时调用)物理帧更新,固定间隔时间执行,间隔时间可以设置
Update (循环时调用)逻辑帧更新,每帧执行
LateUpdate(循环时调用)每帧执行,于Update之后执行
OnDisable (失活时调用)依附的GameObject对象每次失活时调用
OnDestroy(调用一次)对象销毁时调用,依附的GameObject对象被删除时
对象死亡
//当对象(自己这个类对象)被创建时,才会调用该声明周期函数
//类似构造函数,在一个类对象创建时进行初始化操作
void Awake()
{//打印信息的两种方式//1、没有继承MonoBehavior类的时候Debug.Log("日志");Debug.LogError("err");Debug.LogWarning("warning");//2、继承了MonoBehavior,有线程的方法print("打印信息");
}//对象激活时,逻辑处理
void OnEnable()
{print("OnEnable");
}//初始化信息,相对Awake晚一点,在对象进行第一次帧更新之前执行
void Start()
{print("Start");
}
//用于物理更新,每一帧执行,这里的帧和游戏帧有点不同(可以控制时间默认0.02)
//在project setting中的Time设置void FixedUpdate()
{print("FixedUpdate");
}
//主要用于处理游戏核心逻辑更新的函数
void Update()
{print("Update");
}//一般用来处理摄像机位置更新相关
//Update和LateUpdate之间,Unity进行了一些处理,处理动画相关的更新
void LateUpdate()
{print("LateUpdate");
}
//失活时做的处理
void OnDisable()
{print("OnDisable");
}
//删除对象时调用
private void OnDestroy()
{print("OnDestroy");
}
3、生命周期函数支持继承多态
3、Inspector窗口可编辑的变量
Inspector显示的可编辑内容就是脚本的成员变量
1、私有和保护无法显示编辑
2、让私有的和保护的也可以被显示
加序列化字段特性
[SerializeField]
private int i;
系列化就是把一个对象保存到一个文件或数据库字段中
3、公共的可以显示编辑
4、公共的也不让其显示编辑
加特性
[HideInInspector]
public int i2 = 0;
5、大部分类型都能显示编辑
//可以显示
public int[] array;
public List<int> list;
public E_TestEnum type;
public GameObject gameObj;//字典Dictionary、自定义类型变量不能显示
6、让自定义类型可以被访问
在自定义的类上面加特性
[System.Serializable]
public struct MyStruct
{public string name;public int age;
}
//字典Dictionary都不行
7、一些辅助特性
1、分组说明特性 Header为成员分组[Header("基础属性")]public int age;public bool sex;[Header("战斗属性")]public int atk;public int def;
2、悬停注释 Tooltip为变量添加说明[Tooltip("闪避")]public int miss;
3、间隔特性 Space让两个字段之间出现间隔[Space()]public int crit;
4、修饰数值的滑条范围 Range[Range(0,10)]public float luck;
5、多行显示字符串,默认3行 Multiline[Multiline()]public string tips;
6、滚动条显示字符串,默认三行 TextArea[TextArea()]public string myLife;
7、为变量添加快捷方法 ContextMenuItem参数1:显示按钮名参数2;方法名,不能有参数[ContextMenuItem("重置钱","Money")]public int money;private void Money(){money = 10;}
8、为方法添加特性能够在Inspector中执行[ContextMenu("测试")]private void TestFunc(){print("测试方法");money = 20;}添加特性原理:Unity通过反射得到类的信息,然后在Inspector窗口中显示字段信息Unity内部通过反射获取字段的特征,当具有一些特殊特性时,便会做相应的处理
注意事项
1、Inspector窗口中的变量关联的就是对象的成员变量,运行时改变他们就是在改变成员变量
2、拖拽到GameObject对象后,再改变脚本中变量默认值,界面上不会改变
3、运行中修改的信息不会保存
4、Mono中的重要内容
1、重要成员
[ContextMenu("我的测试")]
private void TestFunc()
{1、获取依附的GameObjectprint(gameObject.name);2、获取依附的GameObject的位置信息print(transform.position);print(transform.eulerAngles);//欧拉角print(transform.lossyScale);//缩放大小3、获取脚本是否激活enabled = false;4、获取其他的脚本信息public Test3 otherTest3;//在Unity中相互关联[ContextMenu("我的测试")]private void TestFunc(){print(otherTest3.gameObject.name);print(otherTest3.transform.position);}
2、重要方法
得到依附对象上挂载的其他脚本
1、得到自己挂载的单个脚本 GetComponent
根据脚本名获取,获取失败返回NullTest3_null t = this.GetComponent("Test3_null") as Test3_null;print(t);
根据Type获取t = GetComponent(typeof(Test3_null)) as Test3_null;print(t);
根据泛型获取,建议使用泛型,不用二次转换t = GetComponent<Test3_null>();print(t);
只有能得到场景中别的对象或者对象依附的脚本,就能获取到它的所有信息
2、得到自己挂载的多个脚本
//数组
Test3[] array = GetComponents<Test3>();
print(array.Length);
//List
List<Test3> list = new List<Test3>();
GetComponents<Test3>(list);
print(list.Count);
3、得到子对象挂载的脚本(默认也会找自己是否挂载脚本)
//得子对象得单个脚本
参数false:不找失活,参数true:找失活;不填默认为false
不填默认为false
Test3 t3 = GetComponentInChildren<Test3>();
print(t3);//得子对象得多个脚本
//数组
Test3[] li1 = GetComponentsInChildren<Test3>();
print(li1.Length);
//List
List<Test3> li2 = new List<Test3>();
GetComponentsInChildren(true,li2);
print(li2.Count);
4、得到父对象挂载的脚本(默认也会找自己是否挂载脚本)
得父类多单个脚本t3 = GetComponentInParent<Test3>();print(t3);
得父类多个脚本//数组li1 = GetComponentsInParent<Test3>();print(li1.Length);//ListGetComponentsInParent(true, li2);print(li2.Count);
5、尝试获取脚本
if (TryGetComponent<Test3>(out t3)) { }
6、思考 this
this 代表依附在GameObject自己这个脚本对象
this.gameObject 代表这个脚本对象依附的GameObject游戏对象
this.transform 代表这个脚本对象依附的GameObject游戏对象的位置相关信息