kizumi_header_banner_img

Hello! Beautiful Kizumi!

加载中

文章导读

Unity基础


avatar
Yuyas 2025年12月19日 6

Mathf

 //插值运算 - Lerp

//Lerp函数公式
//result = Mathf.Lerp(start, end, t);

//t为插值系数,取值范围为 0~1
//result = start + (end - start)*t

//插值运算用法一
//每帧改变start的值——变化速度先快后慢,位置无限接近,但是不会得到end位置
start = Mathf.Lerp(start, 10, Time.deltaTime);

//插值运算用法二
//每帧改变t的值——变化速度匀速,位置每帧接近,当t>=1时,得到结果
time += Time.deltaTime;
result = Mathf.Lerp(start, 10, time);

向量

成员属性: magnitude 模长

normalized 单位向量

向量的点乘可以用来判断物体的方位

点乘函数Vector3.Dot()

两物体之间夹角为 Mathf.Acos(Vector3.Dot(A.transform.forward.normalized,(B.transform.position – A.transform.position).normalized))

或者 Vector3.Angle(A.transform.forward, B.transform.position – A.transform.position)

叉乘使用的是左手定则,与常见的判断方式相反

向量的叉乘用于得到平面的法向量,以此判断物体的方位

叉乘函数Vector3.Cross()

如果Cross(A.transform.forward, B.transform.position – A.transform.position).y > 0,则B在A右边,反之在左边

向量插值

线性插值Vector3.Lerp(stPos,endPos,Time.deltime)

球形插值Vector3.Slerp(),区别在于这是一个球形的轨迹

四元数Quaternion

为什么要四元数

欧拉角存在缺点:

1.旋转角度不唯一

2.存在万向节死锁

知识点一 四元数 Quaternion
//四元数Q = [cos(β/2), sin(β/2)x, sin(β/2)y, sin(β/2)z]
//计算原理
//Quaternion q = new Quaternion(Mathf.Sin(30 * Mathf.Deg2Rad), 0, 0, Mathf.Cos(30 * Mathf.Deg2Rad));
//提供的轴角对 初始化 四元数的方法
Quaternion q = Quaternion.AngleAxis(60, Vector3.right);
// 返回沿某轴旋转一定度数之后的单位向量

//创建一个立方体
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
obj.transform.rotation = q;

知识点二 四元数和欧拉角转换
//1.欧拉角转四元数
Quaternion q2 = Quaternion.Euler(60, 0, 0);
GameObject obj2 = GameObject.CreatePrimitive(PrimitiveType.Cube);
obj2.transform.rotation = q2;
//2.四元数转欧拉角
print(q2.eulerAngles);

知识点三 四元数弥补的欧拉角缺点
//1.同一旋转的表示不唯一 四元数旋转后 转换后的欧拉角 始终是 -180~180度

//2.万向节死锁 通过四元数旋转对象可以避免万向节死锁

必备知识点 四元数相乘代表旋转四元数 this.transform.rotation *= Quaternion.AngleAxis(1, Vector3.up);

四元数也可以乘以向量,返回值为向量,相当于对向量的旋转

协同程序

多线程

Thread t = new Thread(Func);

t.start();

关闭线程

t.Abort();

t = null;

协程和多线程的区别

新开一个线程是独立的一个管道,和主线程并行执行 新开一个协程是在原线程之上开启,进行逻辑分时分步执行

1.Unity支持多线程,只不过新开的线程中无法访问Unity相关的内容

一般主要用于复杂的逻辑计算或者网络消息的接受等

Tip:Unity中的多线程一定要记住关闭

2.协同程序不是多线程,是将线程中的逻辑分时执行,避免卡顿

3.继承MonoBehavior的类都可以使用协程

4.协程开启

IEnumerator ie = MyCoroutine(1, “123”); Coroutine c1 = StartCoroutine(ie); // 用变量接收协程,方便指定关闭

