Unity Study
组件
组件生命周期

脚本执行顺序
生命周期函数执行顺序,所有脚本的 Awake =》 所有脚本的 OnEnable =》 所有脚本的 Start。。。

物体打标记
标记

标签
- 方便查找游戏物体
- 可以通过标签判断物体类型

图层
图层最多 32 个,有序号索引
相机可选择拍摄图层,碰撞也可以根据图层选择

向量
单位化、归一化
把向量转化为单位向量
运算
加法
。。。
减法
x1-x2, y1-y2
点乘
可计算夹角
- x1x2 + y1y2 = cos& _ |a| _ |b|
模不影响角度,可以用单位向量计算
- x1x2 + y1y2 = cos& _ |a| _ |b| = n = cos& * 1
预制体
拖拽生产预制体,预制体变体
Vector3
计算夹角
Vector3.Angle(v, v2);
两点间距离
Vector3.Distance(v, v2);
点乘
Vector3.Dot(v, v2);
叉乘
Vector3.Cross(v, v2);
插值,比例计算
Vector3.Lerp(Vector3.zero, Vector3.one, 0.5f);
- 在两个向量之间进行比例计算,0 向量和 1 向量的 0.5(0.5, 0.5, 0.5);
向量属性
模
- v.magnitude
规范化向量
- v.normalized
旋转
欧拉角(0-360)
- Vector3 rotate = new Vector3(0, 30, 0);
四元数转欧拉角
- rotate = quaternion.eulerAngles;
四元数
四维空间的高阶复数,效率更高,而且不会造成万向节死锁
- Quaternion quaternion = new Quaternion(x, y, z, w);
无旋转的四元数
- Quaternion quaternion = Quaternion.identity;
欧拉角转换为四元数
- Quaternion quaternion = Quaternion.Euler(rotate);
看向一个物体
- Quaternion quaternion = Quaternion.LookRotation(new Vector3(0,0,0));
Debug
log
- Debug.Log
- Debug.LogWarning
- Debug.LogError
绘制直线
绘制直线 只有开发人员能看到
- Debug.DrawLine(Vector3.zero, Vector3.one, Color.blue);
绘制射线
- Debug.DrawRay(Vector3.zero, Vector3.up, Color.red);
游戏物体类
当前脚本所挂在的游戏物体
- this.gameObject / gameObject
常用属性
名称
- name
标签,如 player
- tag
图层,会拿到索引
- layer
激活状态
- gameObject.SetActive(false);
- activeInHierarchy (当前真正的激活状态,会被祖先元素影响)
- activeSelf (当前自己的激活状态,不一定够是实际的)
获取 Transform 组件
- this.transform / transform
获取其他组件
- BoxCollider bc = GetComponent< BoxCollider>();
获取当前物体子物体身上的某个组件
- GetComponentInChildren< >();
获取父物体身上的组件
- GetComponentInParent< >();
添加组件
- gameObject.AddComponent< AudioSource>();
通过游戏物体名称获取游戏物体
- GameObject test = GameObject.Find("Test");
- GameObject[] test = GameObject.FindObjects("Test");
通过游戏标签获取
- GameObject test = GameObject.FindWithTag("Player");
- GameObject[] test = GameObject.FindObjectsWithTag("Player");
通过预设体实例化游戏物体
- GameObject go = Instantiate(Prefab);
- Instantiate(Prefab, transform); // 实例化并设为子物体
销毁
- Destroy(go);
游戏时间 Time
游戏开始到现在的时间
- Time.time
时间缩放,默认一倍,可用与加速减速
- Time.timeScale
固定时间间隔
- Time.fixedDeltaTime
上一帧到这一帧所用的游戏时间
- Time.deltaTime
文件路径 application
游戏文件路径(Assets 文件),只读,打包后加密压缩
- Application.dataPath
持久化游戏路径,可写,可用于存储数据
- Application.persistentDataPath
StreamingAssets 只读,打包后不压缩,需要自己手动创建
- Application.streamingAssetsPath
临时文件
- Application.temporaryCachePath
控制是否在后台运行 (生成设置-玩家设置 中也有)
- Application.runInBackground
打开 url 到浏览器
- Application.OpenURL("");
退出游戏
- Application.Quit();
场景

