1.在Unity中,自己写的类(脚本)的名字不能与Unity已有的类的名字相同,如果相同的话就会导致一个错误 --- 当我们在脚本中想调用Unity自带的类的时候,我们只能够调用到自己写的那个与其重名的类(就近原则调用)
比如Unity自带的Component类,你写个脚本(类),将其命名为Componet,如果你想在脚本中调用Unity自带的Component类中的方法或者属性的话,此时它不会找到Unity自带的那个,而是根据就近原则,找到和Component同名的那个脚本
2.Time类的描述
注意通过Time类获取到的时间信息都是与游戏相关的时间
Time类中只有静态变量 -- 能够直接通过 类名+ 点操作符 + 变量名来进行访问的变量
C#输出文本是用 console . writeline()等方法 ,而在Unity的控制台中输出文本则是用debug.log()方法
在脚本中创建一个公开变量的话,这个公开变量会在脚本挂载到游戏物体上(实例化)时,进行可视化显示,具体的就是出现这样一个变量小框
1.deltaTime可以理解为渲染一帧画面所需的时间
每渲染一帧,update方法就执行一次
这上面使用了一个很有意思的策略来平衡了帧数多转的快,帧数少转的慢之间的矛盾
首先在规定时间里,帧数多则表示渲染每一帧所需的时间少,则deltaTime小
而在规定时间里,帧数少则表示渲染每一帧所需的时间多,则deltaTime大
如果只是在一帧被渲染后,执行旋转一度的方法话,就会导致帧数多的转的多,帧数少的转的少
如果想让二者转动的幅度相接近的话,我们可以将帧数多的每帧转动幅度调低,证书少的每帧转动幅度调高,以此实现趋近平衡
那么如何调整转动幅度,答案就是将幅度改为 --- 基准转动幅度 * deltaTime ,这样子的话实际转动幅度就会随着帧时间的改变而改变 ---- 渲染快,帧数多,帧时间小则转的比原来少;渲染慢,帧数少,帧时间大则转的比原来多,二者趋近平衡。
总结 --- 在updata方法中如果想要使得物体移动的速度,旋转的角度不受渲染快慢的影响,则需要将基准速度 * Time.deltaTime属性 , 来达到快的走少点,慢的走多点,使得速度区趋于恒定
1.想让物体的速度(包括旋转和移动)恒定不受渲染快慢的影响的话,我们还可以在Fixupdate方法中实现物体的移动 --- 该方法只有在经过了固定时间才会执行一次,比如每0.02s执行一次。
2.由于是固定时间执行,所以速度是恒定的
接下来讲讲如何通过Time类实现游戏的暂停
这需要我们用到一个Time类中的静态变量 --- timeScale
这个变量的默认值是 1 ,即游戏中的时间和现实中的时间是 1 :1 同步的
当该变量的值小于1的时候,越小,游戏中的时间相对于现实越慢;当该变量的值大于1的时候,越大,游戏中的时间相对于现实中的时间越快。(PS:当值为0的时候,则代表游戏中的时间停止了)
一个需要注意的点 --- 涉及到 update 和 fixUpdate 这两个方法
首先我们要知道,TimeScale等于0时只是游戏中的时间相对于现实中的时间静止了,这个静止不会影响画面的渲染,渲染只和机器的性能和渲染算法有关,与游戏内时间无关 ---而 Update方法则是在渲染一帧后执行一次 --- 也就是说 update方法的执行与TimeScale所代表的游戏时间无关,哪怕TimeScale = 0 ,只要画面还在正常的渲染,Update方法就会正常的执行
FixUpdate方法的特点是经过固定时间后执行一次,而这个时间的参照则是游戏时间(即受TimeScale影响的时间),一般默认游戏时间经过0.02s,FixUpdate方法执行一次,如果TimeScale = 0 , 游戏内时间暂停,则FixUpdate方法也会停止执行
关于Update方法中实现物体移动和转向的一个注意事项:
首先我们知道Update方法是与游戏时间无关的,它只会在渲染完一帧之后执行一次,而在Update方法中实现物体的移动和旋转有两种方式 --- 一种是只有基础速率(转动的快慢与渲染速度的快慢正相关);一种是 基础速率 * 帧时间(deltaTime)
而问题就出在这个帧时间上。帧时间(deltaTime)的参照是游戏时间,当游戏时间暂停,即时间不再流动时 帧时间 = 0 ,则此时物体转动的幅度/移动的距离也会等于0,物体也会跟着一起停止运动
而使用第一种方法则不会,因为没有deltaTime的影响
如果我们既想让游戏物体在游戏时间暂停时也能保持运动的话,我们必须满足以下两个条件:
必须在Update方法中实现物体的移动 / 旋转, 使得物体的移动 / 旋转与画面的渲染挂钩,与游戏时间脱钩
将原本用来使速度不受渲染快慢影响,趋于常数的乘积 --- deltaTime 更换为 unscaledDeltaTime,新更换的这个时间是一个不受游戏时间影响的,独立流动的时间
(ps: unscaled 的意思是不受缩放影响的,上面代指的是时间缩放)
这里的time 和 unscaledTime同理,time是受时间缩放影响的游戏内时间,而unscaledTime则是不受时间缩放影响,正常流动的游戏内时间
每一个组件,脚本都继承了Component类,而component类中有一个方法 --- Getcomponent<>(),这个方法的作用是找到当前组件/脚本挂载的游戏对象(所处的对象集群)中的,与尖括号中的类型相同的组件/脚本(对象)
(PS:这个方法千万不要在update,fixupdate等频繁调用的方法中使用,因为执行该方法需要的时间长,且该方法不需要重复执行,所以只执行一次就可以了)
一般找组件这个操作都是放在 start 或者 awake 方法(生命周期中只执行一次的方法)中的,具体用那个取决于你的需求
不要忘了拼接字符串的 string 和 Format方法(数据按顺序填充入字符串中)
如果加了 :d2 则表示在填充数据之前先将数据转换为某种格式再填充 --- 此处就是先转换为两位数格式(缺少的位数就用0来补上) --- 注意!这个格式转换标识符必须写在花括号里面,不然的话会被识别为字符
1.指定间隔也可以理解为渲染了多帧之后才执行一次
第一种方法:创建时间标定: --- 使用Time.time来实现
已知我每过一秒想要执行某个语句,此时我们可以创建一个时间标定
第一次触发是在Time.time = 1时,第二次是等于2时,第三次是等于3时...
也就是说每触发一次语句,时间标定都会加1秒,而最开始是在标定为1s的时候开始执行的,每执行一次,标定 + 1,直到再次达到标定时再执行一次...依次类推
第二种方法 --- 使用Time.deltaTime 累加来进行判断
首先创建一个记录累加量的成员变量,每执行一帧就让这个累加量 + 一个deltaTime,当该累加量>=1时就说明已经过了一秒了,此时执行语句并讲累加量清0,然后继续累加直到再一次达到1s / 给定执行时间
第三种方法是在 Start生命周期中通过调用 --- InvokeRepeating()方法(翻译过来就是重复调用)来实现
第一个是你要重复调用的方法的方法名,第二个是该方法第一次调用的时间,第三个是每次重复执行之间的时间间隔
这个方法的逻辑就是 --- 达到停止条件后就调用CancelInvoke()方法取消重复调用
该方法如果不填参数的话就是取消所有的方法的调用,如果填参数的话 --- 该参数是要取消调用的方法的方法名 --- 那就是取消特定的方法的调用
像倒计时这种简单的,重复做的 --- 推荐使用 Invoke 方法 -- 简单高效
问题:发射子弹应该用哪一种方法来执行?
答案是第一种方法:
首先,我们必须满足按下鼠标后子弹就会发射,所以我们必须保证鼠标一按方法立刻执行,这样的话第三(按鼠标前就执行了)和第二种(需要积累时间)方法就被排除了,只能用第一种方法来实现
1.首先second那一段代码和它下面那段代码都是实现发射子弹不需要的
2.将nextTime设定为0,只要一按鼠标就必然会执行下面的子弹发射方法,执行后再将next修改为Time.time + 时间间隔,来实现子弹的间断发射
3.第二个方法则常常用到需要先等待(积累时间)然后再做的需求
补充最后一个小知识点 --- 预制件
当有一个游戏对象会在多个场景中被使用的时候,我们就可以创建一个该游戏对象的预制件
制作方法是:将在层级(Hirarchy)面板创建的游戏物体拖到Project面板后,就会自动生成该游戏物体的预制件
1.如果将预制件拖到Hirarchy面板的话,就会生成一个和预制件参数一致的游戏物体,并且该游戏物体的参数是和对应的预制件同步变化的。
2.单独修改游戏物体的参数是不会影响到预制件的参数的(除非你点了Apply),但是修改预制件的参数会使得对应的游戏物体一起跟着变(单独修改的游戏物体中已经修改的参数是不会跟着变的)。
3.如果单独修改完游戏物体的参数后想要将其应用到其它同一个预制体中出来的游戏物体的话
选中调好参数的游戏物体,来到inspector参数面板的Prefab这一行,点击apply即可
(注意此时预制体的参数会和修改好的游戏物体的参数同步)
4.单独修改一个预制件中出来的游戏物体的某些参数,然后再去修改预制件中的对应参数的话,游戏物体中的这些已经修改的参数是不会随着预制件一起变化的,并且这些参数的名称都会被加粗
1.在层级面板中如果看到了用浅蓝色的字体来命名的游戏物体的话,就说明这个游戏物体是预制件的实例
Folder --- 文件夹
2.一般所有的预制件都会统一放在一个名为Prefabs(预制件)的文件夹中