Unity - 编程进阶
Some Keys for Programming / 关键点
The Current Progress / 当前进度
- Unity初级编程 - 中级编程 / ing
- 动画系统demo实践 完成模型导入-> 动画绑定 -> 状态机组织动画
- 工具 fbx -> motiondate -> 中间数据
- ue4状态机 + AI + 行为树
- 着手AIAnimation框架,着手动画系统的改写
ForeachLoop / 循环
1 | using UnityEngine; |
Awake and Start / 初始化方法
执行前提 : 必须将含该方法的脚本作为组件附加至游戏对象上,否则不会执行
Awake : 在加载场景时执行且仅执行一次,若该脚本组件已附加但是未被激活,仍将执行
Start : 在第一帧更新之前执行且仅执行一次,已附加的组件必须为激活态才会执行
FixUpdate and Update / 更新方法
- FixUpdate : 以固定时间间隔调用,每调用一次均完成一次物理计算,因此物理运动需要在此更新
- Update : 下一帧执行前调用,但各帧的时间间隔不一,因此时间间隔不固定,一些简单非物理运动等可以在此更新
1 | using System.Collections; |
Enabling and Disabling Components / 启用禁用组件
ComponentName.enabled
属性来启用或禁用组件
1 | using System.Collections; |
Activating GameObjects / 激活游戏对象
- activeInHierarchy - 继承关系下孩子活跃状态的判断,当父对象设置为不活跃时,子对象仍活跃但是于Hierarchy为不活跃,即不会在场景中显示
- activeSelf - 判断游戏对象的活跃状态
- SetActive - 设置游戏对象的活跃状态
Translate and Rotate func / 变换与旋转方法
transform 为 Transform 类的一个实例,可直接使用该实例下的变换方法 (不好意思,暂不深究,先笼统解释下=-=)
1 | using System.Collections; |
Camera LookAt / 朝向
transform 实例下提供 LookAt 方法设置所附加对象的朝向,但是仅仅是朝向,不会跟随移动
1 | using System.Collections; |
2022/1/5 21:50
Linear Interpolation / 线性插值
U3D Document : Linearly interpolating is finding a value that is some percentage between two given values.
线性插值可以找到两个值之间的某个过渡值,该值在两者之间且满足一定的百分比
U3D Document : The third parameter in each case is still a float representing how much to interpolate.
第三个 Percentage 用于表示该如何插入
注意:
- lerp 函数仅仅是得到两值之间的某插值,注意是得到,若需要使用还需要将该函数返回值作为相应值类型变量进行处理,例如实现光照颜色随时间的平滑过渡,需要使用lerp得到过渡值并将该值赋值给光照颜色属性
Mathf.Lerp (float From, float To, float Percentage);
可用于两值之间的线性插值
U3D Document : Under some circumstances Lerp functions can be used to smooth a value over time.
该func有时还可以用于使某值/属性随时间平滑变化,即将From设置为该值/属性,To设置为期望不断逼近的某值,Percentage设置插入方式,若不想随帧率插入,可将该 Percentage*Time.deltaTime,使其随时间以s为单位平滑变化
Vector3.Lerp (Vector3 From, Vector3 To, float Percentage);
可用于两向量之间的线性插值
Color.Lerp (Color From, Color To, float Percentage);
可用于两颜色之间的线性插值
**Questions: **
- Render 与 Renderer ?
- GetKeyDown 与 GetKey ?
Destroy / 销毁
U3D Document : The Destory function can be used to remove game objects or components from game objects at run time.
sDestroy 函数可以用于 运行时销毁 场景中的游戏对象或者游戏对象上的某组件,其第二个参数可以设置相应的延时
注意:
- 销毁游戏对象的同时,其组件也将销毁
- 脚本可通过 gameObject 直接获取其所附加的游戏对象的引用
1 |
|
GetButton 和 GetKey / 获取输入
Unity 的输入不预先设置轴映射和操作映射来区别按下与持续按下,而是通过三个函数判断输入状态,返回 true or false
Button 与 Key 的区别在于其使用方式,都可获取输入状态,但是 key 要求参数使用指定按键 KeyCode,而 button 可以通过 InputManager 自定义输入,参数使用 ButtonName 即可
GetKeyDown / GetButtonDown
按下的那帧为true,其余为false
GetKey / GetButton
持续按下的所有帧均为true,包括按下那一帧
GetKeyUp /GetButtonUp
松开按键的那一帧为true,其余为false
GetAxis / 获取轴
类似于 GetButton/GetKey,但是其返回值不是 bool 类型而是介于[-1,1]之间的 float 类型,正向驱动轴的按钮按下将使轴趋向于1
即按下该轴绑定的按钮,该轴便会有值,并且能双向驱动,当松开时,该轴的值将恢复0
- Gravity : 松开按钮时轴值恢复0的速度
- Sensitivity : 按下轴时轴趋向 -1 or 1 的速度
- Dead : 使用操作杆时设置,忽视某些细微操作导致的误触,可设置可忽略的范围
- Snap : 若勾选,则按下对应反方向的按钮时,轴将重置为0,若未勾选,按下反方向的按钮时轴值从当前值开始变化
1 | using System.Collections; |
OnMouseDown / 鼠标点击
OnMouseDown 函数用于处理于 GUI控件 或者碰撞体上的点击
1 | using System.Collections; |
GetComponent / 获取组件
可通过 GetComponent<Type> 函数获取某游戏对象上的组件并设置其属性
注意:
- 若组件与获取组件的脚本附加于同一个游戏对象上,则可以直接 GetComponent<Type>
- 若需要获取的组件附加于其他游戏对象上,则需要先获取对应游戏对象,再通过该游戏对象调用 GetComponent<Type> 方法
- GetComponent<Type> 方法很消耗性能,因此一般仅在初始化时调用一次获取组件,而不逐帧调用
1 | using UnityEngine; |
DeltaTime / 时间增量
U3D Document : The interval in seconds from the last frame to the current one (Read Only).
Time.deltaTime 为当前帧与上一帧的间隔时间,以秒/s为单位,只读不可修改
U3D Document : An important thing to remember when handling time-based actions like this is that the game’s framerate is not constant and neither is the length of time between Update function calls.
以时间为基准的运动,不能逐帧实现,因为游戏帧率不是恒定的,即每一次 update 调用的时间间隔不是恒定的,逐帧实现的运动将导致运动不均匀
U3D Document : The solution is to scale the size of the movement by the frame time which you can read from the Time.deltaTime property.
能够使得运动更均匀顺滑的解决方案是通过 Time.deltaTime 属性值来缩放运动距离大小,随着帧率的变化,Time.deltaTime 也将随之变化,因此对象的移动速度将保持不变
1 | using System.Collections; |
Instantiate / 运行时实例化
以发射器为例,可以完成运行时创建预制件的克隆体
注意:
- 预制件创建的初始位置一般通过 barried 来设置,barried 为一个空游戏对象用于占位子弹发射位置
- 子弹的销毁不在if中完成,而是将销毁脚本附加于预制件上
- 可以使用 Launcher 空游戏对象用于在层级中管理枪支与barried,并将发射脚本置于 Launcher 上
1 | using System.Collections; |
Invoke / 延时调用
Invoke 可以完成某个方法的延时调用来完成对延时有要求的函数调用系统
Invoke(string FuncName,float DelayTime)
可以完成 FuncName 的延时调用,以秒/s为单位,DelayTime秒后调用
InvokeRepeating(string FuncName,float DelayTime,float IntervalTime)
可以完成 FuncName 的延时调用,以秒/s为单位,DelayTime秒后调用,并且每隔IntervalTime秒重复调用
CancelInvoke(string FuncName)
可以关闭对 FuncName 延时重复调用
2022/1/6 15:43
Properties / 属性
通过属性访问器来访问成员而不是通过 public 来访问的优势在于
- 可是使该成员 只读/只写,省去相应访问器即可
- 访问器中可添加一些方法
1 | using UnityEngine; |
Generics / 泛型
where 关键字指定泛型类型约束
Generics Class
public class ClassName<T> {}
Generics Function
public returnType FuncName<T> () {}
Generics Interface
public interface InterfaceName<T> {}
Generic Constraint / 泛型约束
区别于c++,c++仅仅起暗示作用并不会实际约束,而c#会对期望的类型作出约束
public class ClassName<T> where T : ConstraintList {}
public returnType FuncName<T> () where T : ConstraintList {}
public interface InterfaceName<T> where T : ConstraintList {}
ConstraintList / 约束列表 :
- Struct T类型必须为值类型
- new() T类型必须包含无参的公共构造函数,构造函数约束需要出现在约束列表的最后
- class T类型必须为引用类型
- ClassName T类型必须为 ClassName 类型或派生自 ClassName 基类类型
- InterfaceName T类型必须已实现 InterfaceName 接口
Member Hiding / 成员隐藏
在进行上转型时,为了能够调用父类的方法或属性,因此将子类的同名方法或属性前加 new 关键字进行隐藏,正常通过子类引用调用时并无影响,但是在上转型时,将隐藏子类的成员,而调用父类的成员
1 | using System.Collections; |
Questions:
- new 关键字隐藏的意义是什么?没有new在上转型时,不仍然会调用父类的方法吗,为何需要new呢?
- virtual 需要搭配 override ,只有其中一个将表示什么意思
Overriding / 重写
c#中重写需要将父类被重写的方法添加 virtual 关键字声明为虚函数,子类添加 override 关键字指明重写
Interface / 接口
c#接口也有泛型,实现接口时使用 : + 接口 即可
1 | using UnityEngine; |
Extension Methods / 拓展方法
Extension Methods 拓展方法可以不创建某个类的派生类,也不更改某个类,但是为该类”新增”了公用的方法
注意:
- 拓展方法需要有一个静态类作容器
- 拓展方法本身也为静态方法,但是可以像实例方法一样调用
- 拓展方法的参数指定拓展的类型,前需要有关键字this
- 拓展方法仍不可访问拓展类的私有成员
1 | using System.Collections; |
Lists and Dictionaries / 列表与字典
List 为动态数组,以泛型方式创建,并制定元素类型,提供Add,Remove,Sort,Clear等接口
Dictionarie 类似于map,以键值对形式存储元素
注意:
- 需要先引用命名空间 System.Collections.Generic;
1 | // List |
2022/1/6 21:48
Coroutines / 协程
协程本质上是一个用返回类型 IEnumerator 声明的函数,并在主体的某个位置包含 yield return 语句
yield return null; 是暂停执行下一帧恢复的调用点
要将协程设置为 运行/停止 态,需要使用 StartCoroutine() / StopCoroutine() / StopAllCoroutines()
StartCoroutine(string name, object parameter = null)
使用字符串类启动具有特定名称的协程并可以使用相应的 StopCoroutine() 来停止该协程的执行,同时可以指定参数 parameter
StopCoroutine(string name)
StopAllCoroutines()
停止该行为上运行的所有协程
WaitForSeconds(float time)
使用缩放时间来使协程暂停指定秒数
注意:
- 实际暂停时间等于 给定时间 * Time.timeScale
- 其只能与 yield 语句结合使用,暂停时间过后,继续从当前位置执行
1 | using System.Collections; |
Quaternions / 四元数
Quaternions 用来管理旋转,不要轻易改变,但是可以通过unity提供的相应接口完成旋转管理
Quaternion.identity
U3D Document : It Effectively set its Euler rotation to (0,0,0) or no rotation.
设置一个对象的 rotation 属性为 Quaternion.identity,即无旋转,欧拉角值为 (0,0,0)
Quaternion.LookRotation (Vector3 forward, Vector3 upwards = Vector3.up)
U3D Document : Creates a rotation with the specified
forwardand
upwardsdirections.
暂略,有点懵
Quaternion.Slerp (Quaternion a, Quaternion b, float t)
U3D Document : Quaternion A quaternion spherically interpolated between quaternions a and b. The parameter t is clamped to the range [0, 1],If the value of the parameter is close to 0, the output will be close to a, if it is close to 1, the output will be close to b.
非线性插值,可以按比例进行球形插值,t的范围为[0,1],t越接近0,插值越接近a,t越接近1,插值越接近b
Delegates / 委托
委托是存有对某个 方法 引用的引用类型变量
Declaration / 声明
delegate 关键字可以声明可由该委托引用的方法
注意:
- 委托与其可引用的方法具有相同的函数签名
Instantiation / 实例化
委托对象的实例化必须通过 new 创建,并且初始化时给定需要引用的方法名即可
Multicasting of a Delegate / 委托的多播
+ 可用于委托的合并,一个合并委托将调用它所合并的委托
- 可用于合并委托的移除
1 | using System.Collections; |
Attributes / 特性
U3D Document : Attributes allow you to attach additional behavior to the methods and variables you create.
Attributes 允许你赋予创建的变量或者方法特别的行为
注意:
- 特性书写形式为 [],若带参数则可以使用()指出
Range
[Range(min,max)] 可以在 inspectors 面板中显示可调整的滚动条来设置变量的大小0
ExecuteInEditMode
[ExecuteInEditMode] 可以使脚本在非运行模式下被执行
注意:
- 执行结果将是不可逆转的永久性的,需要注意该特性的执行后果
Events / 事件
事件使用 Publisher / Subscriber 发布者/订阅者 机制,使得订阅了发布者的订阅者在发布者发生变动时,作出响应的事件处理
delegate 关键字完成委托的创建,event 关键字完成事件的创建
Publisher / 发布者
创建事件处理任务的委托,并创建事件
设置相应的事件通知函数,完成对事件的调用,进而完成通知
作出改动时完成事件通知函数的调用
注意:
- 事件一般设置为共有的静态成员
Subscriber / 订阅者
设置与委托相对应的事件处理函数
设置相应的接口完成对事件的订阅与取消订阅
1 | using System.Collections; |
Question:
- Quaternions / 四元数 以后细锁
2022/1/7 15:00