场景类
SceneManager.LoadScene(1)通过索引或名称同步加载场景并跳转,需要引入命名空间
using UnityEngine.SceneManagement;
void Start()
{
SceneManager.LoadScene(1);
}获取当前场景
- Scene scene = SceneManager.GetActiveScene();
名称
- scene.name
是否加载完成
- scene.isLoaded
场景所在路径
- scene.path
场景索引
- scene.buildIndex
获取场景的所有游戏物体
- GameObject[] gos = scene.GetRootGameObjects();
场景管理类
using UnityEngine.SceneManagement;
已经加载的场景数量
- SceneManager.sceneCount
创建新场景
- Scene newScene = SceneManager.CreateScene("newScene");
卸载场景, 异步
- SceneManager.UnloadSceneAsync(newScene);
加载场景
- SceneManager.LoadScene("MyScene", LoadSceneModal.Single); 加载后替换
- SceneManager.LoadScene("MyScene", LoadSceneModal.Additive); 以叠加的方式加载场景
异步加载场景并获取进度
- SceneManager.Load("MyScene", LoadSceneModal.Additive); 以叠加的方式加载场景
以协程方法来异步加载场景
AsyncOperation operation;
IEnumerator LoadScene(){
operation = SceneManager.LoadSceneAsync(1);
yield return operation;
}获取进度,进度最大为 0.9
- operation.progress
加载完场景后不自动跳转
- operation.allowSceneActivation = false;
Transform
相对于世界、相对于父物体
- position/localPosition
- rotation/localRotation
- eulerAngles/localEulerAngles
- localScale
向量(轴方向)
- forward
- right
- up
操作
看向
- LookAt(Vector3)
旋转
- transform.Rotate(Vector3.up, 1);
绕某个物体旋转, 绕(0,0,0)点的 up 轴,以速度 5 旋转
- transform.RotateAround(Vector3.zero, Vector3.up, 5);
移动
- transform.Translate(Vector3.forward * 0.1f);
父子关系
获取父物体
- transform.parent.gameObject;
子物体个数
- transform.childCount;
解除父子关系
- transform.DetachChildren();
获取子物体
- Transform trans = transform.Find("child");
- trans = transform.GetChild(0);
判断是否为子物体
- bool res = trans.isChildOf(transform);
设置为父物体
- trans.SetParent(transform);
键盘鼠标操作
鼠标
鼠标点击
按下鼠标 0 左键 1 右键 2 滚轮
- if (Input.GetMouseButtonDown(0))
持续按下鼠标
- if (Input.GetMouseDown(0))
抬起鼠标
- if (Input.GetMouseButtonUp(0))
键盘
按下键盘按键
- if (Input.GetKeyDown(KeyCode.A))
- if (Input.GetKeyDown("a"))
持续按下键盘
- if (Input.GetKey(KeyCode.A))
键盘抬起
- if (Input.GetKeyUp(KeyCode.A))
虚拟轴、虚拟按键
虚拟轴介绍
虚拟轴设置

使用
获取水平轴
- float horizontal = Input.GetAxis("Horizontal");
获取竖直轴
- float vertical = Input.GetAxis("Vertical");
虚拟按键,相当于允许游戏自定义按键,如跨平台
- if (Input.GetButtonDown("Jump"))
触摸操作
开启多点触摸
- Input.multiTouchEnabled = true;
判断单点触摸
if (Input.touchCount == 1)
触摸对象
- Touch touch = Input.touches[0];
触摸位置
- touch.position
触摸阶段
switch(touch.phase){
case TouchPhase.Began:
break;
case TouchPhase.Moved:
break;
// 静止
case TouchPhase.Stationary:
break;
// 结束
case TouchPhase.Ended:
break;
// 因为其他事件打断被取消了
case TouchPhase.Canceled:
break;
}多点触摸
if (Input.touchCount == 2)
Touch touch2 = Input.touches[1];
角色控制
为物体添加 CharacterController 组件,再创建一个控制组件
private CharacterController player;
// Start is called before the first frame update
void Start()
{
player = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical);
//Debug.DrawLine(Vector3.zero, dir, Color.blue);
player.SimpleMove(dir * 10);
}物理系统
重力
碰撞检测 collider
监听发生碰撞
- private void OnCollisionEnter(Collision collision)
持续发生碰撞
- private void OnCollisionStay(Collision collision)
结束碰撞
- private void OnCollisionExit(Collision collision)
Collision collision -碰撞到的物体信息
- collision.gameObject.name
触发
监听发生碰撞
- private void OnTriggerEnter(Collider other)
持续发生碰撞
- private void OnTriggerStay(Collider other)
结束碰撞
- private void OnTriggerExit(Collider other)
铰链 弹簧
Higne Joint
Spring Joint
Fixed Joint
物理材质
创建物理材质,添加到 Collider 上
射线检测
创建射线
- Ray ray = new Ray(Vector3.zero, Vector3.up);
从摄像机获取射线
- Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
声明一个碰撞信息类
- RaycastHit hit;
碰撞检测
- bool res = Physics.Raycast(ray, out hit);
- if res == true
碰撞到的位置
- Debug.Log(hit.Point)
多检测
- RaycastHit[] hits = Physics.RaycastAll(ray, 100);
- RaycastHit[] hits = Physics.RaycastAll(ray, 100, 1 < < 10);
粒子系统
创建粒子系统,使用贴图,调整参数
画线、拖尾
Line Renderer
线的位置不在 transform 里,在 LineRenderer 里
设置线段位置
LineRenderer lineRenderer = GetComponent<LineRenderer>();
lineRenderer.position = 3;
lineRenderer.SetPosition(0, Vector3.zero);
lineRenderer.SetPositions(...);还可以修改:颜色、宽度
Trail Renderer
拖尾效果

