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、获取依附的GameObject
print(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
根据脚本名获取,获取失败返回Null
Test3_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);
//List
GetComponentsInParent(true, li2);
print(li2.Count);
5、尝试获取脚本
if (TryGetComponent<Test3>(out t3)) { }
6、思考 this
this 代表依附在GameObject自己这个脚本对象
this.gameObject 代表这个脚本对象依附的GameObject游戏对象
this.transform 代表这个脚本对象依附的GameObject游戏对象的位置相关信息