笔记主要包含脚本简介,
GameObject
, Time
, Transform
等六大组件以及光源物理音效三大系统的简单入门,除了概念就是API,坚持学完赶紧做项目吧,有一说一还是很枯燥的,be a 无情的 API learner
Unity脚本基础
大基础
依附基类:MonoBehaviour
tips:依附了该基类的类不能实例化,只能挂载(表现形式为把写好的脚本拖到对象上)到具体的对象上产生实例化的效果
限制只能挂一个相同脚本特性:[DisallowMultipleComponent]
帧的概念:一秒内循环的次数,如1秒60帧需要每次循环的时间达到16.66ms,30帧需要达到33.33ms
Unity里输出日志:
Debug.log("输出的内容")
=》没有继承Mono
基类print("输出的内容")
=>继承了Mono
基类(你也是python?)
生命周期函数
unity运行时的本质是一个死循环,不断执行下面这些生命周期函数
下面的顺序即为执行时的顺序(但是又看到一个说法,说是FixedUpdate
不一定在Update
前调用,要根据它实际的物理时间来看)
Awake()
:只在开始时的初始化时调用一次,可看作类似于构造函数OnEnable()
:对象在激活(Inspector
窗口左上角打勾)时调用Start()
:只在开始时的帧更新时调用一次FixedUpdate()
:物理模块的更新,自设定的帧更新(左上角编辑中程序环境中Time一项中设置)Update()
:帧更新,主要处理逻辑的地方LateUpdate()
:比上面慢一点的帧更新,通常用来更新摄像机(在两个帧更新当中通常处理动画相关,避免渲染出问题)OnDisable()
:与OnEnable()
对应,对象在失活时调用OnDestroy()
:删除对象时调用
tips:这些函数并不是Mono
中的成员函数,unity在运行脚本时通过反射查看是否有这些函数,如果有才执行相关逻辑,所以如果不用这些函数就不要生命,会损失效率
Inspector窗口显示
如果有公有成员变量,将会自动显示在该窗口
常用特性
[SerializeField]
:使私有和保护修饰的成员变量能够显示[HideInInspector]
:使公有的成员变量不显示[Serializable]
:使自定义类型显示(该特性在System
中)
tips:字典和自定义类型不会显示,自定义类型可以通过加特性显示,而字典无论如何都无法显示
辅助特性
[Header("组名")]
:用于将不同的变量进行分组[Tooltip("说明")]
:对变量的额外说明,鼠标指向变量即可看到[Space()]
:变量与变量之间间隔距离[Range(x,y)]
:拖条改值,x和y为上下限[Multiline(x)]
:将字符串改成x行显示,按↑↓拖条[TextArea(x,y)]
:字符串改为最小x行显示,最大y行显示,比y大可以用滚轮拖条[ContextMenuItem("按钮名称","方法")]
:让变量有方法可用,右键相关变量即可用[ContextMenu("方法")]
:让方法能在运行中使用
MnonBehaviour基类
成员变量
- 类名变量
gameObject
:有name
的属性,获取相关脚本名称 - 位置变量
transform
:有position
位置,ealerAngles
角度,lossyscale
缩放大小的属性 - 激活变量
enabled
:判断对象是否激活
成员方法
※※※ 获取脚本
GetComponent
:最常用方便的泛型式获取
GetComponent<"脚本名称">()
按照名字获取
GetComponent("脚本名称")
按照类型获取
GetComponent(typedef(脚本名称))
tips:后两种获取的为
Mnon
基类,要使用需要将其as
为脚本类型,较为麻烦,后续也不再阐述这两种方法
获取多个脚本
GetComponent<>()
:- 该方法会返回数组,需要用数组接住
- 或者提前声明一个
list
,将其作为参数传入
获取后代脚本
GetComponentInChildren<>()
:参数为true
时可以找到失活对象的脚本获取多个后代脚本
GetComponentsInChildren<>()
:同上获取前辈脚本
GetComponentInparent<>()
获取多个前辈脚本
GetComponentsInparent<>()
尝试获取脚本
TryGetComponent<>()
:未获取对象会返回false
,等效于使用GetComponent
方法获取脚本后判空执行逻辑
组件GameObject
成员变量gameObject
属性有name
名称,activeSelf
是否激活,isStatic
是否为静态,layer
查看层次,tag
查看标签,transform
看到位置
静态方法
- 创建几何体
CreatePrimitive(PrimitiveType.xxx)
:xxx为具体的几何体 - 用名字找一个对象
Find("名字")
- 用标签找一个对象
FindWithTag("标签")
或FindGameObjectWithTag("标签")
- 用标签找多个对象
FindGameObjectsWithTag("标签")
(以上几种均不能找到失活对象)
另外的,还有Object
(unity里的基类,不是c#里那个,Mono
往上找也继承了它)里面的方法找对象方法FindObjectOfType<脚本名称>()
tips:这几种找对象的方法均不常用,效率太低了
- 实例化(克隆)对象
Instantiate(obj)
:动态创建对象,在运行时把预设体或对象拖到obj
处,这里的obj
是一个提前声明一个GameObject
(Object
也可以点出这个方法) - 延迟删除对象
Destroy(见后)
:一帧后删除,异步的,可减少长停顿的概率;若为删对象,参数(obj,希望延迟删除的时间)
;若为删脚本,参数(脚本名称) - 立即删除对象
DestroyImmediate()
:不建议使用,效率低 - 过场景不删对象
DontDestroyOnLoad(this.gameObject)
:参数通常为这个
成员方法
使用其中的方法前要先new
一个,但new
的时候其实就创建出一个新物体了
GameObject obj = new GameObject("物体名字",typeof("希望挂载的脚本名"),......)
- 为对象添加脚本
AddComponent(typeof(脚本名称))
,该方法和前面提到的缺陷一样,还要as
,所以一般使用泛型式AddComponent<脚本名称>()
- 得到脚本:与
Mono
基类成员方法部分获取脚本一致 - 标签比较
CompareTag("标签")
:返回T/F - 设置活性
SetActive(bool)
- 广播之通知自己执行什么
SendMessage("函数名")
:在自己身上的所有脚本里去找这个函数来执行 - 广播之把后代也找一下
BroadcaseMessage("函数名")
- 广播之把前辈也找一下
SendMessageUpwards("函数名")
tips:广播用的少,效率低
组件Time
静态成员变量
- 时间缩放
Time.timeScale
:为0时表现为时停,为1时正常流速,为2时二倍速 - 帧间隔时间(最近一次循环的时间)
Time.deltaTime
:可用于计算位移,该时间会受timeScale
影响(即与其相乘后得出结果),对应的有Time.unScaleDeltaTime
不受timeScale
影响 - 从游戏开始到现在的时间
Time.time
:受timeScale
影响,对应的有Time.unscaledTime
不受其影响 - 物理帧间隔时间
Time.fixedDeltaTime
:受timeScale
影响,可在左上角进行Project Setting
设置,对应的有Time.fixedUnscaledDeltaTime
不受其影响 - 帧数
Time.frameCount
组件Transform
不要搞混:transform
本质是一个Transfoem
类,它是Mono
基类中的一个成员,使用它和使用Transform
是一个效果,直接使用this.transform
更为快捷,当然this
也可以直接省略
Vector3结构体基础
基本概念
即包含x,y,z三个坐标的一个结构体向量表示
常用向量表示
Vector3.zero
表示(0,0,0),one
表示(1,1,1),相应的right
和left
,forward
和back
,up
和down
分别为三组表示x轴,z轴,y轴上的三组向量=》世界坐标系下的方向
常用方法
Vector3.Distance(Vector v1, Vector v2)
:计算两点间距离
位置与位移
位置position
本质是一个Vector3
- 世界坐标系下的坐标
transform.position
- 相对于父对象的坐标
transform.localPosition
:该数值与右边面板上的一致
改变位置时只能整体改变,如让position
直接加上new Vector3(x,y,z)
如果要单独改,采用向量形式,如加上Vector3.up * 10
自己坐标系下方向的表示:transform.forward
或者其他五个
位移 = 方向 * 速度 * 时间
自己算位移:如transform.position += transform.forward * 1 * Time.deltaTime
,时间通常使用帧间隔时间
如果要采用世界坐标下的方向,则为Vector3.forward
API计算位移(通常下计算位移的方法)transform.Translate(位移多少,相对的坐标系)
:第一个参数即上面的右式,第二个参数默认相对自己,若要改变,有Space.World/Self
来改变
坑点:Translate
实际上在算偏移量,如果用自己坐标下transform
作为第一个参数,且相对于自己Self
,则会产生一个不服预期的新方向去动,即一般不用这两者进行搭配
角度与旋转
3d数学中的四元数transform.rotation
下面为对角度的使用,本质还是Vector3
- 世界坐标系下的角度
transform.eulerAngles
- 相对于父对象的角度
transform.localEulerAngles
:同理,界面上一致
改变角度也一样不能单独设置,只能整体改变
API计算自转(通常不自己算)transform.Rotate(转的角度,相对的坐标系)
:与计算位移时基本一致,但是此处不能使用transform.forward
这种直接表示,要去new
一个Vector3
去乘角度(时间 * 速度)
通用下的自转重载(常用):transform.Rotate(相对于哪个轴,角度,相对的坐标系)
:这里相对于哪个轴就可以用Vector.forward
此类向量表示了
绕某点转transform.RotateAround(绕谁转,绕谁的哪个轴,角度)
:可以用来模拟太阳系,这里这个“谁”传他的Vector
就行
缩放与看向
缩放
- 世界坐标系下的缩放
transform.lossyScale
- 相对于父对象的缩放
transform.localScale
一样,只能整体改,但是,相对于世界的不能改,只能得(层级叠加下,子类会乘上父类的缩放值造成意想不到的结果)
=》但是呢又是但是,可以间接做到:没有父对象的时候,改local
就是相对于世界的
没API,要改只能自己加来算(悲)
看向
某游戏里按滚轮锁敌
transform.LookAt(谁)
:传Vector
或者Transform
都行
小技巧:可以在脚本里定义一个Transform
,运行时拖过去
其实还有相对于哪个轴的参数,但没必要,默认是相对于y轴的,以我们的head为例,看别人的时候一般只会绕着y轴左右转,,,
父子关系
对父对象操作
获取父对象transform.parent
:对该项.name
可获取父对象名称
设置当前对象的父对象:
- 自己认父
transform.parent = GameObject.Find("父对象名称").transform
:设置为null
可断绝父子关系 - API认父
transform.SetParent(父对象transform, 是否改变世界坐标)
:对第二个参数,为true
时会和父对象算相对位置,视觉上当前对象位置不变;为false
时是将世界坐标直接赋值给父子关系中自己的坐标,保持面板上前后坐标的一致
对子对象操作
扔了所有儿子transform.DetachChildren()
获取子对象Transform[] sons = transform.Find("子对象名称")
- 与
GameObject.Find()
不同,这里获取的直接是子对象的transform
,但是泛用性比GameObject
的差,只能找子对象,基于此,效率会比GameObject
那个要高一点 - 同时该方法可以找到失活对象
- 儿子可能有多个,所以要用数组来存,用
sons.childCount
可获取儿子数量,sons.Getchild(下标)
可获取具体的儿子,这两者结合可以遍历儿子
单个子对象的操作
假设现在有public
成员Transform son
,对哪个儿子操作在运行时拖过去即可
- 判断自己是不是某人的儿子
son.IsChildOf(某人的transform)
:你是不是我爸 - 得到自己是第几个儿子
son.GetSiblingIndex()
:我是几房的 - 将自己设置为0号长子
son.SetAsFirstSibling()
:谋权篡位 - 将自己设置为最小的幼子
son.SetAsLastSibling()
:博得宠爱 - 将自己设置为n号儿子
son.SetsiblingIndex(n)
:当n不合法时会自动设置为幼子
坐标转换
世界=》本地
可用于判断相对位置,用的不多
- 点坐标的转换
transform.InverseTransformPoint(要转换的世界坐标向量Vector3)
:受缩放影响,返回值即为本地坐标向量(就是画两个坐标系算不同的位置) - 方向的转换:
transform.InverseTransformDirection(Vector3)
不受缩放影响,transform.InverseTransformVector()
受缩放影响(本质上是方向向量的平移)
本地=》世界
重点,有什么用呢=》特效创建:创建一个技能对象后,让他留在原地进行攻击范围的判断,不因为自己转向而跟着转向(王者荣耀安琪拉二技能也没跟着你跑吧)
- 点坐标的转换
transform.TransformPoint(Vector3)
:受缩放影响 - 方向的转换:上面那个部分去掉
Inverse
即可(偷个懒)
组件Input与Screen
输入系统Input
比较重要的成员
鼠标位置Input.mousePosition
:原点在左下角,会返回一个向量,z恒等于零
鼠标输入
Input.GetMouseButtonDown(n)
:在按下时检测,n=0时检测左键,=1时检测右键,=2时检测中键Input.GetMouseButtonUp(n)
:在抬起时检测Input.GetMouseButton(n)
:按下抬起都检测,即检测长按(拖动某个物体?)
检测中键滚动Input.mouseScrollDelta
:返回向量,y=1时向上滚动,=0时没动,=-1时向下滚动
键盘输入
Input.GetKeyDown(哪个键)
:按下检测,一般使用KeyCode
枚举来.
出具体的键,不易出错,当前也可以用字符串去匹配,但是字符必须是小写Input.GetKeyUp(哪个键)
:抬起检测Input.GetKey(哪个键)
:长按
检测默认轴输入:控制位移旋转的,嗯…相当于对上面的检测鼠标键盘再封装一层,就不用写个if
来做相关逻辑判断了
Input.GetAxis("哪个轴")
:这个轴可以去Project Settings
里的Input Manager
里查,比如说Horizontal
水平控制a和d,Vertical
垂直控制w和s,Mouse X
和Mouse Y
控制鼠标移动等等,按下对应一组键后实际上是在-1到1之间渐变Input.GetAxisRaw("哪个轴")
:没有渐变
相对不重要的
鼠标
检测任意键或鼠标长按Input.anykey
:经典按任意键继续
检测任意键按下Input.anykeyDown
检测一帧键盘输入Input.inputString
:可以和上面那个配合做改键
手柄
得到按键名称Input.GetJoystickNames()
手柄键输入Input.GetButtonDown("哪个键")
:这个是按下检测,还有抬起和长按不再赘述了
移动端触摸
不是说这个不重要,只是以后可能不在这里面检测,好像有专门的虚拟手柄UI
触摸数量Input.touchCount
具体的触摸对象Touch t1 = touches[0]
:有了对象还可以t1.position
看位置,t1.deltaPosition
相对屏幕上方位置
允许多点触碰Input.multiTouchEnabled = true
陀螺仪Input.gyro
:.enabled = true
开启,.gravity
重力加速度,.attitude
旋转四元数,.rotatioRate
转速
屏幕Screen
比较重要的成员
获取显示器屏幕分辨率Screen.currentResolution
:返回一个Resolution
结构体
设置游戏里屏幕窗口宽高Screen.width/height
设置屏幕休眠模式Screen.sleepTimeout = SleepTimeout.NeverSleep/SystemSetting
:这个实际上是int
类型的赋值,SleepTimeout
是一个类,.
出来的那两项是它里面的常量
设置分辨率Screen.SetResolution(x, y, 是否全屏)
:一般移动端不用
相对不重要的
设置全屏Screen.fullScreen = true
以下在发布上有,一般不在这边设置
窗口模式Screen.fullScreenMode = FullScreenMode.
:FullScreenMode
是一个枚举,有独占全屏,全屏窗口,最大化窗口和窗口模式四种
是否自动屏幕转向Screen.autorateTolandscapeLeft
:左边转,同理有右边转,下边转是autorotateToPortrait
,上边转是autorotateToPortraitUpsideDown
指定显示方向Screen.orientation = ScreenOrientation.
:ScreenOrientation
也是一个枚举,有水平方向等等
组件Camera
面板参数
点开一般项目创建时自带的主摄像机main camera
Clear Flags
:3d用skybox
,2d用Solid color
Culling Mask
:要画哪些layer
,剔除Projection
:透视还是正交,和坐标轴那边那个一样Depth
:两个摄像机叠加显示时,需要将该项改为不同值,该项越高,越后被渲染,同时较深的Clear Flags
要改为Depth only
Target Texture
:从Project
栏右键创建Render Texture
,可以用来贴底片做小地图Viewport Rect
:分屏Target Display
:更改Game
窗口中显示的Dieplay
代码控制
摄像机成员
获取摄像机数量Camera.allCamerasCount
获取所有的摄像机Camera.allCameras
相关委托Camera.CameraCallback
,这里的CameraCallback
是一个类型,有以下三类
onPrecull
:剔除前处理,不渲染被挡住的onPreRender
:渲染前处理onPostRender
:渲染后处理
获取主摄像机Camera.main
:实际上是获取Tag
为主摄的,但一般这样种Tag
只有一个
摄像机对象成员
以获取的main
来.
可以找到面板上所有的参数
世界转Game
屏幕坐标main.WorldToScreenPoint(世界坐标)
:返回的Vector3
中z表示物体离当前摄像机有多远=》可以用来做血条
屏幕转世界坐标main.ScreenToWorldPoint(屏幕坐标)
:这里的屏幕坐标,可以先用Input.mousePosition
获取x,y,但是要填z,不能直接传,z坐标表示一个切出来的横截面离摄像机的距离(摄像机的视角是发散出去的)
光源系统
可以到商店里获取光源资源,自带的Store
里的Standard
里,现在好像没了?
光源面板参数
和主摄像机一样,点开一般项目创建会自带一个光源Directional Light
Type
:4种光源类型,有一个是烘焙(算好贴图,节约性能)下才能用Mode
:Realtime
实时,Baked
先算好直接放,Mixed
两种的叠加Intensity
:亮度Shadow Type
:阴影类型,NoShadows
,HardShadows
生硬(带刺的影子),SoftShadows
柔和Cookie
:贴图资源,光源资源拖到这Draw Halo
:球形光环Flare
:耀斑(强化光泽的)Culling Mash
:让指定Layer
不受影响,剔除
以下为比较少用的
Indirect Multiplier
:反射后是否更弱RealtimeShadows
栏:Strength
暗度,Resdution
分辨率,Bias
离光距离,Normal Bias
延法线收缩距离,Near Panel
近裁减面Render Mode
:渲染优先级,Auto
运行时确定,Important
逼真,像素单位级别渲染,Notimportant
快速渲染
代码控制
定义一个public
的Light light
,可以用light.
出上面所有的参数,其他暂时没必要
光系统面板参数
Windows
=>Rendering
=>Light Settings
找到
Environment
栏
Skybox Material
:天空盒材质,建一个材质后Shader
做这个Sun Source
:太阳来源Environment Lights
:环境光
Other Settings
栏
Fog
:雾开关Halo Texture
:光环纹理Halo Strength
:光环可见性Flare Fade Speed
:耀斑淡出时间Flare Strength
:耀斑可见性Spot Cookie
:贴图形状
物理系统之碰撞检测
产生碰撞的条件:两个物体都要有碰撞器Collider
,并且至少有一个物体有刚体RigidBody
碰撞时产生的力实际上是作用到刚体上,与别的物体碰到后自己的刚体受到力的改变从而产生位移,碰撞器是决定物体体积的
刚体RigidBody
右下角加脚本组件可以找到
面板参数
Mass
:质量,单位kgDrag
:空气阻力Angular Drag
:扭矩阻力(阻碍旋转的力)Use Gravity
:是否受重力影响Is Kinematic
:打开后物体将不会受碰撞影响,只能通过transform
改变位置Interpolate
:插值运算(使运动变得平滑),None
,Interpolate
由上一帧预测,Extrapolate
由下一帧估计(这里的帧指的是物理帧)Collision Detection
:碰撞检测模式(防止体积太小直接穿过去了,比如说两帧间刚好跳过某物体,视觉上就是直接穿过去了没有发生碰撞),Discrete
离散,Continuous
连续,Continuous Speculative
连续检测,Continuous Dynamic
连续动态,这四项性能消耗从低到高,离散会把其他同化,不同的两种模式匹配会有不同的效果(比如两个连续会变成离散的处理,遇到问题再查表)Constraints
:约束限制,约束哪个轴,哪个轴上就不会有位移Info
:当前状态
代码控制刚体加力
刚体加力的本质是给了一个带方向的速度(啊物理学的冲刷)
获取刚体RigidBody rigidBody = GetComponent<RigidBody>()
:这是Mono
基类的那个方法
添加力rigidBody.AddForce(Vector3向量)
:相对于世界,当然,参数也可以是transform
去获取向量,加的方向不同(参考Transform
部分),对应的相对于本地rigidBody.AddRelativeForce(向量)
添加扭矩阻力(旋转)rigidBody.AddTorque(向量)
:相对于世界,对应的相对于本地rigidBody.AddRelativeTorque(向量)
改变速度rigidBody.velocity = 向量
模拟爆炸rigidBody.AddExplosionForce(100, Vector3.zoro, 10)
:参数分别为力的大小,爆炸中心坐标,半径(只影响挂在了该脚本的)
添加力还有重载rigidBody.AddForce(向量, 力的模式)
:力的模式ForceMode
可以改变力的运算方式,这是个枚举,有Acceleration
给一个持续加速度,忽略质量,Force
给一个持续的力(最正常),Impulse
给一个瞬时力,忽略时间,VelocityChange
给一个瞬时速度,忽略质量和时间(这里的忽略实际上是赋值为1,是拿动量定理Ft = mv算的速度)
添加力场(常力):这是个脚本,右边添加
Tips:有的时候(拿物体斜着去碰)为了节约性能刚体会自动休眠不起作用,可以添加代码if (rigidBody.IsSleeping) rigidBody.Wakeup()
叫醒它
碰撞器Collider
右下角加脚本组件,但一般自带,毕竟要表示体积
分类
性能高(常用):盒装Box,球状Sphere,胶囊状Capsule
准确率高:网格Mesh(无数个小三角形搭起来,效果极好CPU也很烧),轮胎(环状)Wheel,地形Terrain
Tips:异形物体的表示可通过多种碰撞器的组合,但是组合后只有给父对象加刚体才能整体进行碰撞检测,给儿子加没用
共同参数
每个碰撞器参数都不一样,但有一部分是相同的
- ※※※
IsTrigger
:勾选即认为是触发器=》不参与碰撞,只进行检测,用于事件检测(穿透攻击或者说是主角进入了某个场景触发剧情) Meterial
:物理材质,决定碰撞的方式Center
:对象局部空间中的中心点位置,即体积碰撞时计算的实际位置
物理材质的创建:Assets
右键找到Physic Meterial
创建调整后拖到上面的参数一栏
物理材质相关参数设置
Friction
:摩擦力(分为动静两个)Bounciness
:弹力Combine
:碰撞力的组合(分为摩擦力和弹力两种)
各自参数
盒状:Size
调整大小
球状:Radius
半径
胶囊状:Radius
底面半径,Height
高度,Direction
朝向
网格:Convex
有刚体后勾选这个才能碰撞其他网格,Cooking Options
,Mesh
轮胎:创建后无法显示,必须依赖其他物体(成为儿子),在父对象上点刚体后才能显示
地形:以后再看,有专门的课时
相关代码控制
碰撞检测函数
特殊的生命周期函数(严格上来讲是事件的回调,不是真正的生命周期函数),在FixedUpdate
和Update
中间调用,也是属于反射自动调用的类型
OnCollisionEnter(Collision collision)
:发生碰撞时接触时执行,写法就这样,碰的时候就把碰自己那个传进去了(这个Collision
实际上是一个事件)OnCollisionExit(Collision collision)
:离开时执行OnCollisionStay(Collision collision)
:有摩擦力时执行
得碰撞器脚本collision.collider
:除了这个,还可以得gameObject
,transform
,相当于是碰撞了后我就可以得到你所有信息
有多少点触碰collision.contractCount
得到触碰点的坐标ContactPoint[] = collision.contacts
触发器检测响应函数
也是特殊的生命周期函数,要生效必须勾选碰撞器参数里的isTrigger
OnTriggerEnter(Collider collider)
:接触时调用,可以用来判断子弹打人扣血(这里的Collider
是碰撞器的基类,即所有碰撞器组件脚本都继承)OnTriggerExit(Collider collider)
:分开时调用OnTriggerStay(Collider collider)
:重叠时调用
同样的,collider.
可以得到触发者的所有信息
其他注意事项
- 满足碰撞的条件后双方都调用函数
- 六个函数一般选择性写,正常都为
private
,可以加virtual
让子类重写 - 异形物体要调用这六个函数,刚体必须在父对象身上
音效系统
支持的音频格式:wav,mp3,ogg,aiff
添加时也是比较暴力的,外面的直接拖到Assets
就行(右键也可以)
设置导入音源的面板参数
右下角可以预览,这些参数不追求什么效果的话一般不怎么调
Force To Mono
:多声道转单声道,二级选项Normalize
是否标准化Load in Background
:后台加载,不卡主线程(可以节约性能,游戏运行时卡的不行了可以勾这个)Ambisonic
:主体混响声LoadType
:加载类型,Decompress OnLoad
不压缩,适合小音效,直接全部放内存里,加载很快,内存受罪,Compress in memory
压缩,适合大音效,内存占用小,但加载比较慢,Streaming
流,几乎不占内存了,但是CPU受罪,经典性能换内存Preload Audio Data
:预加载,勾了进场就开始加载Compresion Format
:压缩方式,PCM
几乎不压缩,Vorbis
压一点,ADPCM
压出来噪音Onality
:音频质量,不适用于PCK/ADPCM/HEVAG
Sample Rate Setting
:采样率,Preserve Sample Rate
保持,Optimize Sample Rate
优化,Override
手动覆盖
音频源AudioSource
右下角先加脚本
面板参数
说实话,如果某个参数太过专业看不懂,一般情况下应该不会去改它,看不懂的话真正要实现这个效果的时候再去学吧。。
AudioClip
:把你导入设置好的音源拖过来,就可以在运行时播放了Output
:默认输出到音频监听器,可以改到混音器Mute
:静音Bypass Effect
:开关滤波器Bypass Listener Effects
:开关所有监听器Bypass Reverb Zones
:开关所有混响区Play On Awake
:对象创建时播放音量(此时一阵强劲的音乐响起…)Loop
:循环播放(Boss战磨死Boss选手有了共鸣)Priority
:优先级(多个音乐叠加时起作用,但一般不会出现这种情况)Volume
:音量Pitch
:音高(好像是播放速度)Stereo Pan
:左右声道Spatial Blend
:受3D空间影响的程度(越远越小这种意思)Peverb Zone Mix
:混响区输出信号量3D Sound Settings
:声音远近的进阶设置,会受到Spatial Blend
参数影响(成正比)Doppler Level
:多普勒效果(音乐方面的专业知识)Spread
:扩散角度(立体还是多声道)Volume Rolloff
:声音衰减速度,Logarithmic Rolloff
靠近时声音很大,远离后衰减很快,Linear Rolloff
越远越小,Custom Rolloff
曲线图设置Min/Max Distance
:最小距离内保持的最大音量,以及超出最距离后音量消失
代码控制
获取音频源AudioSource audioSource = GetComponent<AuioSource>()
:还还还是Mono
那个
播放audioSource.Play()
:等效于停止暂停audioSource.UnPause()
。。。
停止audioSource.Stop()
暂停audioSource.Pause()
延迟播放audioSource.PlayDelayed(延迟的秒数)
以上这几种就算没勾选Play ON Awake
也可以控制
检测播放完毕audioSource.isPlaying
动态控制播放的三种方法
- 直接挂一个音频源脚本用上面的方法播放
Instantiate(obj)
:实例化一个挂在音效脚本的对象,这个方法无法去管理该对象,所以很少用- 再创建一个音频源脚本对象,设置它的
clip
成员(就是音频文件,和参数面板第一个一个类型)后,让这个新的脚本去播放
音效监听器AudioListener
这个脚本相当于是耳朵,默认挂在眼睛(主摄像机)身上
主摄像机一般就是主角的视角,而有了这个脚本后,音频源播放的音乐才行被听到
所以必须要有一个,但一般也只有一个
麦克风Microphone
获取设备麦克风Microphone.devices
开始录制Microphone.Start(null, false, 10, 30000)
:返回一个AudioClip
对象,第一个参数是设备名,null
即默认,第二个参数表示超出录制长度后是否重新录制,第三个参数是录制时长,第四个参数为采样率
结束录制Microphone.End(null)
:参数为设备名
获取数据(有了录制后返回的AudioClip clip
)
AudioClip clip = Microphone.Start(null, false, 10, 30000);
float[] f = new float[clip.channels * clip.samples];//声道数*剪辑长度=采样率,即上面的30000
clip.GetData(f, 0);//数据保存在f中,第二个参数为偏移,默认为0
其他实践小知识点
场景切换与退出游戏
场景切换SceneManager.LoadScene("场景名")
:要切换的场景必须加载到场景列表中,在File=》Build Settings里设置
还有一个已经过时的方法Application.LoadLevel("场景名")
,可能会在老项目中见到
退出游戏Application.Quie()
:发布后这条语句才会有用
鼠标设置
隐藏鼠标Cursor.visible = false
锁定鼠标Cursor.LockState = CursorLockMode.
:CursorLockMode
是一个枚举,None
不锁,Locked
限制在屏幕中心点,Confined
限制在窗口内(锁住了后esc出来)
设置鼠标图片Cursor.SetCursor(图片,相对图片左上角的偏移,光标模式)
:定义一个public
的Textur2D
成员,界面上拖过去,下面的设置最好设置为Cursor
类型透视,偏移是一个向量,光标模式一般填CursorMode.Auto
随机数与自带委托
随机数Random.Range(x, y)
:获取int
时为[ ),获取float
时为[ ] (这个Random是unity自带的,要用c#那个必须要引入System,并且指明System.Random
)
委托UnityAction
:用法和c#的Action
一样,没有func
一样的有返回值委托
模型
基本概念:骨(骨骼,表现动作)+肉(网格面片,表现轮廓)+皮(贴图,表现颜色)=》后两者是必须的,这样才能有一个静态模型
支持格式:fbx(推荐),dae,3ds,dxf,obj
导好fbx模型最好面朝z轴,注意缩放大小单位(一般是美术去做模型并导出,但导出时需要告诉他们这两点)
笔记到这里就结束了,学完这个还做不了小项目,要赶紧学数据持久化和GUI,快学吧快学吧。。。。
学习资料来源:b站唐老狮