Animation(46)
老版 Animation
GetComponent< Animation>.play("name");
新版 Animator
创建动画器控制器,并拖拽到 Animator 组件里
触发
触发触发器,如果想立刻触发,有退出时间取消勾选
- GetComponent< Animator>().SetTrigger("pickup");
角色移动动画控制
private Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(horizontal, 0, vertical);
if (dir != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(dir);
animator.SetBool("isWalk", true);
transform.Translate(Vector3.forward * Time.deltaTime);
} else
{
animator.SetBool("isWalk",false);
}
}动画 检查器
Rig - 动画类型
Animation - 剪辑
- 循环时间
- 循环匹配
- 旋转/位置烘培(是否不转/移动)
Animation - 曲线
随动画进度获取一个曲线的值,可用于根据动画进度设置火焰大小等
Animation - 事件
在关键帧设置事件,在组件中实现事件函数,可达成如左右脚落地触发音效等
混合动画 动画混合树
可实现动画的混合,如按比例混合 walk 和 run

动画图层
在一个图层里
- Any State
- Entry
- 子状态机
- 上一层状态机
- Exit
多图层
- 权重 0-1
- 遮罩
- 创建一个 Avatar 遮罩,将操控的设为绿色,将遮罩拖如动画器图层的遮罩
反向动力学
动画器中对应层的 IK 要勾上
private void OnAnimatorIk(int layerIndex) {
// 设置头部IK
animator.SetLookAtWeight(1);
animator.SetLookAtPosition(target.position);
// 设置右手IK权重
animator.SetIkPositionWeight(AvatarIkGoal.LeftHand, 1);
// 旋转
animator.SetIkRotationWeight(AvatarIkGoal.LeftHand, 1);
// 设置右手IK
animator.SetIKPosition(AvatarIKGoal.LeftHand, target.position);
animator.SetIKRotation(AvatarIKGoal.LeftHand, target.rotation);
}导航组件 寻路
生成导航地形网格
地形设为静态导航
窗口-AI-导航
- 烘培
为 player 导航
为 player 添加导航代理组件(Nav Mesh Agent)
using UnityEngine.AI;
private NavMeshAgent agent;
agent = GetComponent<NavMeshAgent>();
// 鼠标点击获取位置并寻路
if (Input.GetMouseButtonDown(0)){
Ray ray = Camera.main.ScreenPointToRay(Input.mouseposition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit){
Vector3 point = hit.point;
// 设置该点为导航目标点
agent.SetDestination(point);
}
}网格链接与动态障碍物
导航网格障碍物组件(Nav Mesh Obstacle),可动态切割导航网格
导航-烘培-生成分离网格链接,导航-对象 里要勾上
链接两个点,可以来回传送
随便选中两个点中的一个,添加Off Mesh Link组件, 添加起始和结束物体
区域遮罩
Nav Mesh Agent 区域遮罩部分,该 player 不能访问
区域类型、区域花费
UI
必须要先创建 canvas 画布,所有的 ui 内容都是绘制在 canvas 画布上的,所有的 ui 都需要是 canvas 的子物体
渲染模式
- 屏幕空间 - 覆盖 : 永远在场景上面
- 屏幕空间 - 摄像机 : 永远在摄像机里
- 世界空间
事件系统 EventSystem
图片
锚点
面板
遮罩
文本
适配 content size fitter
按钮
布局
Vertical Layout Group
Horizontal Layout Group
Grid Layout Group