Unity入门
将之前的笔记整理下来
Unity概叙
Unity是一个游戏开发的集成工具,降低了游戏开发的门槛,提高了开发效率。
工程文件夹
Assets:工程资源文件夹(美术资源脚本)
Library:库文件夹
Logs:日志文件夹
obj:编译中间文件
Packages:包配置信息
ProjectSettings:工程设置信息
Unity界面基础
Inspector检查窗口:用于设置游戏对象具体信息
Console控制台窗口:用于显示调试信息,报错、警告、打印信息等
Scene场景窗口:所有游戏对象所在地
Hierarchy层级窗口:所有游戏的对象名单
Game游戏窗口:玩家看到的游戏画面
Project工程窗口:所有游戏资源和脚本内容
Scence场景和Hierarchy层级窗口
Hierarchy
我们可以在Hierarchy窗口中创建或拖入各种游戏对象。
Hierarchy层级窗口快捷键:
F2:对象改名
Ctrl+C:复制
Ctrl+V:粘贴
Ctrl+D:克隆一个
Delete:删除
Scence
我们可以在Scene窗口中查看所有游戏对象设置所有游戏对象。
窗口上方工具条内容:
1.渲染模式
2.2D、3D视图切换
3.光源、音效、特效显示开启
4.辅助线显示
5.辅助功能,控制场景上提示图标等
6.搜索
7.场景轴向
关于Unity中的3D世界坐标轴:
红色为X轴正向
绿色为Y轴正向
蓝色为Z轴正向
以屏幕为参照物:
垂直屏幕向内为Z正方向
平行屏幕向右为X正方向
平行屏幕向上为Y正方向
场景中的操作:
左键相关:
鼠标单击:选中单个物体
鼠标框选:选中多个物体
Ctrl+鼠标单击:多选物体
长按ALT键+鼠标左键+移动鼠标:相对观察视口中心点旋转
选中物体之后,按F键:居中显示物体(或者在层级窗口中双击对象)
右键相关:
鼠标右键按下+移动鼠标:旋转视口
鼠标右键按下+WASD:漫游场景
鼠标右键按下+WASD+Shift:快速漫游场景
长按ALT键+鼠标右键+移动鼠标:相对屏幕中心点拉近拉远
中键相关:
滚动鼠标中间:相对屏幕中心点拉近拉远
鼠标中间按下+移动鼠标:平移观察视口
长按ALT键+滚动鼠标中间:鼠标指哪就朝哪拉近拉
Game游戏和Project工程
Game
游戏画面窗口,玩家能看到的画面内容.
Project
工程资源窗口,所有的工程资源都会在该窗口
中显示,显示的内容为Assets文件夹中的所有内容.
Project工程窗口关键功能:
1.窗口设置
2.创建相关资源文件
3.查找
4.按资源类型查找
5.按名字查找
资源类型:
图片格式:jpg、png、tga
模型格式:fbx、max、maya
音效:wav、mp3、ogg
文本:txt、json、bytes
视频:mp4
Inspector检查和Console控制台
Inspector
查看场景中游戏对象关联的C#脚本信息.
Console
用于查看调试信息的窗口报错、警告、测试打印都可以显示在其中,默认未开启可以在Window——>General中开启或者使用快捷键:Ctrl+Shift+C,该窗口将显示代码编译过程中或者游戏运行过程中的报错、警告、测试信息主要用于查错和调试用。
Console控制台窗口:
1.清空控制台
2.相同内容折叠显示
3.运行时清空
4.构建时清空
5.报错暂停运行
6.是否显示错误信息
7.是否显示警告信息
8.是否显示打印信息
工具栏和父子关系
工具栏
从左到右:
1.文件操作:新建工程,新建场景,工程打包等等
2.编辑操作:对象编辑操作相关,工程设置,引擎设置相关
3.资源操作:基本等同于Project窗口中右键相关功能
4.对象操作:基本等同于Hierarchy窗口中右键相关功能
5.脚本操作:Unity自带的脚本,可以添加各系统中的脚本
7.窗口:可以打开Unity各核心系统的窗口
9.帮助:检查更新,查看版本等等功能
File中的重要选项:BuildSetting(工程发布打包)
Edit中的重要选项:Project Setting(工程各系统设置)、Preferences(首选项,可以设置编程软件)、GameObject中的重要选项:MoveToView、Align With View、Align View to Selected(几种快捷设置位置的功能)
父子关系
对象之间产生父子关系后,如何相互影响?爸爸干嘛,儿子干嘛;儿子干嘛,爸爸不管。
Scene上方作用:
pivot:以本身为中心点;
center:以整体为中心点;
local:以本身旋转为朝向;
global:以世界坐标为朝向;
Unity工作原理
使用它时是处于运行中的,我们是在一个运行中的软件里制作游戏的,Unity开发的本质就是在Unity引擎的基础上,利用反射和引擎提供的各种功能进行的拓展开发。
反射机制和游戏场景
反射机制的体现:除了Transform这个表示位置的标配剧本外,我们可以为这个演员(GameObject)关联各种剧本(C#脚本),让它按照我们剧本中(代码逻辑中)的命令来处理事情,而为演员添加剧本的这个过程,就是在利用反射new一个新的剧本对,象和演员(GameObject)对象进行关联,让其按我们的命令做事;
利用反射举例体现:
1.修改Inspector面板中Transform的内容:已知对象,类名,变量名,通过反射为该对象设置变量值;
2.新建一个脚本后,添加给一个指定的GameObject对象:已知类名,可以获取所有公共成员,故可以在Inspector
面板上创建各公共字段信息
游戏场景的本质:游戏场景文件后缀为.unity,它的本质就是一个配置文件,Unity有一套自己识别处理它的机制,但是本质就是把场景对象相关信息读取出来,通过反射来创建各个对象关联各个脚本对象;
预设物和资源包的导入导出
后缀名:.prefab,Prefabs放该类型文件;
预制物删除变红处理:点击预制物右键Unpack Prefab;
Project右键:导入导出包(.unitypackage);
Unity脚本基础
默认脚本内容:Editor\Data\Resources\ScriptTemplates
脚本基本规则
1.创建规则:
1.不在VS中创建脚本了
2.可以放在Assets文件夹下的任何位置(建议同一文件夹管理)
3.类名和文件名必须一致,不然不能挂载(因为反射机制创建对象,会通过文件名去找Type)
4.建议不要使用中文名命名
5.没有特殊需求 不用管命名空间
6.创建的脚本默认继承MonoBehavior
2.MonoBehavior基类:
1.创建的脚本默认都继承MonoBehaviour 继承了它才能够挂载在GameObject上
2.继承了MonoBehavior的脚本不能new 只能挂!!!!!!!!
3.继承了MonnBehavior的脚本不要去写构造函数,因为我们不会去new它,写构造函数没有任何意义
4.继承了MonoBehavior的脚本可以在一个对象上挂多个(如果没有加DisallowMultipleComponent特性)
5.继承MonoBehavior的类也可以再次被继承,遵循面向对象继承多态的规则
3.不继承MonoBehavior的类
1.不继承Mono的类 不能挂载在GameObject上
2.不继承Mono的类 想怎么写怎么写 如果要使用需要自己new
3.不继承Mono的类 一般是单例模式的类(用于管理模块) 或者数据结构类(用于存储数据)
4.不继承Mono的类 不用保留默认出现的几个函数
生命周期函数
总结:这些生命周期函数 如果你不打算在其中写逻辑 那就不要使用这些命周期函数。
我们要知道,虽然建议大家不在继承MonoBehavior的类中写构造函数;
但是不意味着我们不能写,当我们在继承MonoBehavior的类中写无参构造函数时,你会发现在编辑模式下或者运行后,只要该脚本挂载在场景中,那么该无参构造函数是会被自动执行的。
因为Unity的工作原理中提到的反射机制,Unity实际上通过反射帮助我们实例化了该脚本对象,既然要实例化那么肯定是需要new的,只不过Unity中不需要我们自己new继承了MonoBehavior的类,只要挂载后Unity帮助我们做了这件事。
那么为什么不建议大家写构造函数呢?
1.Unity的规则就是,继承MonoBehavior的脚本不能new只能挂载
2.生命周期函数的Awake是类似构造函数的存在,当对象出生就会自动调用
3.写构造函数反而在结构上会破坏Unity设计上的规范
打印方式:
普通:Debug.Log(“123”);
报错:Debug.LogError(“出错了!!!!!”);
警告:Debug.LogWarning(“警告!!!”);
Inspector窗口可编辑变量
知识点一: 私有和保护无法显示编辑,公共的可以显示编辑;
知识点二 :[SerializeField]让私有的和保护的也可以被显示;
知识点三:[HideInInspector]公共的也不让其显示编辑;
知识点四:[System.Serializable] 让自定义类型可以被访问;//加在类前,而字典怎么都不行
知识点七: 辅助特性
1.[Header(“分组说明”)] :分组说明特性,为成员分组;
2.[Tooltip(“说明内容”)] //悬停注释,为变量添加说明;
3.[Space()]:间隔特性,让两个字段间出现间隔
4.[Range(最小值, 最大值)] //修饰数值的滑条范围;
5.[TextArea(3, 4)] :滚动条显示字符串,默认不写参数就是超过3行显示滚动条;
6.[ContextMenuItem(“显示按钮名”, “方法名”)] :为变量添加快捷方法,参数1 显示按钮名,参数2 方法名 不能有参数;
7.[Multiline(4)] :多行显示字符串 默认不写参数显示3行
8.[ContextMenu(“测试函数”)] :方法添加特性能够在Inspector中执行
继承自MonoBehavior重要内容
重要成员
1.获取依附的GameObject:this.gameObject;
2.获取依附的GameObject的位置信息:
-print(this.transform.position);//位置
-print(this.transform.eulerAngles);//角度
-print(this.transform.lossyScale);//缩放大小
3.获取脚本是否激活: this.enabled;
重要方法
1:得到依附对象上挂载的其它脚本
//1.得到自己挂载的单个脚本,获取脚本的方法 如果获取失败 就是没有对应的脚本 会默认返回空
this.GetComponent("脚本名");
//2.得到自己挂载的多个脚本
this.GetComponents<泛形类型>();
//3.得到子对象挂载的脚本(它默认也会找自己身上是否挂载该脚本)
//函数是有一个参数的 默认不传 是false 意思就是 如果子对象失活 是不会去找这个对象上是否有某个脚本的
//如果传true 及时 失活 也会找
//得子对象 挂载脚本 单个
this.GetComponentInChildren<泛形类型>(true);
this.GetComponentsInChildren<泛形类型>(true);
//4.得到父对象挂载的脚本(它默认也会找自己身上是否挂载该脚本)
this.GetComponentInParent<泛形类型>();
this.GetComponentsInParent<泛形类型>();
//5.尝试获取脚本
//提供了一个更加安全的 获取单个脚本的方法 如果得到了 会返回true
//然后在来进行逻辑处理即可
this.TryGetComponent<泛形类型>(out 赋值变量)
Unity重要组件和API
GameObject最小单位
直接实例化:new GameObject(“实体名”,typeof(要添加的组件名)…….) ;
注意事项:
1.建议使用Destroy方法,它是异步的,不会马上删除对象,只是给对象加一个标识,一般情况下下一帧才会把对象从内存一处。;
2.如果继承自mono,可以省略GameObject字段;
3.对象失活也是可以用一些方式获取的;
4.广播方法效率很低,不建议使用;
知识点一 GameObject中的成员变量
//名字
print(this.gameObject.name);
this.gameObject.name = "Lesson4唐老狮改名";
print(this.gameObject.name);
//是否激活
print(this.gameObject.activeSelf);
//是否是静态
print(this.gameObject.isStatic);
//层级
print(this.gameObject.layer);
//标签
print(this.gameObject.tag);
transform
this.transform 上一节课讲解的 通过Mono去得到的依附对象的GameObject的位置信息
//他们得到的信息是一样 都是依附的GameObject的位置信息
print(this.gameObject.transform.position);
知识点二 GameObject中的静态方法
//创建自带几何体
//只要得到了一个GameObject对象 我就可以得到它身上挂在的任何脚本信息
//通过obj.GetComponent来得去
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
obj.name = "唐老狮创建的立方体";
//查找对象相关的知识
//两种找单个对象的共同点:
//1.无法找到失活的对象的
// 只能找到 激活的对象
//2.如果场景中 存在多个满足条件的对象
// 我们无法准确确定找到的是谁
//1查找单个对象
//通过对象名查找
//这个查找效率比较低下 因为他会在场景中的所有对象去查找
//没有找到 就会返回null
GameObject obj2 = GameObject.Find("唐老狮");
//通过tag来查找对象
GameObject obj3 = GameObject.FindWithTag("Player");
//和上面的方法一样,名字不一样而已
GameObject obj3 = GameObject.FindGameObjectWithTag("Player");
//得到某一个单个对象 目前有2种方式了
//1.是public从外部面板拖 进行关联
//2.通过API去找
//2查找多个对象
//找多个对象的API 只能是通过tag去找多个 通过名字 是没有找多个的方法的
//通过tag找到多个对象
//它也是 只能找到 激活对象 无法找到失活对象
GameObject obj3 = GameObject.FindGameObjectsWithTag("Player");
//还有几个查找对象相关是用的比较少的方法 是GameObject父类 Object提供的方法
//引出额外知识点 Unity中的Object和C#中的万物之父的区别
//Unity里面的Object 不是指的万物之父object
//Unity里的Object 命名空间在UnityEngine中的 Object类 也是集成万物之父的一个自定义类
//C#中的Object 命名空间是在System中的
//它可以找到场景中挂载的某一个脚本对象
//效率更低 上面的GameObject.Find 和通过FindWithTag找 只是遍历对象
//这个方法 不仅要遍历对象 还要遍历对象上挂载的脚本
Lesson4 o = GameObject.FindObjectOfType<Lesson4>();
print(o.gameObject.name);
//实例化对象(克隆对象)的方法
//实例化(克隆)对象 它的作用 是根据一个GameObject对象 创建出一个和它一模一样的对象
GameObject obj5 = GameObject.Instantiate(myObj);
//以后学了更多知识点 就可以在这操作obj5
//如果你继承了 MonoBehavior 其实可以不用写GameObject一样可以使用
//因为 这个方法时Unity里面的 Object基类提供给我们的 所以可以直接用
Instantiate(myObj);
//删除对象的方法
GameObject.Destroy(myObj2);
//第二个参数 代表延迟几秒钟删除
GameObject.Destroy(obj5, 5);
Destroy不仅可以删除对象 还可以删除脚本
GameObject.Destroy(this);
//删除对象有两种作用
//1.是删除指定的一个游戏对象
//2.是删除一个指定的脚本对象
//注意:这个Destroy方法 不会马上移除对象 只是给这个对象加了一个移除标识
// 一般情况下 它会在下一帧时把这个对象移除并从内存中移除
//如果没有特殊需求 就是一定要马上移除一个对象的话
//建议使用上面的 Destroy方法 因为 是异步的 降低卡顿的几率
//下面这个方法 就是立即把对象 从内存中移除了
GameObject.DestroyImmediate(myObj);
//如果是继承MonoBehavior的类 不用写GameObject
Destroy(myObj2);
DestroyImmediate(myObj);
//过场景不移除
//默认情况 在切换场景时 场景中对象都会被自动删除掉
//如果你希望某个对象 过场景不被移除
//下面这句代码 就是不想谁过场景被移除 就传谁
//一般都是传 依附的GameObject对象
//比如下面这句代码的意思 就是自己依附的GameObject对象 过场景不被删除
GameObject.DontDestroyOnLoad(this.gameObject);
//如果继承MOnoBehavior也可以直接写
DontDestroyOnLoad(this.gameObject);
知识点三 GameObject中的成员方法
//创建空物体
//new一个GameObject就是在创建一个空物体
GameObject obj6 = new GameObject();
GameObject obj7 = new GameObject("唐老狮创建的空物体");
GameObject obj8 = new GameObject("顺便加脚本的空物体", typeof(Lesson2),typeof(Lesson1));
//为对象添加脚本
//继承MOnoBehavior的脚本 是不能够去new
//如果想要动态的添加继承MonoBehavior的脚本 在某一个对象上
//直接使用GameObject提供的方法即可
Lesson1 les1 = obj6.AddComponent(typeof(Lesson1)) as Lesson1;
//用泛型更方便
Lesson2 les2 = obj6.AddComponent<Lesson2>();
//通过返回值 可以得到加入的脚本信息
//来进行一些处理
//得到脚本的成员方 和继承Mono的类得到脚本的方法 一模一样
//标签比较
//下面两种比较的方法 是一样的
if(this.gameObject.CompareTag("Player"))
{
print("对象的标签 是 Player");
}
if(this.gameObject.tag == "Player")
{
print("对象的标签 是 Player");
}
//设置激活失活
//false 失活
true 激活
obj6.SetActive(false);
obj7.SetActive(false);
obj8.SetActive(false);
//次要的成员方法 了解即可 不建议使用
//强调
//下面讲的方法 都不建议大家使用 效率比较低
//通过广播或者发送消息的形式 让自己或者别人 执行某些行为方法
//通知自己 执行什么行为
//命令自己 去执行这个TestFun这个函数 会在自己身上挂在的所有脚本去找这个名字的函数
//它会去找到 自己身上所有的脚本 有这个名字的函数去执行
this.gameObject.SendMessage("TestFun");
this.gameObject.SendMessage("TestFun2", 199);
//广播行为 让自己和自己的子对象执行
this.gameObject.BroadcastMessage("函数名");
//向父对象和自己发送消息 并执行
this.gameObject.SendMessageUpwards("函数名");
UnityEngine.GameObject - Unity 脚本 API (unity3d.com)
Time时间相关
作用:主要 用于游戏中参与位移、记时、时间暂停等;
重要内容:
//知识点一 时间缩放比例
//时间停止
Time.timeScale = 0;
//回复正常
Time.timeScale = 1;
//2倍速
Time.timeScale = 2;
//知识点二 帧间隔时间
//帧间隔时间 主要是用来计算位移
//路程 = 时间*速度
//根据需求 选择参与计算的间隔时间
//如果希望 游戏暂停时就不动的 那就使用
Time.deltaTime;
//如果希望 不受暂停影响
Time.unscaledDeltaTime;
//帧间隔时间:最近的一帧 用了多长时间(秒)
//受scale影响
print("帧间隔时间" + Time.deltaTime);
//不受scale影响的帧间隔时间
print("不受scale影响的帧间隔时间" + Time.unscaledDeltaTime);
知识点三 游戏开始到现在的时间
//它主要用来计时 单机游戏中计时
//受scale影响
print("游戏开始到现在的时间:" + Time.time);
//不受scale影响
print("不受scale影响的游戏开始到现在的时间:" + Time.unscaledTime);
知识点四 物理帧间隔时间 FixedUpdate
//受scale影响
Time.fixedDeltaTime;
//不受scale影响
Time.fixedUnscaledDeltaTime;
知识点五 帧数
//从开始到现在游戏跑了多少帧(次循环)
print(Time.frameCount);
UnityEngine.Time - Unity 脚本 API (unity3d.com)
Transform-位置和位移
Vector3
常用:
//常用变量
print(Vector3.zero);//000
print(Vector3.right);//100
print(Vector3.left);//-100
print(Vector3.forward);//001
print(Vector3.back);//00-1
print(Vector3.up);//010
print(Vector3.down);//0-10
//常用方法 (后续加)
//计算两个点之间的距离的方法
print(Vector3.Distance(v1, v12));
//返回float 两个向量之间的角度(以度为单位)
Vector3.Angle();
UnityEngine.Vector3 - Unity 脚本 API (unity3d.com)
位置
(注意:位置的赋值不能直接改变x,y,z 只能整体改变)
位移方式:
//知识点一:位置
//相对世界坐标系
this.gameObject.transform;
//相对父对象
this.transform.localPosition;
//世界正朝向
Vector3.forwad;
//本身正朝向
transform.forward;
//知识点二 位移
//坐标系下的位移计算公式:路程 = 方向 * 速度 * 时间
//方式一 自己计算
//想要变化的 就是 position
//用当前的位置 + 我要动多长距离 得出最终所在的位置
this.transform.position = this.transform.position + this.transform.up * 1 * Time.deltaTime;
//因为我用的是 this.transform.forward 所以它始终会朝向相对于自己的面朝向去动
this.transform.position += this.transform.forward * 1 * Time.deltaTime;
//方向非常重要 因为 它决定了你的前进方向
this.transform.position += Vector3.forward * 1 * Time.deltaTime;
//方式二 API
//参数一:表示位移多少 路程 = 方向 * 速度 * 时间
//参数二:表示 相对坐标系 默认 该参数 是相对于自己坐标系的
//1相对于世界坐标系的 Z轴 动 始终是朝 世界坐标系 的 Z轴正方向移动
this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World);
//2相对于世界坐标的 自己的面朝向去动 始终朝自己的面朝向移动
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);
//3相对于自己的坐标系 下的 自己的面朝向向量移动 (一定不会这样让物体移动) XXXXXXX
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.Self);
//4相对于自己的坐标系 下的 Z轴正方向移动 始终朝自己的面朝向移动
this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.Self);
UnityEngine.Transform - Unity 脚本 API (unity3d.com)
Tramsfrom-角度和旋转
知识点一 角度相关
相对世界坐标角度:transform.eulerAngles;
相对父对象角度:transform.localEulerAngles;
知识点二 旋转相关
//自己计算(省略 和位置一样 不停改变角度即可)
//API计算
//自转
//每个轴 具体转多少度
//第一个参数 相当于 是旋转的角度 每一帧
//第二个参数 默认不填 就是相对于自己坐标系 进行的旋转
this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime);
this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime, Space.World);
//相对于某个轴 转多少度
//参数一:是相对哪个轴进行转动
//参数二:是转动的 角度 是多少
//参数三:默认不填 就是相对于自己的坐标系 进行旋转
// 如果填 可以填写相对于 世界坐标系进行旋转
this.transform.Rotate(Vector3.right, 10 * Time.deltaTime);
this.transform.Rotate(Vector3.right, 10 * Time.deltaTime, Space.World);
//相对于某一个点转
//参数一:相当于哪一个点 转圈圈
//参数二:相对于那一个点的 哪一个轴转圈圈
//参数三:转的度数 旋转速度 * 时间
this.transform.RotateAround(Vector3.zero, Vector3.right, 10 * Time.deltaTime);
Transfrom-缩放和看向
知识点一 缩放
//相对世界坐标系
print(this.transform.lossyScale);
//相对本地坐标系(父对象)
print(this.transform.localScale);
//注意:
//1.同样缩放不能只改xyz 只能一起改(相对于世界坐标系的缩放大小只能得 不能改)
//所以 我们一般要修改缩放大小 都是改的 相对于父对象的 缩放大小 localScale
this.transform.localScale = new Vector3(3, 3, 3);
//2.Unity没有提供关于缩放的API
//之前的 旋转 位移 都提供了 对应的 API 但是 缩放并没有
//如果你想要 让 缩放 发生变化 只能自己去写(自己算)
this.transform.localScale += Vector3.one * Time.deltaTime;
知识点二 看向
//让一个对象的面朝向 可以一直看向某一个点或者某一个对象
//看向一个点 相对于世界坐标系的
this.transform.LookAt(Vector3.zero);
//看向一个对象 就传入一个对象的 Transform信息
this.transform.LookAt(lookAtObj);
Transfrom-父子关系
知识点一 获取和设置父对象
//获取父对象
print(this.transform.parent.name);
//设置父对象 断绝父子关系
this.transform.parent = null;
//设置父对象 认爸爸
this.transform.parent = GameObject.Find("Father2").transform;
//通过API来进行父子关系的设置
this.transform.SetParent(null);//断绝父子关系
this.transform.SetParent(GameObject.Find("Father2").transform);//认爸爸
//参数一:我的父亲
//参数二:是否保留世界坐标的 位置 角度 缩放 信息
// true 会保留 世界坐标下的状态 和 父对象 进行计算 得到本地坐标系的信息
// false 不会保留 会直接把世界坐标系下的 位置角度缩放 直接赋值到 本地坐标系下
this.transform.SetParent(GameObject.Find("Father3").transform, false);
知识点二 抛妻弃子
//就是和自己的所有儿子 断绝关系 没有父子关系了
this.transform.DetachChildren();
知识点三 获取子对象
//按名字查找儿子
//找到儿子的 transform信息
//Find方法 是能够找到 失活的对象的 !!!!! GameObject相关的 查找 是不能找到失活对象的
print(this.transform.Find("Cube (1)").name);
//他只能找到自己的儿子 找不到自己的孙子 !!!!!!
print(this.transform.Find("GameObject").name);
//虽然它的效率 比GameObject.Find相关 要高一些 但是 前提是你必须知道父亲是谁 才能找
//遍历儿子
//如何得到有多少个儿子
//1.失活的儿子也会算数量
//2.找不到孙子 所以孙子不会算数量
print(this.transform.childCount);
//通过索引号 去得到自己对应的儿子
//如果编号 超出了儿子数量的范围 那会直接报错的
//返回值 是 transform 可以得到对应儿子的 位置相关信息
this.transform.GetChild(0);
知识点四 儿子的操作
//判断自己的爸爸是谁
//一个对象 判断自己是不是另一个对象的儿子
if(son.IsChildOf(this.transform))
{
print("是我的儿子");
}
//得到自己作为儿子的编号
print(son.GetSiblingIndex());
//把自己设置为第一个儿子
son.SetAsFirstSibling();
//把自己设置为最后一个儿子
son.SetAsLastSibling();
//把自己设置为指定个儿子
//就算你填的数量 超出了范围(负数或者更大的数) 不会报错 会直接设置成最后一个编号
son.SetSiblingIndex(1);
Transfrom-坐标转换
知识点一 世界坐标转本地坐标
print(Vector3.forward);
//世界坐标系 转本地坐标系 可以帮助我们大概判断一个相对位置
//世界坐标系的点 转换 为相对本地坐标系的点
//受到缩放影响
print("转换后的点 " + this.transform.InverseTransformPoint(Vector3.forward));
//世界坐标系的方向 转换 为相对本地坐标系的方向
//不受缩放影响
print("转换后的方向" + this.transform.InverseTransformDirection(Vector3.forward));
//受缩放影响
print("转换后的方向(受缩放影响)" + this.transform.InverseTransformVector(Vector3.forward));
知识点二 本地坐标转世界坐标
//本地坐标系的点 转换 为相对世界坐标系的点 受到缩放影响
print("本地 转 世界 点" + this.transform.TransformPoint(Vector3.forward));
//本地坐标系的方向 转换 为相对世界坐标系的方向
//不受缩放影响
print("本地 转 世界 方向" + this.transform.TransformDirection(Vector3.forward));
//受缩放影响
print("本地 转 世界 方向" + this.transform.TransformVector(Vector3.forward));
Input输入相关
//知识点一 鼠标在屏幕位置
Input.mousePosition
//知识点二 检测鼠标输入
//鼠标按下一瞬间 进入
//0左键 1右键 2中键
Input.GetMouseButtonDown(0)
//中键滚动
//返回值的 y -1往下滚 0没有滚 1往上滚
//它的返回值 是Vector的值 我们鼠标中键滚动 会改变其中的Y值
print(Input.mouseScrollDelta);
//知识点三 检测键盘输入
//传入字符串的重载
//这里传入的 字符串 不能是大写的 不然会报错
//只能传入小写字符串
Input.GetKeyDown("q")
//推荐枚举型
Input.GetKey(KeyCode.W)
//知识点四 检测默认轴输入
//我们学习鼠标 键盘输入 主要是用来
//控制玩家 比如 旋转 位移等等
//所以Unity提供了 更方便的方法 来帮助我们控制 对象的 位移和旋转
//键盘AD按下时 返回 -1到1之间的变换
//相当于 得到得这个值 就是我们的 左右方向 我们可以通过它来控制 对象左右移动 或者左右旋转
float h = Input.GetAxis("Horizontal");
//键盘SW按下时 返回 -1到1之间的变换
//得到得这个值 就是我们的 上下方向 我们可以通过它来控制 对象上下移动 或者上下旋转
print(Input.GetAxis("Vertical"));
//鼠标横向移动时 -1 到 1 左 右
print(Input.GetAxis("Mouse X"));
//鼠标竖向移动时 -1 到 1 下 上
print(Input.GetAxis("Mouse Y"));
//我们默认的 GetAxis方法 是有渐变的 会总 -1~0~1之间 渐变 会出现小数
//GetAxisRaw方法 和 GetAxis使用方式相同
//只不过 它的返回值 只会是 -1 0 1 不会有中间值
//知识点三 其它的监听
//是否有任意键或鼠标长按
if(Input.anyKey)
//是否有任意键或鼠标按下
if(Input.anyKeyDown)
//这一帧的键盘输入
print(Input.inputString);
//手柄输入相关
//得到连接的手柄的所有按钮名字
string[] strs = Input.GetJoystickNames();
//某一个手柄键按下
if( Input.GetButtonDown("Jump") )
//某一个手柄键抬起
if (Input.GetButtonUp("Jump"))
//某一个手柄键长按
if (Input.GetButton("Jump"))
//移动设备触摸相关
if(Input.touchCount > 0)
{
Touch t1 = Input.touches[0];
//位置
print(t1.position);
//相对上次位置的变化
print(t1.deltaPosition);
}
//是否启用多点触控
Input.multiTouchEnabled = false;
//陀螺仪(重力感应)
//是否开启陀螺仪 必须开启 才能正常使用
Input.gyro.enabled = true;
//重力加速度向量
print(Input.gyro.gravity);
//旋转速度
print(Input.gyro.rotationRate);
//陀螺仪 当前的旋转四元数
//比如 用这个角度信息 来控制 场景上的一个3D物体受到重力影响
//手机怎么动 它怎么动
print(Input.gyro.attitude);
UnityEngine.Input - Unity 脚本 API (unity3d.com)
Screen屏幕相关
//知识点一 静态属性
//常用
//当前屏幕分辨率
Resolution r = Screen.currentResolution;
print("当前屏幕分辨率的宽" + r.width + "高" + r.height);
//屏幕窗口当前宽高
//这得到的 是当前 窗口的 宽高 不是设备分辨率的宽高
//一般写代码 要用窗口宽高 做计算时 就用他们
print(Screen.width);
print(Screen.height);
//屏幕休眠模式
Screen.sleepTimeout = SleepTimeout.NeverSleep;
//不常用
//运行时是否全屏模式
Screen.fullScreen = true;
//窗口模式
//独占全屏FullScreenMode.ExclusiveFullScreen
//全屏窗口FullScreenMode.FullScreenWindow
//最大化窗口FullScreenMode.MaximizedWindow
//窗口模式FullScreenMode.Windowed
Screen.fullScreenMode = FullScreenMode.Windowed;
//移动设备屏幕转向相关
//允许自动旋转为左横向 Home键在左
Screen.autorotateToLandscapeLeft = true;
//允许自动旋转为右横向 Home键在右
Screen.autorotateToLandscapeRight = true;
//允许自动旋转到纵向 Home键在下
Screen.autorotateToPortrait = true;
//允许自动旋转到纵向倒着看 Home键在上
Screen.autorotateToPortraitUpsideDown = true;
//指定屏幕显示方向
Screen.orientation = ScreenOrientation.Landscape;
知识点二 静态方法
//设置分辨率 一般移动设备不使用
Screen.SetResolution(1920, 1080, false);
UnityEngine.Screen - Unity 脚本 API (unity3d.com)
Camera摄像机相关
1.*Clear Flags:
如何清除背景:
skybox天空盒(3D)
Solid Color颜色填充(2D)
Depth only 只画该层,背景透明(叠加渲染)
Don't Clear 不移除,覆盖渲染
2.*Culling Mask
选择性渲染部分层级:可以指定只渲染对应层级的对象
3.*Projection
2.1Perspective 透视模式
FOV Axis:视场角 轴-决定了光学仪器的视野范围
Field of view:视口大小
Physical Camera:物理摄像机、勾选后可以模拟真实世界中、摄像机、焦距、传感器尺寸、透镜移位等等
Focal Length:焦距
Sensor Type:传感器类型
Sensor Size:传感器尺寸
Lens Shift:透镜移位
Gate Fit:闸门配合
2.2orthographic 正交摄像机(一般用于2D游戏制作)
Size:摄制范围
4.*Clipping Planes:
裁剪平面距离(近和远)
5.Viewport Rect:
视口范围屏幕上将绘制该摄像机视图的位置:
主要用于双摄像机游戏
0~1 相当于宽高百分比
6.*Depth:
渲染顺序上的深度(多个摄像机,越小的越先渲染,大的覆盖小的)
7.Redering path:
渲染路径
8.*Target Texture:
渲染纹理:
可以把摄像机画面渲染到一张图上:主要用于制作小地图(摄像机渲染到这张图上)
在Project右键创建 Render Texture
9.*Occlusion Culling:
是否启用剔除遮挡(性能优化)
10.Allow HDR:
是否允许高动态范围渲染
11.Allow MSAA:
是否允许抗锯齿
12.Allow Dynamic Resolution:
是否允许动态分辨率呈现
13.Target Display:
用于哪个显示器:主要用来开发有多个屏幕的平台游戏
代码相关:
知识点一 重要静态成员
//1.获取摄像机
//如果用之前的知识 来获取摄像机
//主摄像机的获取
//如果想通过这种方式 快速获取摄像机 那么场景上必须有一个 tag为MainCamera的摄像机
print(Camera.main.name);
//获取摄像机的数量
print(Camera.allCamerasCount);
//得到所有摄像机
Camera[] allCamera = Camera.allCameras;
print(allCamera.Length);
//2.渲染相关委托
//摄像机剔除前处理的委托函数
Camera.onPreCull += (c) =>
{
};
//摄像机 渲染前处理的委托
Camera.onPreRender += (c) =>
{
};
//摄像机 渲染后 处理的委托
Camera.onPostRender += (c) =>
{
};
知识点二 重要成员
//1.界面上的参数 都可以在Camera中获取到
//比如 下面这句代码 就是得到主摄像机对象 上的深度 进行设置
Camera.main.depth = 10;
//2.世界坐标转屏幕坐标
//转换过后 x和y对应的就是屏幕坐标 z对应的 是 这个3D物体 里我们的摄像机有多远
//我们会用这个来做的功能 最多的 就是头顶血条相关的功能
Vector3 v = Camera.main.WorldToScreenPoint(this.transform.position);
print(v);
//3.屏幕坐标转世界坐标
//只所以改变Z轴 是因为 如果不改 Z默认为0
//转换过去的世界坐标系的点 永远都是一个点 可以理解为 视口 相交的焦点
//如果改变了Z 那么转换过去的 世界坐标的点 就是相对于 摄像机前方多少的单位的横截面上的世界坐标点
Vector3 v = Input.mousePosition;
v.z = 5;
obj.position = Camera.main.ScreenToWorldPoint(v);
//print(Camera.main.ScreenToWorldPoint(v));
UnityEngine.Camera - Unity 脚本 API (unity3d.com)
核心系统
光源系统基础
Light组件
1.*Type:光源类型
Spot:聚光灯
Range:发光范围距离
Spot Angle:光锥角度
Directional:方向光(环境光)
Point:点光源
Area:面光源(烘焙下用)
2.*Color:
颜色
3.*Mode:光源模式
Realtime:
实时光源
每帧实时计算,效果好,性能消耗大
Baked:
烘焙光源
事先计算好,无法动态变化
Mixed:
混合光源
预先计算+实时运算
4.*Intensity:
光源亮度
5.Indirect Multiplier:
改变间接光的强度
低于1,每次反弹会使光更暗大于1,每次反弹会使光更亮
6.*Shadow Type:
NoShadows:关闭阴影
HardShadows:生硬阴影
SoftShadows:柔和阴影
7.RealtimeShadows
Strength:阴影暗度 0~1之间,越大越黑
Resolution:阴影贴图渲染分辨率,越高越逼真,消耗越高
Bias:阴影推离光源的距离
Normal Bias:阴影投射面沿法线收缩距离
Near Panel:渲染阴影的近裁剪面
8.*Cookie:
投影遮罩(用图制作光照的样子)
9.Cookie Size:
大小设置
10.Draw Halo:
球形光环开关(光晕)
11.*Flare:
耀斑(工程文件可以自己右键创建该类型文件,想再Game显示,摄像机添加Flare Layer脚本)
12.Render Mode:渲染模式
Auto:运行时确定
Important:以像素质量为单位进行渲染,效果逼真,消耗大
Not Important:以快速模式进行渲染
13.*Culling Mask:剔除遮罩层,决定哪些层的对象受到该光源影响
UnityEngine.Light - Unity 脚本 API (unity3d.com)
光窗口
1.Environment-环境相关设置
Skybox Material-天空盒材质:可以改变天空盒(创建天空盒创建一个材质球将种类设置为skybox)
Sun Source-太阳来源:不设置会默认使用场景中最亮的方向光代表太阳
Environment Lighting-环境光设置:
Source-环境光光源颜色:
Skybox:天空和材质作为环境光颜色
Gradient:可以为天空、地平线、地面单独选择颜色和他们之间混合
Intensity Multiplier-环境光亮度;
Ambient Mode-全局光照模式只有启用了实时全局和全局烘焙时才有用:
Realtime(已弃用)
Baked
2.OtherSettings-其它设置:
Fog-雾开关(性能消耗):
Color-雾颜色:
Mode-雾计算模式:
Linear-随距离线性增加:
Start:离摄像机多远开始有雾
End:离摄像机多远完全遮挡
Exponential-随距离指数增加:-Density-强度;
Exponential Qquare-随距离比指数更快的增加-Density:强度;
Halo Texture:光源周围挥着光环的纹理
Halo Strength:光环可见性
Flare Fade Speed:耀斑淡出时间最初出现之后淡出的时间;
Flare Strength:耀斑可见性
Spot Cookie:聚光灯默认剪影纹理
Lighting 窗口 - Unity 手册 (unity3d.com)
物理系统之碰撞检测
Rigidbody组件
重点:碰撞产生的必要条件,两个物体都有碰撞器,至少一个物体有刚体。
1.RigidBody组件信息:
Mass:质量(默认为千克)质量越大惯性越大;
Drag:空气阻力根据力移动对象时影响对象的空气阻力大小,0 表示没有空气阻力;
Angular Drag:根据扭矩旋转对象时影响对象的空气阻力大小。0 表示没有空气阻力;
Use Gravity:是否受重力影响
Is Kinematic:如果启用此选项,则对象将不会被物理引擎驱动,只能通过 (Transform) 对其进行操作。对于移动平台,或者如果要动画化附加了 HingeJoint 的刚体,此属性将非常有用;
Interpolate-(物理帧时间长时使用)插值运算,让刚体物体移动更平滑:
None:不应用插值运算;
Interpolate:根据前一帧的变换来平滑变换;
Extrapolate:差值运算,根据下一帧的估计变换来平滑变换;
Constraints-约束,对刚体运动的限制:
Freeze Position:有选择地停止刚体沿世界 X、Y 和 Z 轴的移动;
Freeze Rotation:有选择地停止刚体围绕局部 X、Y 和 Z 轴旋转;
Collision Detection(碰撞检测模式)-用于防止快速移动的对象穿过其它对象而不检测碰撞:
Discrete(离散检测):对场景中的所有其他碰撞体使用离散碰撞检测。其他碰撞体在测试碰撞时会使用离散碰撞检测。用于正常碰撞(这是默认值);
Continuous(连续检测):对动态碰撞体(具有刚体)使用离散碰撞检测,并对静态碰撞体(没有刚体)使用连续碰撞检测;设置为连续动态 (Continuous Dynamic) 的刚体将在测试与该刚体的碰撞时使用连续碰撞检测。(此属性对物理性能有很大影响,如果没有快速对象的碰撞问题,请将其保留为 Discrete 设置),其他刚体将使用离散碰撞检测。
Continuous Speculative(连续推测检测):对刚体和碰撞体使用推测性连续碰撞检测。该方法通常比连续碰撞检测的成本更低。
API:
//知识点一 刚体自带添加力的方法
//给刚体加力的目标就是
//让其有一个速度 朝向某一个方向移动
//1.首先应该获取刚体组件
rigidBody = this.GetComponent<Rigidbody>();
//2.添加力
//相对世界坐标
//世界坐标系 Z轴正方向加了一个里
//加力过后 对象是否停止移动 是由阻力决定的
//如果阻力为0 那给了一个力过后 始终 是不会停止运动
rigidBody.AddForce(Vector3.forward * 10);
//如果想要在 世界坐标系方法中 让对象 相对于自己的面朝向动
rigidBody.AddForce(this.transform.forward * 10);
//相对本地坐标
rigidBody.AddRelativeForce(Vector3.forward * 10);
//3.添加扭矩力,让其旋转
//相对世界坐标
rigidBody.AddTorque(Vector3.up * 10);
//相对本地坐标
rigidBody.AddRelativeTorque(Vector3.up * 10);
//4.直接改变速度
//这个速度方向 是相对于 世界坐标系的
//如果要直接通过改变速度 来让其移动 一定要注意这一点
rigidBody.velocity = Vector3.forward * 5;
//5.模拟爆炸效果
//模拟爆炸的力 一定是 所有希望产生爆炸效果影响的对象
//都需要得到他们的刚体 来执行这个方法 才能都有效果
rigidBody.AddExplosionForce(100, Vector3.zero, 10);
//知识点二 力的几种模式
//第二个参数 力的模式 主要的作用 就是 计算方式不同而已
//由于4中计算方式的不同 最终的移动速度就会不同
rigidBody.AddForce(Vector3.forward * 10, ForceMode.Acceleration);
//动量定理
//Ft = mv
// v = Ft/m;
//F:力
//t:时间
//m:质量
//v:速度
//1.Acceleration
//给物体增加一个持续的加速度,忽略其质量
//v = Ft/m
//F:(0,0,10)
//t:0.02s
//m:默认为1
//v = 10*0.02/ 1 = 0.2m/s
//每物理帧移动0.2m/s*0.02 = 0.004m
//2.Force
//给物体添加一个持续的力,与物体的质量有关
//v = Ft/m
//F:(0,0,10)
//t:0.02s
//m:2kg
//v = 10*0.02/ 2 = 0.1m/s
//每物理帧移动0.1m/s*0.02 = 0.002m
//3.Impulse
//给物体添加一个瞬间的力,与物体的质量有关,忽略时间 默认为1
//v = Ft/m
//F:(0,0,10)
//t:默认为1
//m:2kg
//v = 10*1/ 2 = 5m/s
//每物理帧移动5m/s*0.02 = 0.1m
//4.VelocityChange
//给物体添加一个瞬时速度,忽略质量,忽略时间
//v = Ft/m
//F:(0,0,10)
//t:默认为1
//m:默认为1
//v = 10*1/ 1 = 10m/s
//每物理帧移动10m/s*0.02 = 0.2m
//知识点三 力场脚本(Unity封装好了的组件)
ConstantForce组件
//补充 刚体的休眠
//获取刚体是否处于休眠状态 如果是
if (rigidBody.IsSleeping())
{
//就唤醒它
rigidBody.WakeUp();
}
UnityEngine.Rigidbody - Unity 脚本 API (unity3d.com)
碰撞器
碰撞器面板说明:
1.3D碰撞器种类
1.盒状
2.球状
3.胶囊
4.网格
5.轮胎
6.地形
2.共同参数:
Is Trigger:是否是触发器,如果启用此属性,则该碰撞体将用于触发事件,并被物理引擎忽略,主要用于进行没有物理效果的碰撞检测;
Material:物理材质(工程右键可以创建一个物理材质.material文件),可以确定碰撞体和其它对象碰撞时的交互(表现)方式。
Center:碰撞体在对象局部空间中的中心点位置
3.常用碰撞器:
BoxCollider-盒状碰撞器-Size:碰撞体在X、Y、Z方向上的大小;
Sphere Collider-球状碰撞器-Radius:球形碰撞体的半径大小;
Capsule Collider-胶囊碰撞器:
Radius:胶囊体的半径
Height:胶囊体的高度
Direction:胶囊体在对象局部空间中的轴向
4.异形物体使用多种碰撞器组合:刚体对象的子对象碰撞器信息参与碰撞检测;
5.不常用碰撞器:
Mesh Collider-网格碰撞器:
Convex:勾选此复选框可启用 Convex。如果启用此属性,该 Mesh Collider 将与其他 Mesh Collider 发生碰撞。Convex Mesh Collider 最多 255 个三角形。
Cooking Options-启用或禁用影响物理引擎对网格处理方式的网格烹制选项:
-None:禁用下方列出的所有 Cooking Options
-Everything:启用下方列出的所有 Cooking Options。
-Cook for Faster Simulation:使物理引擎烹制网格以加快模拟速度。启用此设置后,这会运行一些额外步骤,以保证生成的网格对于运行时性能是最佳的。这会影响物理查询和接触生成的性能。禁用此设置后,物理引擎会使用更快的烹制速度,并尽可能快速生成结果。因此,烹制的 Mesh Collider 可能不是最佳的。
-Enable Mesh Cleaning:使物理引擎清理网格。启用此设置后,烹制过程会尝试消除网格的退化三角形以及其他几何瑕疵。此过程生成的网格更适合于在碰撞检测中使用,往往可生成更准确的击中点。
-Weld Colocated Vertices:使物理引擎在网格中删除相等的顶点。启用此设置后,物理引擎将合并具有相同位置的顶点。这对于运行时发生的碰撞反馈十分重要。
Mesh:引用需要用于碰撞的网格。
Wheel Collider-环状 碰撞器:
Mass:车轮的质量
Radius:车轮的半径
Wheel Damping Rate:这是应用于车轮的阻尼值
Suspension Distance:车轮悬架的最大延伸距离(在局部空间中测量)。悬架始终向下延伸穿过局部 Y 轴。
Force App Point Distance:此参数定义车轮上的受力点。此距离应该是距车轮底部静止位置的距离(沿悬架行程方向),以米为单位。当 forceAppPointDistance = 0 时,受力点位于静止的车轮底部。较好的车辆会使受力点略低于车辆质心。
Suspension Spring:悬架尝试通过增加弹簧力和阻尼力来到达目标位置 (Target Position)
-Spring:弹簧力尝试到达目标位置。值越大,悬架达到目标位置就越快
-Damper:抑制悬架速度。值越大,悬架弹簧移动就越慢
-Target Position:悬架沿悬架距离 (Suspension Distance) 的静止距离。1 对应于完全展开的悬架,0 对应于完全压缩的悬架。默认值为 0.5,与常规汽车的悬架行为匹配。
Forward Friction-车轮向前滚动时轮胎摩擦的特性;Sideways Friction车轮侧向滚动时轮胎摩擦的特性—:
-Extremum Slip:曲线的极值点。
-Extremum Value:曲线的极值点。
-Asymptote Slip:曲线的渐近点。
-Asymptote Value:曲线的渐近点。
-Stiffness:Extremum Value 和 Asymptote Value 的乘数(默认值为 1)。改变摩擦力的刚度。将此值设置为零将完全禁用车轮的所有摩擦力。通常在运行时修改刚度以使用脚本来模拟各种地面材质。
注意事项:不必通过转动或滚动 WheelCollider 对象来控制汽车;附加了 WheelCollider 的对象应始终相对于汽车本身固定;
Terrain Collider-地形碰撞器
Terrain Data:地形数据
Enable Tree Colliders:选中此属性时,将启用树碰撞体
物理材质
物理材质参数说明
Dynamic Friction:已在移动时使用的摩擦力。通常为 0 到 1 之间的值。值为零就像冰一样,值为 1 将使对象迅速静止(除非用很大的力或重力推动对象)
Static Friction:当对象静止在表面上时使用的摩擦力。通常为 0 到 1 之间的值。值为零就像冰一样,值为 1 将导致很难让对象移动。
Bounciness:表面的弹性如何?值为 0 将不会反弹。值为 1 将在反弹时不产生任何能量损失,预计会有一些近似值,但可能只会给模拟增加少量能量。
Friction Combine-两个碰撞对象的摩擦力的组合方式:
-Average:对两个摩擦值求平均值。
-Minimum:使用两个值中的最小值。
-Maximum:使用两个值中的最大值。
-Multiply:两个摩擦值相乘。
unce Combine:两个碰撞对象的弹性的组合方式。其模式与 Friction Combine 模式相同
碰撞检测函数
注意:碰撞和触发响应函数 属于 特殊的生命周期函数 也是通过反射调用.
//知识点一 物理碰撞检测响应函数
//碰撞触发接触时会 自动执行这个函数
private void OnCollisionEnter(Collision collision)
{
//Collision类型的 参数 包含了 碰到自己的对象的相关信息
//关键参数
//1.碰撞到的对象碰撞器的信息
//collision.collider
//2.碰撞对象的依附对象(GameObject)
//collision.gameObject
//3.碰撞对象的依附对象的位置信息
//collision.transform
//4.触碰点数相关
//collision.contactCount
//接触点 具体的坐标
//ContactPoint[] pos = collision.contacts;
//只要得到了 碰撞到的对象的 任意一个信息 就可以得到它的所有信息
print(this.name + "被" + collision.gameObject.name + "撞到了");
}
//碰撞结束分离时 会自动执行的函数
private void OnCollisionExit(Collision collision)
{
print(this.name + "被" + collision.gameObject.name + "结束碰撞了");
}
//两个物体相互接触摩擦时 会不停的调用该函数
private void OnCollisionStay(Collision collision)
{
print(this.name + "一直在和" + collision.gameObject.name + "接触");
}
//知识点二 触发器检测响应函数
//触发开始的函数 当第一次接触时 会自动调用
protected virtual void OnTriggerEnter(Collider other)
{
print(this.name + "被" + other.gameObject.name + "触发了");
}
//触发结束的函数 当水乳相融的状态结束时 会调用一次
private void OnTriggerExit(Collider other)
{
print(this.name + "被" + other.gameObject.name + "结束水乳相融的状态了");
}
//当两个对象 水乳相融的时候 会不停调用
private void OnTriggerStay(Collider other)
{
print(this.name + "和" + other.gameObject.name + "正在水乳相融");
}
音效系统
音频文件导入
1.导入参数设置
常用格式:wav、mp3、ogg、aiff;
音频文件属性设置
Force To Mono:多声道转单声道;
Normalize:强制为单声道时,混合过程中被标准化;
Load In Background:在后台加载,不阻塞主线程;
Ambisonic:立体混响声 ,非常适合 360 度视频和 XR 应用程序,如果音频文件包含立体混响声编码的音频,请启用此选项;
LoadType-加载类型:
Decompress On Load:不压缩形式存在内存,加载块,但是内存占用高(适用于小音效文件);
Compress in memory:压缩形式存在内存,加载慢,内存小(仅适用于较大音效文件)
Streaming:以流形式存在,使用时解码。内存占用最小,cpu消耗高(性能换内存)
Preload Audio Data:预加载音频,勾选后进入场景就加载,不勾选,第一次使用时才加载
Compression Format-压缩方式:
PCM:音频以最高质量存储
Vorbis:相对PCM压缩的更小,根据质量决定
ADPCM:包含噪音,会被多次播放的声音,如碰撞声
Quality:音频质量,确定要应用于压缩剪辑的压缩量。(不适用于 PCM/ADPCM/HEVAG 格式)
Sample Rate Setting-PCM 和 ADPCM 压缩格式允许自动优化或手动降低采样率:
Preserve Sample Rate:此设置可保持采样率不变(默认值);
Optimize Sample Rate:此设置根据分析的最高频率内容自动优化采样率;
Override Sample Rate:此设置允许手动覆盖采样率,因此可有效地将其用于丢弃频率内容;
音频源和音频监听组件
组件面板说明:
AudioSource-音频源:
AudioClip:声音剪辑文件(音频文件)
Output:默认将直接输出到场景中的音频监听器,可以更改为输出到混音器(音乐游戏可能会用);
Mute:静音开关;
Bypass Effect:开关滤波器效果;
Bypass Listener Effects:快速开关所有监听器;
Bypass Reverb Zones:快速开关所有混响区
Play On Awake:对象创建时就播放音乐,也就是开关启动游戏就播放;
Loop:循环
Priority:优先级(越大越不容易被其他音效覆盖)
Volume:音量大小
Pitch:音高
Stereo Pan:2D声音立体声位置。相当于左右声道
Spatial Blend:音频受3D空间的影响程度(设置是2d游戏还是3d音效)
Reverb Zone Mix:到混响区的输出信号量
3D Sound Settings-和Spatial Blend参数成正比应用:
Doppler Level:多普勒效果等级
Spread:扩散角度设置为3D立体声还是多声道
Volume Rolloff-声音衰减速度:
Logarithmic Rolloff:靠近音频源时,声音很大,但离开对象时,声音降低得非常快。
Linear Rolloff:与音频源的距离越远,听到的声音越小。
Custom Rolloff:音频源的音频效果是根据曲线图的设置变化的。
Min/Max Distance:最小距离内,声音保持最大响度;最大距离外,声音开始减弱;
AudioListener-音频监听脚本;
音频源代码控制
//知识点一 代码控制播放停止
//播放音效
audioSource.Play();
//延迟播放 填写的是秒数
audioSource.PlayDelayed(5);
//停止音效
audioSource.Stop();
//暂停
audioSource.Pause();
//停止暂停 和暂停后 Play效果是一样的 都会继续播放现在的音效
audioSource.UnPause();
知识点二 如何检测音效播放完毕
//如果你希望某一个音效播放完毕后 想要做什么事情
//那就可以在Update生命周期函数中 不停的去检测 它的 该属性
//如果是false就代表播放完毕了
audioSource.isPlaying
知识点三 如何动态控制音效播放
//1.直接在要播放音效的对象上挂载脚本 控制播放
//2.实例化挂载了音效源脚本的对象
//这种方法 其实用的比较少
//Instantiate(obj);
//3.用一个AudioSource来控制播放不同的音效
//AudioSource aus = this.gameObject.AddComponent<AudioSource>();
//aus.clip = clip;
//aus.Play();
//潜在知识点
//一个GameObject可以挂载多个 音效源脚本AudioSource
//使用时要注意 如果要挂载多个 那一定要自己管理他们 控制他们的播放 停止 不然 我们没有办法准确的获取
//谁是谁
UnityEngine.AudioClip - Unity 脚本 API (unity3d.com)
麦克风输入相关
知识点一 获取设备麦克风信息
string[] strs = Microphone.devices;
知识点二 开始录制
//参数一:设备名 传空使用默认设备
//参数二:超过录制长度后 是否重头录制
//参数三:录制时长
//参数四:采样率
clip = Microphone.Start(null, false, 10, 44100);
知识点三 结束录制
Microphone.End(null);
知识点四 获取音频数据用于存储或者传输
//规则 用于存储数组数据的长度 是用 声道数 * 剪辑长度
float[] f = new float[clip.channels * clip.samples];
clip.GetData(f, 0);
print(f.Length);