unity 脚本 – 笔记

发布于 2022-11-06  95 次阅读


--------脚本编程--------

9.1 脚本

unity中使用vsCode编辑脚本
在unity中 菜单-edit-External Tools-选择用vsCode编辑
如果vsCode没有代码提示,需要使用vsCode打开整个unity项目,在控制台输出日志Omnisharp Log的输出中检查是否缺少对应版本的.net SDK,下载相应的sdk。在vscode中安装c#插件。

unity加载的脚本,文件名必须与类名一致,这点和java一样了。其实c#的话是允许不一致的,只不过unity要求一致。

9.2 当前物体

中文API https://docs.unity3d.com/cn/2021.2/ScriptReference/index.html

ToString("F3") flot格式化三位小数
update方法 帧更新
帧时间间隔Time.deltaTime

11.1 物体的移动

float dy = speed*Time.deltaTime;
this.transform.Translate(0,dy,0,Space.Self);

11.1.1 引用问题

Java的函数调用都是值传递 只不过有的对象、引用型变量是引用传递
C#既有值传递又有引用传递 分类型 值传递类型:结构,枚举,基础数据类型(排除string)

结构体和类的区别
结构体是值类型,类是引用类型结构体存在栈中,类存在堆中结构体成员不能使用protected访问修饰符,而类可以结构体成员变量申明不能指定初始值,而类可以结构体不能申明无参的构造函数,而类可以结构体申明有参构造函数后,无参构造不会被顶掉结构体不能申明析构函数,而类可以结构体不能被继承,而类可以。结构体需要在构造函数中初始化所有成员变量,而类随意结构体不能被静态static修饰(不存在静态结构体),而类可以

结构体和类在使用上很类似,结构体甚至可以用面向对象的思想来形容一类对象。结构体具备着面向对象思想中封装的特性,但是它不具备继承和多态的特性,因此大大减少了它的使用频率。

结构体和类最大的区别是在存储空间上的,因为结构体是值,类是引用,因此他们的存储位置一个在栈上,一个在堆上,通过之前知识点的学习,我相信你能够从此处看出他们在使用的区别——值和引用对象在赋值时的区别。

由于结构体不具备继承的特性,所以它不能够使用protected保护访问修饰符。

如何选择结构体和类
要用到继承和多态时,直接淘汰结构体。比如玩家、怪物等等
对象是数据集合时,优先考虑结构体。比如位置、坐标等等从值类型和引用类型赋值区别上去考虑,比如时长需要被赋值被传递的对象,且改变赋值的对象,原对象不想跟着变时,就用结构体。比如坐标、向量、旋转等等

Unity 为什么不能直接修改vector3.x yz
原因就在于Vector3是一个结构体,而position是一个自动实现的属性。 public struct Vector3
在C#里,结构体是值类型的,值类型在通过方法传递的时候,所传递的只是值的副本。
C#的属性可以说是两个分别名为get和set的方法
而当我们写出形如 transform.position.x = 1 这样的代码时,是在通过get方法得到position,然后修改position的x字段的值。
但是,由于position是结构体类型的,get得到的也只是position的一个副本,而对这个副本所作出的任何修改,都对原positon没有任何影响,因此这样的修改是毫无意义的。编译器会禁止这样的修改操作,也就是可以理解的了。

获取实体

//用名称 很容易出错
GameObject qb = GameObject.Find("TestObj");
一般都定义一个public成员变量,然后在unity绑定此脚本的实体inspector里指定。

父物体
在Transform中维护的
this.transform.parent
顶级的话没有父物体,那就是返回null。
重设父物体
transform.SetParent(Transform p)

子物体
this.transform.GetChild(0);

foreach (Transform child in transform)
{
child.position += Vector3.up * 10.0f;
}
this.transform.Find("子名称/孙子名称");
添加子物体
this.transform.add

隐藏子物体
Transform child = this.transform.Find("子物体名称");
if(child.gameObject.activeSelf){
child.gameObject.SetActive(false);
}

相对运动的方法

Space枚举 World世界 Self自身
float speed = 1;
float distance = speed * Time.deltaTime;
this.transform.Translate(0,0,distance,Space.Self);

//转向物体
GameObject qb = GameObject.Find("TestObj");
this.transform.LookAt(qb.transform);

//指定向上方向的向量。
Vector3.magnitude

//自转
float jiao = 60;
this.transform.Rotate(0, jiao * Time.deltaTime, 0, Space.Self);

//公转
1.让父节点转动,子节点也会跟着转
this.transform.parent.Rotate(0, jiao * Time.deltaTime, 0, Space.Self);
2.围绕位置转动 RotateAround
this.transform.RotateAround(this.transform.parent.position,Vector3.up, jiao * Time.deltaTime);

常见回调函数
Awake 初始化 执行一次 总是执行
Start 初始化 执行一次 组件禁用不会执行
Update 帧更新
OnEnable 此实体或脚本组件启用时调用
OnDisable 此实体或脚本组件禁用时调用

13.3 脚本执行顺序

整体按阶段执行
执行所有awake -> 执行所有start -> ......
默认所有实体脚本谁先执行不确定,与层级管理中摆放顺序无关。可以指定优先级,01234 顺序执行

主控脚本

用来设置全局

脚本的参数

全局变量可以在unity里展示并编辑 必须声明为public。
这样不同的实体可以定义不同的变量,但是使用同一个脚本。
unity中参数赋值是先于脚本的awake执行的。

特性

[Tooltip("特性")]
public float speed = 1f;

特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。 您可以通过使用特性向程序添加声明性信息。 一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。

自定义结构体在Inspector上显示

1.在自定义结构体前加 [System.Serializable]
[System.Serializable]
public struct TestStruct
{
public float a;
public float b;
public float c;

}

2.在创建该结构体时在前面加 [SerializeField]
[SerializeField]
public TestStruct testStruct3;

在play状态下保存参数

可以在play下copy component
停止后在past component values
实现参数的拷贝


啦啦啦!