IEnumerator MyCoroutine(int i,string s) { print(i); // yield break; 使用此语句 后面的操作不会执行 yield return new WaitForSeconds(1.0f); print(s); }

yield return 不同内容的含义

1.下一帧执行 yield return 数字; yield return null; 在Update和LateUpdate之间执行

2.等待指定秒后执行 yield return new WaitForSeconds(秒); 在Update和LateUpdate之间执行

3.等待下一个固定物理帧更新时执行 yield return new WaitForFixedUpdate(); 在FixedUpdate和碰撞检测相关函数之后执行

4.等待摄像机和GUI渲染完成后执行 yield return new WaitForEndOfFrame(); 在LateUpdate之后的渲染相关处理完毕后之后,主要用来截图使用

5.一些特殊类型的对象 比如异步加载相关函数返回的对象 之后讲解 异步加载资源 异步加载场景 网络加载时再讲解 一般在Update和LateUpdate之间执行

6.跳出协程 yield break;

协程关闭

StopAllCoroutines(); StopCoroutine(c1);

协程开启后 组件和物体销毁,协程不执行 物体失活协程不执行,组件失活协程执行

Resources资源动态加载

同步加载

Resources文件夹可以有多个,可以不在Assets文件夹下

用法 :Resources.Load(“object_name”),返回对象为Object,如果使用LoadAll则为Object数组

常用方法为泛型 :Resources.Load<T>(“object_name”),此时返回的对象为T,不需要手动转换

Unity提供得Text类为TextAsset

文件夹中允许存在不同类型的同名文件,在Load的时候传入第二参数Type确定具体文件

异步加载

Resources.LoadAsync<T>(“object_name”)

返回的值为ResourceRequest

rq.completed为参数AsyncOperation的一个事件,需要往该事件里添加操作,表示异步加载完成后要执行的操作,可以把AsyncOperation强转为ResourceRequest再调用asset表示希望得到的对象

T obj = (a as ResourceRequest).asset as T

。当然也可以不在这个事件里得到asset,在外部直接调用,前提是需要判空,因为是异步加载

if(rq != null)
T obj = rq.asset as T

手动卸载缓冲区资源

Resoureces.UnloadAsset(obj) // 卸载指定资源

Resources.UnloadUnusedAssets() // 卸载未使用的资源

通常搭配GC垃圾回收一起使用,GC.Collect()

场景异步加载

SceneManager.LoadSceneAsync(name); // 返回值为AsyncOperation,可以往该事件里加入函数

还可以通过协程配合异步加载场景,这样不仅可以添加结束后的操作,还可以添加加载时的操作,需要注意的时,在删除原本场景的gameObject时不能删除挂载此脚本的物体,这样无法执行结束后的操作,可以通过

DontDestroyOnLoad(this.gameObject)来防止该物体在切换场景时被销毁

LineRendered

常用API:

startWidth,endWidth

pointCount

SetPosition(index,pos) // 必须先设置pointCount才能设置这个

范围检测

Physics.OverlapBox()

Physics.OverlapCapsule()

Physics.OverlapSphere()

返回值都为collider[]

射线检测

创建射线对象:

Ray r = new Ray(position,direction)

Ray r = Camera.main.ScreenPointToRay(Input.mousePosition) // 从摄像机发出射线

执行射线检测:

只检测是否碰撞

Physicals.Raycast(r,maxDis,layer,QueryTriggerInteraction) // QueryTriggerInteraction省略默认为UseGlobal 返回值为bool

得到碰撞物体信息

RaycastHit hitInfo

Physicals.Raycast(r,out hitInfo,maxDis,layer,QueryTriggerInteraction) // 碰撞物体信息存储在hitInfo 返回值依旧是bool 为上面一个方法的重载

hitInfo.point // 碰撞到的点

hitInfo.normal // 碰撞到的法线

hitInfo.distance // 碰撞到的对象与自己的距离

需要得到碰撞多个物体的信息时

RaycastHit[] hits = Physicals.Raycast(r,maxDis,layer,QueryTriggerInteraction)

屏幕坐标相关

为Camera的内置方法

ScreenPoint坐标单位为分辨率

Viewport坐标单位归一化为[0,1]



评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字
插入代码

个人信息

avatar

24
文章
1
评论
1
用户

近期文章