个人主页:@元宇宙-秩沅
hallo 欢迎 点赞 收藏⭐ 留言 加关注✅!
本文由 秩沅 原创
收录于专栏 unity 实战系列
⭐相关文章⭐
⭐【软件设计师高频考点暴击】
-本站最全-unity常用API大全(万字详解),不信你不收藏
-关于游戏剧情模式中用到的基础简单API
-控制游戏人物移动的细节到底有多少?
-坦克炮管旋转发射炮弹(向量基础,射线碰撞,物体实例化)
-基于unity物体定点移动与模拟刹车的细节 GIF 图文详解
fps (Frames Per Second) : 即每秒钟帧数
人眼舒适放松可视帧数是每秒24帧
处理1帧游戏逻辑中的计算量过大,或CPU机能不行,不能在—帧的时间内处理完所有游戏逻辑
场景的本质-配置文件-(场景类型文件右键通过记事本可以看到)
☑️辅助特性:
①世界坐标系——transform…
②物体坐标系——transform.Local…
③屏幕坐标系
④视口坐标系——用的较少,主要调整窗口
坐标转换
Reset()://重置函数,
调用情况和时间:
编译器不运行的情况下 和 使用脚本组件Reset功能的时候, 挂脚本的时候
调用次数: 1次
Awake(); //苏醒函数
调用情况和时间:
1.点击运行的时候
2.组件从失灵到激活的时候,但只调用一次
3.Instantiate方法调用的时候
调用次数: 1次
OnEnable(); //组件调用函数
调用情况和时间: 组件从失灵到激活的时候,可多次实现
调用次数:只要组件有失灵到激活的状态就可调用 ,
Strat():
调用情况和时间: 当游戏物体被激活,或者脚本组件被激活时调用 , (点击运行的时候也是会被激活)
调用次数: 1次
FixedUpdate(每帧)
一般用作物理更新
调用情况和时间: FixedUpdate一般适用在相关物理引擎中。它的频 率是0.02秒,是固定的。
调用次数: 大概每秒50次左右、
FixedUpdate & Update & LateUpdate的 区别详解
UpData(每帧) ;
一般用作游戏逻辑更新 update取决于电脑显卡的性能,好的话,快,不行的话就慢,所以相比Fixed Update它具有随机性。
调用情况和时间: 在以上生命周期函数之后,每帧调用一次
调用次数: 大概每秒60次左右
变量赋值生效顺序:
变量声明直接赋值 > 检视面板赋值 > Awake > Enable > 外部赋值 > Start
LateUpate(每帧):
一般用作相机更新 它的执行顺序在update的后面,一般适用于相机的跟随,物体运动在update中,相机跟随在LateUpdate,这样会减少误差,避免出现不必要的瑕疵。
调用情况和时间: 在Update调用之后,并且也是每秒60帧左右(适用于物体移动后的视角跟随)
调用次数: 大概每秒60次左右
OnGUI(每帧)
OnDisable():
调用情况和时间: 和OnEnable差不多,但是Disable是组件从完好到失活的状态, (相当于关闭组件的时候)
调用次数: 组件从激活到失灵的时候调用(二者前提是在游戏运行的时候)
OnApplicationQuit()
调用情况和时间: 当所有游戏物体退出时调用,适用于打包的时候
调用次数: 满足以上情况便调用
OnDestroy();
调用情况和时间: 适用于物体的销毁,删除,以及游戏的停止退出时
调用次数: 满足以上情况便调用
总的执行顺序为:
1.创建物体的三种方式
1.new 构造函数
2.instantiate 实例化方法
3.Gameobject .CreatPrimtive(Primitve Type.cube);使用特别的API创建一些基本的游戏物体类型(原始几何体)
2.游戏物体的获取和查找
if(this.TryGetComponent<>( out 脚本名) )
{
//获取到了就进行处理
}
⭐ 获取
1.this
2.获取游戏物体的标签 gameObject.tag
3.获取游戏物体的名字 gameObject.name
4.获取游戏物体的层级 gameObject.layer
获取对象位置信息
1.子对象的获取
2.父对象的获取
3.Project的资源获取–资源加载
4.根据脚本名获取
获取脚本的方法 如果获取失败 就是没有对应的脚本 会默认返回空
Test t = this.GetComponent(“Test”) as est;
print(t);
根据Type获取
t = this.GetComponent(typeof(Test)) as Test;
print(t);
根据泛型获取 建议使用泛型获取 因为不用二次转换
t = this.GetComponent();
⭐脚本的获取
脚本是否失活
this.enabled = false;
1.得到自己挂载的单个脚本
Test t = this.GetComponent(“Test”) as Test;
2.得到自己挂载的多个脚本
Lesson3[] array = this.GetComponents();
3.得到子对象挂载的脚本(它默认也会找自己身上是否挂载该脚本)
t = this.GetComponentInChildren
4.得到父对象挂载的脚本(它默认也会找自己身上是否挂载该脚本)
t = this.GetComponentInParent
5.尝试获取脚本
提供了一个更加安全的 获取单个脚本的方法 如果得到了 会返回true
⭐查找物体
find的本质——单例模式的升级版 + 服务定位器 (若代码较为复杂的话性能消耗较大)
GameObject[] enemyGos= GameObject.FindGameObjectsWithTag("Enemy");
for (int i = 0; i < enemyGos.Length; i++)
{
Debug.Log("查找到的敌人游戏物体名称是:"+enemyGos[i].name);
}
⭐失灵
⭐销毁
3.继承
常见类的继承关系:
自己创建的类 -> MonoBehavair->Behavir->Conpment->Object
不要爸爸了:this.transform.SetParent(null);
认爸爸 :this.transform.SetParent(GameObject.Find(“爸爸名”).transform);
参数二:是否保留世界坐标的 位置 角度 缩放 信息
this.transform.SetParent(GameObject.Find(“Father3”).transform, false);
true : 保留 世界坐标下的状态 和 父对象 进行计算 得到本地坐标系的信息 false : 不会保留 会直接把世界坐标系下的 位置角度缩放 直接赋值到 本地坐标系下
不要儿子了: this.transform.DetachChildren();
得到儿子数量:this.transform.childCount
得到儿子信息: this.transform.GetChild(0);
亲子鉴定:son.IsChildOf(this.transform)
得到自己是第几个儿子:son.GetSiblingIndex())
把自己变成太子: son.SetAsFirstSibling();
把自己变成最后的一个儿子: son.SetAsLastSibling();
直接设置自己是第几个儿子: son.SetSiblingIndex(1);
1.transform的位置信息
transform.position ----游戏物体trans组件的世界位置信息
transform.Rotation----游戏物体的四元旋转信息
transform.enlerAugle- —游戏物体的欧拉角的信息(也就是Inspactor面板中的Rotation信息)
transform.localposition/localRotion/localenleAugle--------表自身的自身信息
2.游戏物体的自身方向和世界轴方向
针对自身:
==transform.forword ==----向前Z轴方向
transform.up------向上y轴方向
transform.right----向右x轴方向
针对世界:
vector.XX…
针对看向:
transform.LookAt(某个方向)——一直看向某个方向
transform.LookAt(某个物体)——一直看向某个物体
针对缩放
#region 知识点一 缩放
//相对世界坐标系
print(this.transform.lossyScale);
//相对本地坐标系(父对象)
print(this.transform.localScale);
距离运动相关
this.transform.position = this.transform.position + this.transform.up * 1 * Time.deltaTime;
this.transform.position += this.transform.forward * 1 * Time.deltaTime;
this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.World);
this.transform.Translate(this.transform.forward * 1 * Time.deltaTime, Space.World);
this.transform.Translate(Vector3.forward * 1 * Time.deltaTime, Space.Self);
3.用transform组件来进行查找(包含索引查找)
被创造的游戏物体的世界坐标位置是——xx.transform.position
当前transform组件挂载的游戏物体对象的名字是——transform.name
当前transform组件挂载的游戏对象的子对象的数量——transform.childCount
查找当前游戏物体的子对象的trans组件名称为——transform.Find(“zz”)
查找当前游戏物体的第一个子对象——transform.GetChild(0));
查找该游戏物体在父类中子对象的索引位置"——transform.GetSiblingIndex()
1.Vector2结构体的静态变量
1.Vector2.up // 以下的形式pint之后是 (X,y)
2.Vector2.down
3.Vector2.Left
4.Vector2,Riht
5.Vector2.one //单位化之后的值
6.Vetor2.zero // 原点的值
2.Vector2 结构体的成员变量
1.x
2.y
3.XX.normalized //返回 单位化的值
4XX.magnitude //返回该向量的模长
5.XX.sqrMagnitude //返回该向量 模长的平方
‘’‘’‘’‘’‘’‘’
3.索引器的格式和存在的目的
1,格式
访问修饰符 + 数据类型+ this [ 索引类型 index]
{
get
set
}
2.目的:
简化结构体或者类成员的引用 (简化代码),可向数组用下标那样调用成员
4.Vector2的公共函数-Equrls()
Equrls(); // 比较两个向量是否相等
用法 : XX1 . Equals( XX2 );
5,Vector2的静态方法
1.vector2.Angle(); 返回两个向量的夹角
2.vevtor2.Distance(): 返回两个点(向量)的距离
3.Vetor2.Lerp(a , b, t) ;返回两个向量的差值 (二维向量线性差值)
4.Vecor.LerpUnclamped(a,b,t) ; 在 a 与 b 之间按 t 进行线性插值,t 没有限制。
5.Vector2.MoveTowards(a , b,t): t为限制向量的移动步频(可以理解为规定速度移动)、
6.vector2.max();
7.vector2.min();
8.vecotr2.smoothDamp(a,b,v ,t);平滑阻尼,可理解为汽车刹车效果,v为速度是二维向量,t为平滑时间
1,MathF类的静态变量
✅Math和MathF的区别:mathf是unity封装的类它在基于math数学类的基础上添加了适合unity游相关的方法
✅强制类型转换和向下取整&向下取整:除去c#中常用的三个强转 —ceilToInt() 和 FloorInt()
✅钳制函数MathF.clamp()
✅Mathf.sigh()-判断正负
✅Mathf.MoveTowords()——无限接近但不完全相等
✅Mathf.SmoothDamp()——先快后慢
//1.π - PI
//2.取绝对值 - Abs
//3.向上取整 - CeilToInt
//4.向下取整 - FloorToInt
//5.钳制函数 - Clamp
//6.获取最大值 - Max
//7.获取最小值 - Min
//8.一个数的n次幂 - Pow
//9.四舍五入 - RoundToInt
//10.返回一个数的平方根 - Sqrt
//11.判断一个数是否是2的n次 - IsPowerOfTwo
//12.判断正负数 - Sign
1,MathF类的静态变量
2,MathF类的静态函数
print(Mathf.Abs(-1.2f)+ “,-1.2的绝对值”);
print(Mathf.Acos(1)+“,1(以弧度为单位)的反余弦”);
print(Mathf.Floor(2.74f)+“,小于或等于2.74的最大整数”);
print(Mathf.FloorToInt(2.74f)+“,小于或等于2.74的最大整数”);
Mathf.Lerp(1,2,0.5f) ——,a和b按参数t进行线性插值
Mathf.LerpUnclamped(1, 2, -0.5f)——,a和b按参数t进行线性插值
float start = 0;
float result = 0;
float time = 0;
//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);
3,MathF类中的 倒计时 函数
Math.MoveTowards()
void Update()
{
print("游戏倒计时:" + endTime);
endTime = Mathf.MoveTowards(endTime,0,0.1f); //每次减0.01 直到endTime为0
}
弧度转角度
float rad = 1;
float anger = rad * Mathf.Rad2Deg;
角度转弧度
anger = 1;
rad = anger * Mathf.Deg2Rad;
三角函数
//注意:需要加上弧度值
Mathf.Sin(30 * Mathf.Deg2Rad) //0.5
Mathf.Cos(60 * Mathf.Deg2Rad) //0.5
通过反三角函数求弧度
弧度 = Mathf.Asin() / Acos();
反三角函数得到的结果是 正弦或者余弦值对应的弧度
rad = Mathf.Asin(0.5f); //弧度
print(rad * Mathf.Rad2Deg); //角度
练习
【Unity每日一记】让一个物体按余弦曲线移动—(三角函数的简单运用)
位置 + 向量 = 平移位置
位置 - 向量 = 平移位置
位置 - 位置 = 向量
向量 - 位置 = 无意义
向量 * 向量 = 向量
向量 * 值 = 扩大模长
向量之间的距离 ——Vector3.Disrtance() 向量 和向量之间相减 A - B
0向量——Vector.zero()
向量模长——Vector3.magnitude() 相等于向量之间的距离
单位向量——Vector3.normalized()适用于物体移动的时候的单位化计算
向量+向量 和向量+位置 的区别——前者为向量(高数中的向量相加)后者为相当于扩大作用结果是位置
位置-位置的几何意义——结果为向量 ,向量-向量 = 向量
向量的加减乘除 —— 加减应用于物体平移 乘除的进行缩放要用本地坐标
向量的点乘——Vector3.Dot 结果为余弦值,用来判断对象的大概方位(前后)和夹角
向量的叉乘——Vector3.Dot 结果为法向量垂直于两个向量构成的平面,判断(左右)
向量的线性差值运算——直线轨迹
vector3.Lerp( S,E,T); ——S为开始值,E为最终值
①每帧改变S的值(先快后慢)—适合摄像机的跟随
②每帧改变T的值(匀速变化)—适合摄像机的跟随
线性插值
//1.先快后慢 每帧改变start位置 位置无限接近 但不会得到end位置
transform.position = Vector3.Lerp(
transform.position,target.position, Time.deltaTime);
//2.匀速 每帧改变时间 当t>=1时 得到结果
//当time>=1时 改变了目标位置后会直接瞬移到目标位置
if(nowTarget != target.position)
{
nowTarget = target.position;
time = 0;
startPos = B.position;
}
time += Time.deltaTime;
B.position = Vector3.Lerp(startPos, nowTarget, time);
球形插值
C.position = Vector3.Slerp(Vector3.right * 10, Vector3.left * 10 +
Vector3.up*0.1f, time*0.01f);
【Unity每日一记】向量操作摄像机的移动(向量加减)
【Unity每日一记】关于物体(敌方)检测—(向量点乘相关)
【Unity每日一记】方位辨别—向量的叉乘点乘结合
特点
1,绕着某个轴转x度,轴可以是任意轴(轴-角对)
2,避免了欧拉角中万向节死锁的问题
3,避免了欧拉角中角度变化不在(-180,180)范围内的问题
原理公式
假定四元数Q绕着n轴旋转β度
//计算原理_绕x轴旋转60度
Quaternion q = new Quaternion(Mathf.Sin(30 * Mathf.Deg2Rad),
0, 0, Mathf.Cos(30 * Mathf.Deg2Rad));
直接简单公式
//绕x轴旋转60度
Quaternion q = Quaternion.AngleAxis(60, Vector3.right);
API常用
1.四元数和欧拉角转换
欧拉角转四元数
Quaternion A = Quaternion.Euler(60, 0, 0);
四元数转欧拉角
A.eulerAngles
2.旋转
四元数相乘代表旋转四元数
//四元数旋转方法
transform.rotation *= Quaternion.AngleAxis(30,vector3.forword);
3.单位化四元数
Instantiate(XXXX, Vector3.zero, Quaternion.identity);
4.四元数的差值运算
transform.rotation = Quaternion.Slerp(transform.rotation,
target.rotation, Time.deltaTime);
time += Time.deltaTime;
B.transform.rotation = Quaternion.Slerp(start,
target.rotation, time);
5.四元数的旋转看向——LookAt的本质
Quaternion A = Quaternion.LookRotation(B.position - A.position);
//B - A = AB 向量 ,所以传入的是向量
transform.rotation = A;
【Unity每日一记】进行发射,位置相关的方法总结
【Unity每日一记】摄像机相关向量代码API大全
1,随机类的静态变量
随机数int和float
Random.range()/int是左闭右开,float是左闭右闭
①随机出旋转数
Random.rotantion
②随机出的欧拉角
Random.rotation.enluarAngles
③随机出的欧拉角转四元数
Quteronion.luer.( Random.rotation.enluarAngles)
④随机出的浮点数
Random.Vauler 范围是 【0,1)
⑤按图形随机出数字 --应用于枪口的圆形子弹发射(FPS)
Random. insideUnitCircle
在(-1,-1)~(1,1)范围内随机生成的一个vector2")
2.随机类的静态函数
成员变量
名字: this.gameObject.name
是否激活:
this.gameObject.activeSelf
是否是静态
this.gameObject.isStatic
层级
this.gameObject.layer
标签
this.gameObject.tag
创建几何体
GameObject.CreatePrimitive(PrimitiveType.Cube);——正方体
查找——消耗性能
实例化
GameObject.Instantiate(xx);
销毁
GameObject.Destroy(xx)
Destroy方法 本质上给这个对象加了一个移除标 一般情况下 它会在下一帧时把这个对象移除并从内存中移除 如果没有特殊需求 就是一定要马上移除一个对象的话 建议使用上面的 Destroy方法 因为 是异步的 降低卡顿的几率
场景不移除对象
GameObject.DontDestroyOnLoad( xx );
切换场景后物体会被删除,该API对象 过场景不被删除
添加脚本
标签比较
激活失活设置
1,鼠标回调事件函数
private void OnMouseDown()
{
print(“在挂载的物体身上按下了鼠标”);
}
private void OnMouseUp()
{
print(“在挂载的物体身上按下的鼠标抬起了”);
}
private void OnMouseDrag()
{
print(“在挂载的物体身上用鼠标进行了拖拽操作”);
}
private void OnMouseEnter()
{
print(“鼠标移入了挂载的物体”);
}
private void OnMouseExit()
{
print(“鼠标移出了挂载的物体”);
}
private void OnMouseOver()
{
print(“鼠标悬停在了挂载的物体上方”);
}
private void OnMouseUpAsButton()
{
print(“鼠标在挂载的物体身上松开了”);
}
0,相关
1,连续检测(按键,鼠标)
2.连续检测(事件)
手柄相关
得到所有按钮的名字 ——Input.GetJoystickNameS()
if (Input.GetButton(“Fire1”))
{
print(“当前玩家正在使用武器1进行攻击!”);
}
if (Input.GetButton(“Fire2”))
{
print(“当前玩家正在使用武器2进行攻击!”);
}
if (Input.GetButton(“RecoverSkill”))
{
print(“当前玩家使用了恢复技能回血!”);
}
3.间隔检测(事件)
if (Input.GetButtonDown(“Jump”))
{
print(“当前玩家按下跳跃键”);
}
if (Input.GetButtonUp(“Squat”))
{
print(“当前玩家松开蹲下建”);
}
if (Input.GetKeyDown(KeyCode.Q))
{
print(“当前玩家按下Q键”);
}
if (Input.anyKeyDown)
{
print(“当前玩家按下了任意一个按键,游戏开始”);
}
if (Input.GetMouseButton(0))
{
print(“当前玩家按住鼠标左键”);
}
if (Input.GetMouseButtonDown(1))
{
print(“当前玩家按下鼠标右键”);
}
if (Input.GetMouseButtonUp(2))
{
print(“当前玩家抬起鼠标中键(从按下状态松开滚轮)”);
}
玩玩demo可以,实际开发是几乎不能用的。
仅发送消息给自己(以及身上的其他MonoBehaviour对象)
gameObject.SendMessage(“GetMsg”);
SendMessage(“GetSrcMsg”,“BOSS”);
SendMessage(“GetTestMsg”,SendMessageOptions.DontRequireReceiver);
广播消息(向下发,所有子对象包括自己)
BroadcastMessage(“GetMsg”);
向上发送消息(父对象包含自己)
SendMessageUpwards(“GetMsg”);
public void GetMsg()
{
print(“测试对象本身接收到消息了”);
}
public void GetSrcMsg(string str)
{
print(“测试对象本身接收到的消息为:”+str);
}
情况一:
通过按键进行动画的播放
情况二:
和通过参数来进行动画的切换(取消勾选 Has Exit Time)
以标准单位化时间进行淡入淡出效果来播放动画
animator.CrossFade (“Walk” , 0.1f) __值越小过渡的越快
以秒为单位进行淡入淡出效果来播放动画
animator.CrossFadeInFixedTime(“Run”, 0.5f);
1.成员变量
帧间隔时间
transform.Translate(0, 0, Time.deltaTime * 10);
6t//物体沿着自身Z轴方向,每秒移动物体10米运动
完成上一帧所用的时间(以秒为单位
物理帧间隔时间
以下的总时间并不精确,适用于对时间精确不是特别严格的情况
Time.fixedTime + ",表示FixedUpdate(生命周期)已经执行的时间,可以作为自游戏启动以来的总时间(以物理或者其他固定帧率更新的时间间隔累计计算的),基本上是以0.02慢慢累加(有误差)
Time.time + ",游戏开始以来的总时间、
精确时间
Time.time + “,游戏开始以来的总时间”
Time.realtimeSinceStartup + “,游戏开始以来的实际时间”
Time.smoothDeltaTime + ",经过平滑处理的Time.deltaTime的时间
Time.timeSinceLevelLoad + ",自加载上一个关卡以来的时间(进入了新场景后的时间)
时间缩放比例
一共跑了多少帧(多少次循坏)
Time.frameCount
慢动作功能 —时间成员变量
时间流逝的标度,可以用来慢放动作、它的默认值为1,为0.5时可将当前游戏程序中所有时间放慢到原来的0.5倍,若为3 则为原来的三倍
Time.timeScale = 3;
1.协程的定义和用途
协程顾名思义,协同程序
1.延时调用
如果有很多敌人,那么每帧都调用此函数可能会带来很大开销。但是,可以使用协程,每十分之一秒调用一次
协程的定义:
IEnumerator ChangeState() //协程迭代器的定义
{
//暂停几秒(协程挂起)
yield return new WaitForSeconds(2);
//暂停两秒后再切入走路的动画
animator.Play("Walk");`
}
2.和其他逻辑一起协同执行
,比如一些很耗时的工作,在这个协程中执行异步操作,比如下载文件,加载文件,异步生成怪物等
*资源加载一般是一个比较耗时的操作,如果直接放在主线程中会导致游戏卡顿,通常会放到异步线程中去执行。
2.协程的启动和停止
void start()
{
启动方法一:
StartCoroutine("ChangeState"); //括号内的是协程名
启动方法二:
StartCoroutine(ChangeState());
启动方法三: //有参协程只能用该方法开启
IEnumerator ie = ChangeState();
StartCoroutine(ie);
协程停止方法
StopCoroutine("ChangeState");
StopCoroutine(ChangeState());
StopCoroutine(ie);
停止所有协程:
StopAllCoroutines();
}
IEnumerator ChangeState() //协程的定义
{
//暂停几秒(协程挂起)
yield return new WaitForSeconds(2);
//暂停两秒后再切入走路的动画
animator.Play("Walk");`
}
3.协程中的 yield
表示等待一帧
表示等待n秒
表示在本帧帧末执行以下逻辑
IEnumerator ChangeState()
{
//等待一帧 yield return n(n是任意数字)
yield return null;
yield return 100000;
print("转换成Run状态了");
//在本帧帧末执行以下逻辑
yield return new WaitForEndOfFrame();
}
4.协程中的协程和有参协程
StartCoroutine("CreateBoss"); //启动协程
//协程1 功能实时实例化游戏物体
IEnumerator CreateBoss()
{
StartCoroutine(SetCreateCount(5));
while (true) //功能实时实例化游戏物体
{
if (BossNum>=BossCount)
{
yield break; //在协程中break前面要加 yield
}
Instantiate(animator.gameObject);
BossNum++;
yield return new WaitForSeconds(2);
}
}
//协程2 功能实时实例化游戏物体
IEnumerator SetCreateCount(int num)
{
BossCount =num;
yield return null; //暂停一帧
---------------------
此时如果这里只是暂停一帧的话,
那么上面调该有参协程的协程体中,
后面的语句并未生效,因为暂停一帧后,
后面的方法已经执行了,
所以此时的BossCount并不等于有参传递的5
(当然BossCount是全局变量)
---------------------
}
协程的本质
//Ieunmrator接口中的两个成员:MoveNext_移动下一个 Current——当前返回值
while(ie.MoveNext())
{
print(ie.Current);
}
---
# API——invoke延时调用
---
1.延时调用
---
● Invoke(“名字”,秒数)
● InvokeRepeating(“名字”,第一次秒数,之后每次调用间隔秒数)
+ 使用协程的延时调用也可以
+ 使用计时器-MathF.MoveTowords也可以达到延时调用的效果
```csharp
void Start()
{
//调用
//Invoke("CreateGris",3);
InvokeRepeating("CreateGris",1,1);
}
private void CreateGris()
{
Instantiate(grisGo); //实例化
}
2.取消调用
● CancelInvoke(“方法名”);暂停当前延时调用该方法
● CancelInvoke();停止所有的延时调用方法
3.判断是否调用
● IsInvoke(“方法名”);判断当前方法是否进行了延时调用
● IsInvoke();停止程序中所有的延时调用
4,让方法只调用一次的方法
1.常用使物体移动的方法
1,movetowords 和线性差值进行两点间的移动
2,transform.position (利用监听键盘进行实时的位置变化移动)
3,通过刚体进行单向移动(xx.MovePosition)
4,通过刚体的力进行牵引移动 xx.addForce( vector2.方向)
有两个参数的情况
xx.addForce( vector2.方向,ForceMode2D.force 或者 Impuse)
impuse是爆发的瞬时的,应用于爆炸情景
Force则是连续的,,相当于没有第二个参数
方法 | 描述 |
---|---|
Transform.Translate(Vector2.left) | 世界坐标方向 |
Transform.Translate(transform.left) | 自身坐标方向 |
Transform.Translate(Vector2.left,Space.World) | 世界坐标方向 |
Transform.Translate(Vector2.left, Space.Self) | 自身坐标方向 |
Transform.Translate(transform.left ,Space.Self/World) | 自身坐标方向 |
2.细节
1.物理系统相关的API要放进去FixedUpDate
2,受重力影响的程度 gravity Scale
3,阻力 0Linear Drag 线性阻力
常用使物体旋转的方法
通过刚体让物体的旋转( 2D平面用好点)
此时的Rotion并不是四元数 ,在这里就是当前物体的度数
transform组件让物体绕轴旋转(3D立体用好点)
相对于自己的坐标系旋转
this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime);
第一个参数 相当于 是旋转的角度 每一帧
第二个参数 默认不填 就是相对于自己坐标系 进行的旋转
this.transform.Rotate(new Vector3(0, 10, 0) * Time.deltaTime, Space.World);
相对于某个轴 转多少度
this.transform.Rotate(Vector3.right, 10 * Time.deltaTime);
this.transform.Rotate(Vector3.right, 10 * Time.deltaTime, Space.World);
参数一:是相对哪个轴进行转动
参数二:是转动的 角度 是多少
参数三:默认不填 就是相对于自己的坐标系 进行旋转
如果填 可以填写相对于 世界坐标系进行旋转
相对于某一个点转
this.transform.RotateAround(Vector3.zero, Vector3.right, 10 * Time.deltaTime);
参数一:相当于哪一个点 转圈圈
参数二:相对于那一个点的 哪一个轴转圈圈
参数三:转的度数 旋转速度 * 时间
常用操作
AudioSourse组件介绍
![在这里插入图片描述](https://img-blog.csdnimg.cn/255c5e41d54b47769d6140a6a934d608.jpe
Play On Awake 第一次调用就开启
Loop 循环
Pitch 音调
音频源官方手册解释
获取设备麦克风信息
string[] strs = Microphone.devices;
开始录制
clip = Microphone.Start(null, false, 10, 44100);
if( Input.GetKeyDown(KeyCode.Space) )
{
clip = Microphone.Start(null, false, 10, 44100);
}
参数一:设备名 传空使用默认设备
参数二:超过录制长度后 是否重头录制
参数三:录制时长
参数四:采样率
结束录制
Microphone.End(null);
if( Input.GetKeyUp(KeyCode.Space) )
{
Microphone.End(null);
//第一次获取 没有才添加
AudioSource s = this.GetComponent<AudioSource>();
if (s == null)
s = this.gameObject.AddComponent<AudioSource>();
s.clip = clip;
s.Play();
#region 知识点四 获取音频数据用于存储或者传输
//规则 用于存储数组数据的长度 是用 声道数 * 剪辑长度
float[] f = new float[clip.channels * clip.samples];
clip.GetData(f, 0);
print(f.Length);
#endregion
}
基本参数
碰撞到的对象碰撞器的信息
collision.collider
碰撞对象的依附对象(GameObject)
collision.gameObject
碰撞对象的依附对象的位置信息
collision.transform
触碰点数
collision.contactCount
接触点 具体的坐标
ContactPoint[] pos = collision.contacts;
碰撞器
触发器
触发器是碰撞器中的一部分 开启与否 直接按碰撞器组件上的触发器开关即可
onTiggerEnter ( collision2D xx ) 当物体进入到本身的碰撞区时触发
onTriggerStay( collision2D xx ) 当物体呆在本身的碰撞区域时触发
onTriggerExit( colidion2D xx ) 当物体离开 本身的碰撞区域时触发
✌️种类
box,胶囊,球形,车轮,网格,地形
✌️物理材质
✌️碰撞函数
1.Resources 可读 不可写 打包后找不到
2.Application.streamingAssetsPath 可读 PC端可写 找得到
3.Application.dataPath 打包后找不到
4.Application.persistentDataPath 可读可写找得到
1.工程路径获取
该方式 获取到的路径 一般情况下 只在 编辑模式下使用
游戏发布过后 该路径就不存在了
2.Resources资源文件夹
一般不获取路径只能使用Resources相关API进行加载
3.StreamingAssets 流动资源文件夹
4.persistentDataPath 持久数据文件夹
注意:
不需要手动创建
Application.persistentDataPath
不同平台路径不一样
作用:
固定数据文件夹
1.所有平台都可读可写
2.一般用于放置动态下载或者动态创建的文件,游戏中创建或者获取的文件都放在其中(热更新会用到)
5.Plugins 插件文件夹
6. Editor 编辑器文件夹
7. 默认资源文件夹 Standard Assets
注意:
手动创建
作用:
默认资源文件夹
一般Unity自带资源都放在这个文件夹下
代码和资源优先被编译
一般不用
——————— 同步加载———————
5种资源加载的方式,Resource加载介绍
资源加载适用于需要加载资源较多的 情况就不用一个一个的拖拽进去
关键字:@ ,as
卸载AB包的方法: Resource. UnLoadAsset
void Start()
{
Object obj= Resources.Load("sound");
//AudioClip ac = obj as AudioClip;
AudioClip ac = (AudioClip)obj;
AudioSource.PlayClipAtPoint(ac, transform.position);
//Resources.LoadAll("Prefabs");
AudioClip[] audioClips= Resources.LoadAll<AudioClip>("");
foreach (var item in audioClips)
{
Debug.Log(item);
}
//Resources.UnloadAsset
}
C#中的回收机制是系统自动回收的,有多种回收机制,不像其他语言需要手动回收
注意:
//预设体对象加载需要实例化
//其它资源加载一般直接用
#endregion
Resource资源加载操作
加载资源前首先需要在project面板中创建Resource名字的文件夹,为固定文件夹用于资源加载
以加载AudioClip类型的资源为例:
Object obj = Resources.Load("Cube");
Instantiate(obj);
Object obj3 = Resources.Load("Music/BKMusic");
//我们不需要实例化 音效切片 我们只需要把数据 赋值到正确的脚本上即可
audioS.clip = obj3 as AudioClip;
audioS.Play();
文本资源支持的格式——.txt .xml .bytes .json .html .csv …
TextAsset ta = Resources.Load("Txt/Test") as TextAsset;
//文本内容
ta.text
//字节数据组
ta.bytes);
tex = Resources.Load("Tex/TestJPG") as Texture;
——————— 异步加载———————
如果我们加载过大的资源可能会造成程序卡顿
异步加载 就是内部新开一个线程进行资源加载 不会造成主线程卡顿
异步加载 不能马上得到加载的资源 至少要等待一帧
直接异步加载——适用于加载单个资源
//通过事件监听
ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG")
rq.completed += LoadOver;
//completed 是 ResourceRequest 中的委托
// AsyncOperation 是 ResourceRequest 的父类
private void LoadOver( AsyncOperation rq)
{
//在事件中添加结束标识逻辑,这样我们就知道异步加载完成了
print("加载结束");
//加载完成后 会保存在 ResourceRequest类中的 asset Object类型成员里
//此时实现赋值
picture = (rq as ResourceRequest).asset as Texture;
}
配套协程异步加载——适用于加载多个资源
//通过协程的调度器自己判断是否加载结束
StartCoroutine(Load());
IEnumerator Load()
{
ResourceRequest rq = Resources.LoadAsync<Texture>("Tex/TestJPG");
yield return rq;
// yield return rq会自己判断 该资源是否加载完毕了,加载完毕过后才继续执行后面的代码 ,因为ResourceRequest 也是YieldInstruction的子类
//-------------------------------
//isDone 和 progress API的应用
while(!rq.isDone)
{
//打印当前的 加载进度
print(rq.progress);
yield return null;
}
//--------------------------------
picture = rq.asset as Texture;
}
———————资源加载器———————
利用异步直接加载和委托的使用构成简单的资源加载器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
//-------------------------------------
//—————————————————————————————————————
//___________项目: ______________
//___________功能: 简单的资源管理器
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class ResourcesControl
{
static private ResourcesControl control;
static public ResourcesControl Control => control;
private ResourcesControl()
{
}
public void AddResources<T>(string name ,UnityAction<T> source ) where T : Object
{
ResourceRequest yb = Resources.LoadAsync<T>(name);
yb.completed += (reO) =>
{
source( (reO as ResourceRequest).asset as T );
};
}
}
//外部调用
private void Start()
{
GameObject shootball;
ResourcesControl.Control.AddResources<GameObject>("Profabs/ball",(sphere)=> {
shootball = sphere;
} );
}
———————卸载资源———————
Resources多次重复加载不会浪费内存
但是 会浪费性能(每次加载都会去查找取出,始终伴随一些性能消耗)
1.卸载指定资源
Resources.UnloadAsset 方法
注意:
它只能用于一些 不需要实例化的内容 比如 图片 和 音效 文本等
一般情况下很少单独使用它
2.卸载未使用的资源
一般在过场景时和GC一起使用
Resources.UnloadUnusedAssets();
GC.Collect();
常用
当前屏幕分辨率
屏幕窗口当前宽高
屏幕休眠模式
Screen.sleepTimeout = SleepTimeout.NeverSleep;
不常用
运行时是否全屏模式
移动设备屏幕转向相关
允许自动旋转为左横向 Home键在左
Screen.autorotateToLandscapeLeft = true;
允许自动旋转为右横向 Home键在右
Screen.autorotateToLandscapeRight = true;
允许自动旋转到纵向 Home键在下
Screen.autorotateToPortrait = true;
允许自动旋转到纵向倒着看 Home键在上
Screen.autorotateToPortraitUpsideDown = true;
指定屏幕显示方向
Screen.orientation = ScreenOrientation.Landscape;
静态方法
设置分辨率 移动设备不常用
Screen.SetResolution(1920, 1080, false);
加载场景的方法
SceneManasger的操作
首先添加场景加载的命名空间Using UnityEngine.SceneManagement ;
而后把游戏场景都保存(拖拽)在 Buid setting 里面,相当于存储场景的目录
1.同步加载
SceneManager.Load( 序列号) ;
SceneManager.Load( “场景名”) ;
void Start()
{
//SceneManager.LoadScene(1);
//SceneManager.LoadScene("TriggerTest");
}
缺点:加载时造成画面卡帧,因为,在未加载完成前画面是停止的,所以是卡帧现象
2.异步加载
如果当前场景 对象过多或者下一个场景对象过多
这个过程会非常的耗时 会让玩家感受到卡顿
所以异步切换就是来解决该问题的
通常我们和协程一起使用:
SceneManager.LoadAsync(序列号)
SceneManager.LoadAsync(“场景名”)
StartCoroutine(协程迭代器方法() ); //调用协程
AsyncOperation 该类型翻译为异步操作 ,为下面获得异步场景的返回值
AsyncOperation ao= SceneManager.LoadSceneAsync(2);
ao.allowSceneActivation = true 激活场景
ao.progress 场景加载的进度
//-----1.通过事件回调函数 异步加载------
AsyncOperation SS = SceneManager.LoadSceneAsync("XXXX");
SS.completed += (a) =>
{
print("加载结束");
};
SS.completed += LoadOver;
private void LoadOver(AsyncOperation ao)
{
print("LoadOver");
}
//---------2.通过协程异步加载--------
void Start()
{
//由于场景加载后就不会执行加载后的逻辑了,如果要保存就使用 DontDestroyOnLoad(保留场景加载上个场景的东西)第一个异步方法不会出现该情况
DontDestroyOnLoad(this.gameObject);
StartCoroutine(LoadScene("XXXX"));
}
IEnumerator LoadScene(string name)
{
AsyncOperation SS= SceneManager.LoadSceneAsync(name);
//根据游戏规则 自定义进度条变化的条件
yield return SS;
//1.场景加载结束 更新20%
//2.动态加载怪物再更新20%
//3.动态加载场景模型进度条顶满
//4.加载结束隐藏进度条
}
总结
场景异步加载 和 资源异步加载 一样
1.通过事件回调函数
2.协程异步加载
1.事件回调函数
优点:写法简单,逻辑清晰
缺点:只能加载完场景做一些事情 不能在加载过程中处理逻辑
2.协程异步加载
优点:可以在加载过程中处理逻辑,比如进度条更新等
缺点:写法较为麻烦,要通过协程
场景管理器
public class SceneControl
{
private static SceneControl instance = new SceneControl();
public static SceneControl Instance => instance;
private SceneControl() { }
public void LoadScene(string name, UnityAction action)
{
AsyncOperation SS = SceneControl.LoadSceneAsync(name);
SS.completed += (Scene) =>
{
action();
};
}
}
---
# API——光源组件
---
---
组件API --window -light
---
☑️**三光——点光源,聚光灯,面光源(烘培模式开启)**--烘培-节约性能
![在这里插入图片描述](https://img-blog.csdnimg.cn/2c324fa90734437a8e08c31c906c45c6.png)
☑️**光源模式**——实时,烘培,混合
![在这里插入图片描述](https://img-blog.csdnimg.cn/f9291e067e6548719eb752eb68bc38d8.png)
☑️**颜色**——光源颜色
![在这里插入图片描述](https://img-blog.csdnimg.cn/c104ae51251d4559960159d8c93b60e1.png)
☑️**阴影**——生硬,柔和——效率区别
-![在这里插入图片描述](https://img-blog.csdnimg.cn/6a14d759b674492cad3d57410797edb9.png)
☑️**投影遮罩**——只适用聚光灯,需添加Textuer
![在这里插入图片描述](https://img-blog.csdnimg.cn/1895321bae724dbf89bbaf4faa5b9d1d.png)
☑️**光晕开关 + 耀斑(聚光)**—— 前者是球形光(太阳蜡烛) 后者是人眼看到强光的效果 (耀斑有其对应的材质)
![在这里插入图片描述](https://img-blog.csdnimg.cn/ebd432f28c3a401f9b2fdb38bdba0786.png)
---
光设置面板界面 --window -light
---
**针对设置光源参数的默认值**
☑️**天空盒材质的更换**
☑️**太阳光源的设置**
☑️**Fog雾开关**——雾面效果,性能消耗
☑️**耀斑的调节**
☑️**遮罩材质的更改**
![在这里插入图片描述](https://img-blog.csdnimg.cn/bdc3b280d6374766a9f92e4a4ce65983.png)
---
# API——刚体相关
---
> **添加力的方法**
+ 1.获取
rigidBody = this.GetComponent<Rigidbody>();
+ 2.添加力
rigidBody.AddForce(Vector3.forward * 10);
相对世界坐标世界坐标系 Z轴正方向加了一个里加力过后 对象是否停止移动 是由阻力决定的如果阻力为0 那给了一个力过后 始终 是不会停止运动
+ 3. 让对象 相对于自己的面朝向动
相对世界坐标
rigidBody.AddForce(this.transform.forward * 10);
相对本地坐标
rigidBody.AddRelativeForce(Vector3.forward * 10);
>**添加扭矩力,让其旋转**
+ 相对世界坐标
rigidBody.AddTorque(Vector3.up * 10);
+ 相对本地坐标
rigidBody.AddRelativeTorque(Vector3.up * 10);
>**改变速度**
速度方向 是相对于 世界坐标系的
rigidBody.velocity = Vector3.forward * 5;
如果要直接通过改变速度 来让其移动 一定要注意这一点
>.**模拟爆炸效果**
rigidBody.AddExplosionForce(100, Vector3.zero, 10);
模拟爆炸的力 一定是 所有希望产生爆炸效果影响的对象 都需要得到他们的刚体 来执行这个方法 才能都有效果
>**力的几种模式**
力的模式 主要的作用 就是 计算方式不同而已
由于计算方式的不同 最终的移动速度就会不同
+ rigidBody.AddForce(Vector3.forward * 10,ForceMode.Acceleration);
|字符 | 意义 |
|--|--|
| F |力 |
| t |时间|
| m |质量 |
| v |速度 |
| 动量定理 |Ft = mv v = Ft/m; |
+ **1.Acceleration**
给物体增加一个持续的加速度,忽略其质量
|字符 | 值 |
|--|--|
| F |(0,0,10) |
| t |0.02s|
| m |默认为1|
| v |10*0.02/ 1 = 0.2m/s|
| 每物理帧移动 |0.2m/s*0.02 = 0.004m |
+ **2.Force**
给物体添加一个持续的力,与物体的质量有关
|字符 | 值 |
|--|--|
| F |(0,0,10) |
| t |0.02s|
| m |2kg|
| v |10*0.02/ 2 = 0.1m/s|
| 每物理帧移动 |0.1m/s*0.02 = 0.002m |
+ **3.Impulse**
给物体添加一个瞬间的力,与物体的质量有关,忽略时间 默认为1
|字符 | 值 |
|--|--|
| F |(0,0,10) |
| t |0.01s|
| m |2kg|
| v |10*1/ 2 = 5m/s
| 每物理帧移动 |5m/s*0.02 = 0.1m |
+ **4.VelocityChange**
|字符 | 值 |
|--|--|
| F |(0,0,10) |
| t |1s|
| m |1kg|
| v |v = 10*1/ 1 = 10m/s
| 每物理帧移动 |10m/s*0.02 = 0.2m |
> **刚体是否休眠**
+ rigidBody.IsSleeping())
+ rigidBody.WakeUp();——唤醒刚体
---
# API——Camera组件
---
>**可编辑参数了解**
+ **Clear Flags**
![在这里插入图片描述](https://img-blog.csdnimg.cn/448e3e0fd0b9479d8d25694db396db6b.png)
+ **CullingMask选择层级进行渲染**
+ **Projection**
![在这里插入图片描述](https://img-blog.csdnimg.cn/a2751952d5974169bc66869d068cd8ab.png)
+ **Target Texture 小地图应用**
+ **Occlusion Culing 的勾选 优化性能 减少渲染**
+ **渲染分辨率的设置了解** --性能相关
+ **分屏操作 viewport Rect** --应用于双人成行类的游戏
>API
![在这里插入图片描述](https://img-blog.csdnimg.cn/e3c601ca24d545b3a2c5092cdb267e49.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/39f986ab8d0e420b96919ec4325b2579.png)
> **渲染相关委托**
```cpp
//摄像机剔除前处理的委托函数
Camera.onPreCull += (c) =>
{
};
//摄像机 渲染前处理的委托
Camera.onPreRender += (c) =>
{
};
//摄像机 渲染后 处理的委托
Camera.onPostRender += (c) =>
{
};
常用坐标转化
设置主摄像机对象 上的深度
Camera.main.depth = 10;
世界坐标转屏幕坐标
z对应的 是3D物体离摄像机的距离
Vector3 v = Camera.main.WorldToScreenPoint(this.transform.position);
Vector3 pos = Input.mousePosition;
pos.z = 5;
obj.position = Camera.main.ScreenToWorldPoint(pos);
//改变Z轴 是因为 如果不改 Z默认为0转换过去的世界坐标系的点 永远都是一个点 可以理解为 视口 相交的焦点如果改变了Z 那么转换过去的 世界坐标的点 就是相对于 摄像机前方多少的单位的横截面上的世界坐标点
应用
1.LineRenderer是什么
线渲染器 (Line Renderer)官方文档
LineRenderer是Unity提供的一个用于画线的组件来在场景中绘制线段
一般可以用于
2.LineRenderer相关API
代码动态添加一个线段
GameObject line = new GameObject();
line.name = "Line";
LineRenderer lineRenderer = line.AddComponent();
首尾相连
lineRenderer.loop = true;
开始结束宽
lineRenderer.startWidth = 0.02f;
lineRenderer.endWidth = 0.02f;
开始结束颜色
lineRenderer.startColor = Color.white;
lineRenderer.endColor = Color.red;
设置材质
m = Resources.Load<Material>("XXX");
lineRenderer.material = m;
lineRenderer.SetPositions(new Vector3[] { new Vector3(0,0,0),
new Vector3(0,0,5),
new Vector3(5,0,5)});
lineRenderer.SetPosition(3, new Vector3(5, 0, 0));
是否使用世界坐标系
//决定了 是否随对象移动而移动
lineRenderer.useWorldSpace = false;
让线段受光影响 会接受光数据 进行着色器计算
lineRenderer.generateLightingData = true;
特点:
共同参数:
UseGlobal-使用全局设置在该界面中已默认
1.方块状范围检测
Collider[] colliders = Physics.OverlapBox( Vector3.zero, Vector3.one,
Quaternion.AngleAxis(45, Vector3.up),
1 << LayerMask.NameToLayer("UI") |
1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
if(Physics.OverlapBoxNonAlloc(Vector3.zero, Vector3.one, 自定义数组名) != 0)
2.球形状范围检测
无角度参数
参数二为球半径
colliders = Physics.OverlapSphere(Vector3.zero, 5, 1 << LayerMask.NameToLayer("Default"));
if( Physics.OverlapSphereNonAlloc(Vector3.zero, 5, colliders) != 0 )
.3.胶囊体范围检测
参数一:半圆一中心点
参数二:半圆二中心点
参数三:半圆半径
colliders = Physics.OverlapCapsule(Vector3.zero, Vector3.up, 1, 1 << LayerMask.NameToLayer("UI"), QueryTriggerInteraction.UseGlobal);
if ( Physics.OverlapCapsuleNonAlloc(Vector3.zero, Vector3.up, 1, colliders ) != 0 )
特点
只需要判断一条线和物体的碰撞情况
可以在指定点发射一个指定方向的射线
判断该射线与哪些碰撞器相交,得到对应对象
瞬时
应用场景
1.鼠标选择场景上一物体
2.FPS射击游戏(无弹道-不产生实际的子弹对象进行移动)等
API
参数一 | 参数二 |
---|---|
起点 | 方向 |
X.origin | X.direction |
Ray XX = Camera.main.ScreenPointToRay(Input.mousePosition);
屏幕视口坐标转成射线——鼠标点击的地方变成射线
Physics.Raycast 无法检测碰到了谁,只会检测碰到了没有
最多有16个重载
Physics.Raycast常用参数 | 作用 |
---|---|
参数一 | 射线 |
参数二 | 检测的最大距离 超出这个距离不检测 |
参数三 | 检测指定层级(不填检测所有层) |
参数四 | 是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal |
返回值 | bool 当碰撞到对象时 返回 true 没有 返回false |
//第一种写法
Physics.Raycast(XX, 1000,
1 << LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal )
//第二种写法
Physics.Raycast(Vector3.right, Vector3.forward,
1 << LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal )
RaycastHit 在Physics.Raycast的应用 | 作用 |
---|---|
参数一 | 射线 |
参数二 | out RaycastHit 为什么是out ?RaycastHit是结构体 是值类型 out加上去就变成了引用类型,而RaycastHit没有复制所以不用ref |
参数三 | 检测的最大距离 超出这个距离不检测 |
参数四 | 检测指定层级(不填检测所有层) |
参数五 | 是否忽略触发器 UseGlobal-使用全局设置 Collide-检测触发器 Ignore-忽略触发器 不填使用UseGlobal |
返回值 | bool 当碰撞到对象时 返回 true 没有 返回false |
//写法一
RaycastHit YY;
if( Physics.Raycast(XX, out YY, 1000,
1<<LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal) )
//写法二
if( Physics.Raycast(Vector3.right, Vector3.forward, out YY, 1000,
1<<LayerMask.NameToLayer("层级名字"),
QueryTriggerInteraction.UseGlobal) )
特点: 先碰到的在数组的后面
if((r3, XX, 1000, 1 << LayerMask.NameToLayer("Monster"),
QueryTriggerInteraction.UseGlobal) > 0 )
{
}
【Unity每日一记】模仿FPS射击,用弹痕作画的原理如此简单
【Unity每日一记】拖拽放置类游戏的行为原来和这个API有关
1.中文显示乱码现象的解决措施
2.版本中存在老包升级情况
3.printf 和 Debug.Log的区别
(1)printf : 必须要继承,Monobehivar类
(2)Debug.Log:
1.Debug.LogWarning :显示警告、
2.Debug.LogError:显示错误
⭐相关文章⭐
———————————————————
-本站最全-unity常用API大全(万字详解),不信你不收藏
-关于游戏剧情模式中用到的基础简单API
-控制游戏人物移动的细节到底有多少?
-坦克炮管旋转发射炮弹(向量基础,射线碰撞,物体实例化)
-基于unity物体定点移动与模拟刹车的细节 GIF 图文详解
————————————————————
⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
你们的点赞 收藏⭐ 留言 关注✅是我持续创作,输出优质内容的最大动力!